feat(provenance): importer sets image_record.artist_id, stops minting artist tags
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -27,10 +27,7 @@ from ..models import (
|
||||
ImportSettings,
|
||||
Post,
|
||||
Source,
|
||||
Tag,
|
||||
TagKind,
|
||||
)
|
||||
from ..models.tag import image_tag
|
||||
from ..utils.paths import derive_subdir, derive_top_level_artist, hash_suffixed_name
|
||||
from ..utils.phash import compute_phash, find_similar
|
||||
from ..utils.sidecar import find_sidecar, parse_sidecar
|
||||
@@ -244,7 +241,7 @@ class Importer:
|
||||
artist = None
|
||||
artist_name = derive_top_level_artist(source, self.import_root)
|
||||
if artist_name:
|
||||
artist = self._attach_artist_tag(record.id, artist_name)
|
||||
artist = self._attach_artist(record, artist_name)
|
||||
|
||||
# Sidecar provenance (best-effort; never fails the import).
|
||||
self._apply_sidecar(record, source, artist)
|
||||
@@ -266,33 +263,15 @@ class Importer:
|
||||
self.session.flush()
|
||||
return artist
|
||||
|
||||
def _attach_artist_tag(self, image_id: int, artist_name: str) -> Artist:
|
||||
"""Idempotently creates Artist + artist tag, attaches to image.
|
||||
Returns the Artist (sidecar provenance attaches its Source to it)."""
|
||||
def _attach_artist(self, record: ImageRecord, artist_name: str) -> Artist:
|
||||
"""Upsert the Artist and set it as the image's canonical artist.
|
||||
Artist-kind tags were retired in FC-2d-vii-c — the Artist row is
|
||||
the single source of truth. Returns the Artist (sidecar
|
||||
provenance attaches its Source to it)."""
|
||||
artist = self._upsert_artist(artist_name)
|
||||
|
||||
tag = self.session.execute(
|
||||
select(Tag).where(Tag.name == artist_name).where(Tag.kind == TagKind.artist)
|
||||
).scalar_one_or_none()
|
||||
if tag is None:
|
||||
tag = Tag(name=artist_name, kind=TagKind.artist)
|
||||
self.session.add(tag)
|
||||
if record.artist_id is None:
|
||||
record.artist_id = artist.id
|
||||
self.session.flush()
|
||||
|
||||
# Idempotent association; using a raw insert + on-conflict-do-nothing
|
||||
# is cleaner here than fetching first, but for a sync session we just
|
||||
# check existence.
|
||||
already = self.session.execute(
|
||||
select(image_tag.c.tag_id)
|
||||
.where(image_tag.c.image_record_id == image_id)
|
||||
.where(image_tag.c.tag_id == tag.id)
|
||||
).scalar_one_or_none()
|
||||
if already is None:
|
||||
self.session.execute(
|
||||
image_tag.insert().values(
|
||||
image_record_id=image_id, tag_id=tag.id, source="auto",
|
||||
)
|
||||
)
|
||||
return artist
|
||||
|
||||
@staticmethod
|
||||
@@ -339,6 +318,9 @@ class Importer:
|
||||
)
|
||||
return
|
||||
|
||||
if record.artist_id is None:
|
||||
record.artist_id = artist.id
|
||||
|
||||
platform = sd.platform or "unknown"
|
||||
url = sd.post_url or f"sidecar:{platform}"
|
||||
src = self.session.execute(
|
||||
|
||||
Reference in New Issue
Block a user