Document ArtistState

This commit is contained in:
Šarūnas Nejus 2026-01-10 02:28:18 +00:00 committed by Henry
parent 7d83a68bdd
commit 5523ca94a2

View file

@ -127,7 +127,23 @@ class TracklistInfo(TypedDict):
@dataclass
class ArtistState:
"""Represent Discogs artist credits.
This object centralizes the plugin's policy for which Discogs artist fields
to prefer (name vs. ANV), how to treat 'Various', how to format join
phrases, and how to separate featured artists. It exposes both per-artist
components and fully joined strings for common tag targets like 'artist' and
'artist_credit'.
"""
class ValidArtist(NamedTuple):
"""A normalized, render-ready artist entry extracted from Discogs data.
Instances represent the subset of Discogs artist information needed for
tagging, including the join token following the artist and whether the
entry is considered a featured appearance.
"""
id: str
name: str
credit: str
@ -135,9 +151,14 @@ class ArtistState:
is_feat: bool
def get_artist(self, property_name: str) -> str:
return getattr(self, property_name) + (
{",": ", ", "": ""}.get(self.join, f" {self.join} ")
)
"""Return the requested display field with its trailing join token.
The join token is normalized so commas become ', ' and other join
phrases are surrounded with spaces, producing a single fragment that
can be concatenated to form a full artist string.
"""
join = {",": ", ", "": ""}.get(self.join, f" {self.join} ")
return f"{getattr(self, property_name)}{join}"
raw_artists: list[Artist]
use_anv: bool
@ -147,25 +168,38 @@ class ArtistState:
@property
def info(self) -> ArtistInfo:
"""Expose the state in the shape expected by downstream tag mapping."""
return {k: getattr(self, k) for k in ArtistInfo.__annotations__} # type: ignore[return-value]
def strip_disambiguation(self, text: str) -> str:
"""Removes discogs specific disambiguations from a string.
Turns 'Label Name (5)' to 'Label Name' or 'Artist (1) & Another Artist (2)'
to 'Artist & Another Artist'. Does nothing if strip_disambiguation is False."""
"""Strip Discogs disambiguation suffixes from an artist or label string.
This removes Discogs-specific numeric suffixes like 'Name (5)' and can
be applied to multi-artist strings as well (e.g., 'A (1) & B (2)'). When
the feature is disabled, the input is returned unchanged.
"""
if self.should_strip_disambiguation:
return DISAMBIGUATION_RE.sub("", text)
return text
@cached_property
def valid_artists(self) -> list[ValidArtist]:
"""Build the ordered, filtered list of artists used for rendering.
The resulting list normalizes Discogs entries by:
- substituting the configured 'Various Artists' name when Discogs uses
'Various'
- choosing between name and ANV according to plugin settings
- excluding non-empty roles unless they indicate a featured appearance
- capturing join tokens so the original credit formatting is preserved
"""
va_name = config["va_name"].as_str()
return [
self.ValidArtist(
str(a["id"]),
self.strip_disambiguation(anv if self.use_anv else name),
self.strip_disambiguation(anv if self.use_credit_anv else name),
a["join"],
a["join"].strip(),
is_feat,
)
for a in self.raw_artists
@ -181,29 +215,42 @@ class ArtistState:
@property
def artists_ids(self) -> list[str]:
"""Return Discogs artist IDs for all valid artists, preserving order."""
return [a.id for a in self.valid_artists]
@property
def artist_id(self) -> str:
"""Return the primary Discogs artist ID."""
return self.artists_ids[0]
@property
def artists(self) -> list[str]:
"""Return the per-artist display names used for the 'artist' field."""
return [a.name for a in self.valid_artists]
@property
def artists_credit(self) -> list[str]:
"""Return the per-artist display names used for the credit field."""
return [a.credit for a in self.valid_artists]
@property
def artist(self) -> str:
"""Return the fully rendered artist string using display names."""
return self.join_artists("name")
@property
def artist_credit(self) -> str:
"""Return the fully rendered artist credit string."""
return self.join_artists("credit")
def join_artists(self, property_name: str) -> str:
"""Render a single artist string with join phrases and featured artists.
Non-featured artists are concatenated using their join tokens. Featured
artists are appended after the configured 'featured' marker, preserving
Discogs order while keeping featured credits separate from the main
artist string.
"""
non_featured = [a for a in self.valid_artists if not a.is_feat]
featured = [a for a in self.valid_artists if a.is_feat]