diff --git a/core/artist_source_lookup.py b/core/artist_source_lookup.py index 72888af2..507d09e6 100644 --- a/core/artist_source_lookup.py +++ b/core/artist_source_lookup.py @@ -36,6 +36,7 @@ SOURCE_ID_FIELD = { "discogs": "discogs_id", "hydrabase": "soul_id", "musicbrainz": "musicbrainz_id", + "amazon": "amazon_id", } @@ -58,18 +59,19 @@ def find_library_artist_for_source( Returns ``None`` on miss or on any database error. """ column = SOURCE_ID_FIELD.get(source) + if not column: + return None try: with database._get_connection() as conn: cursor = conn.cursor() - if column: - cursor.execute( - f"SELECT id, name FROM artists WHERE {column} = ? LIMIT 1", - (str(source_artist_id),), - ) - row = cursor.fetchone() - if row: - return row[0] + cursor.execute( + f"SELECT id, name FROM artists WHERE {column} = ? LIMIT 1", + (str(source_artist_id),), + ) + row = cursor.fetchone() + if row: + return row[0] if artist_name and active_server: cursor.execute( diff --git a/database/music_database.py b/database/music_database.py index dc3b7a80..0ea632f3 100644 --- a/database/music_database.py +++ b/database/music_database.py @@ -407,6 +407,9 @@ class MusicDatabase: # Add Discogs enrichment columns (migration) self._add_discogs_columns(cursor) + # Add Amazon artist ID column (migration) + self._add_amazon_columns(cursor) + # Backfill match_status for rows that already have an external ID but # NULL status. Prevents enrichment workers from re-processing these # rows forever. Must run AFTER all *_match_status columns have been @@ -2035,6 +2038,18 @@ class MusicDatabase: except Exception as e: logger.error(f"Error adding Discogs columns: {e}") + def _add_amazon_columns(self, cursor): + """Add Amazon artist ID column to artists table.""" + try: + cursor.execute("PRAGMA table_info(artists)") + artists_columns = [column[1] for column in cursor.fetchall()] + if 'amazon_id' not in artists_columns: + cursor.execute("ALTER TABLE artists ADD COLUMN amazon_id TEXT") + cursor.execute("CREATE INDEX IF NOT EXISTS idx_artists_amazon_id ON artists (amazon_id)") + logger.info("Amazon columns added/verified successfully") + except Exception as e: + logger.error(f"Error adding Amazon columns: {e}") + def _backfill_match_status_for_existing_ids(self, cursor): """Set `_match_status = 'matched'` for rows that already have a populated external ID but NULL match_status. diff --git a/tests/metadata/test_artist_source_lookup.py b/tests/metadata/test_artist_source_lookup.py index 7e803d70..32c03cb6 100644 --- a/tests/metadata/test_artist_source_lookup.py +++ b/tests/metadata/test_artist_source_lookup.py @@ -31,6 +31,7 @@ EXPECTED_SOURCE_ID_FIELD = { "discogs": "discogs_id", "hydrabase": "soul_id", "musicbrainz": "musicbrainz_id", + "amazon": "amazon_id", } @@ -68,11 +69,11 @@ class TestSourceIdFieldMapping: "(and the test body) to match." ) - def test_source_only_set_contains_all_mapped_sources(self): - """Every source with a SOURCE_ID_FIELD column must also be in - SOURCE_ONLY_ARTIST_SOURCES. The reverse is not required — sources - without a DB column (e.g. amazon) use name-based lookup only.""" - assert frozenset(SOURCE_ID_FIELD.keys()).issubset(SOURCE_ONLY_ARTIST_SOURCES) + def test_source_only_set_matches_mapping_keys(self): + """Sources eligible for the source-only fallback must all have a + column to look them up by — otherwise the upgrade path silently + returns None.""" + assert SOURCE_ONLY_ARTIST_SOURCES == frozenset(SOURCE_ID_FIELD.keys()) def test_every_mapped_column_exists_on_artists_table(self, db): """Regression for the 2026-04 ``deezer_artist_id`` typo: every column