Refactor date parsing

This commit is contained in:
Šarūnas Nejus 2026-01-23 09:41:52 +00:00
parent f0d712e8c5
commit 3318b539a8
No known key found for this signature in database
2 changed files with 51 additions and 57 deletions

View file

@ -172,28 +172,21 @@ def _preferred_release_event(release: Release) -> tuple[str | None, str | None]:
return release.get("country"), release.get("date")
def _set_date_str(
info: beets.autotag.hooks.AlbumInfo,
date_str: str,
original: bool = False,
) -> None:
"""Given a (possibly partial) YYYY-MM-DD string and an AlbumInfo
object, set the object's release date fields appropriately. If
`original`, then set the original_year, etc., fields.
"""
if date_str:
date_parts = date_str.split("-")
for key in ("year", "month", "day"):
if date_parts:
date_part = date_parts.pop(0)
try:
date_num = int(date_part)
except ValueError:
continue
def _get_date(date_str: str) -> tuple[int | None, int | None, int | None]:
"""Parse a partial `YYYY-MM-DD` string into numeric date parts.
if original:
key = f"original_{key}"
setattr(info, key, date_num)
Missing components are returned as `None`. Invalid components are ignored.
"""
if not date_str:
return None, None, None
parts = list(map(int, date_str.split("-")))
return (
parts[0] if len(parts) > 0 else None,
parts[1] if len(parts) > 1 else None,
parts[2] if len(parts) > 2 else None,
)
def _merge_pseudo_and_actual_album(
@ -528,16 +521,20 @@ class MusicBrainzPlugin(MusicBrainzAPIMixin, MetadataSourcePlugin):
albumtypes.append(sec_type.lower())
info.albumtypes = albumtypes
info.original_year, info.original_month, info.original_day = _get_date(
release["release_group"]["first_release_date"]
)
# Release events.
info.country, release_date = _preferred_release_event(release)
release_group_date = release["release_group"].get("first_release_date")
if not release_date:
# Fall back if release-specific date is not available.
release_date = release_group_date
if release_date:
_set_date_str(info, release_date, False)
_set_date_str(info, release_group_date, True)
info.year, info.month, info.day = (
_get_date(release_date)
if release_date
else (
info.original_year,
info.original_month,
info.original_day,
)
)
# Label name.
if release.get("label_info"):

View file

@ -64,7 +64,7 @@ class MusicBrainzTestCase(BeetsTestCase):
@staticmethod
def _make_release(
date_str="2009",
date="2009",
recordings=None,
track_length=None,
track_artist=False,
@ -79,7 +79,7 @@ class MusicBrainzTestCase(BeetsTestCase):
"disambiguation": "R_DISAMBIGUATION",
"release_group": {
"primary_type": "Album",
"first_release_date": date_str,
"first_release_date": date,
"id": "RELEASE GROUP ID",
"disambiguation": "RG_DISAMBIGUATION",
},
@ -209,7 +209,7 @@ class MusicBrainzTestCase(BeetsTestCase):
class MBAlbumInfoTest(MusicBrainzTestCase):
def test_parse_release_with_year(self):
release = self._make_release("1984")
release = self._make_release(date="1984")
d = self.mb.album_info(release)
assert d.album == "ALBUM TITLE"
assert d.album_id == "ALBUM ID"
@ -220,12 +220,12 @@ class MBAlbumInfoTest(MusicBrainzTestCase):
assert d.artist_credit == "Artist Credit"
def test_parse_release_type(self):
release = self._make_release("1984")
release = self._make_release(date="1984")
d = self.mb.album_info(release)
assert d.albumtype == "album"
def test_parse_release_full_date(self):
release = self._make_release("1987-03-31")
release = self._make_release(date="1987-03-31")
d = self.mb.album_info(release)
assert d.original_year == 1987
assert d.original_month == 3
@ -307,7 +307,7 @@ class MBAlbumInfoTest(MusicBrainzTestCase):
assert t[1].index == 2
def test_parse_release_year_month_only(self):
release = self._make_release("1987-03")
release = self._make_release(date="1987-03")
d = self.mb.album_info(release)
assert d.original_year == 1987
assert d.original_month == 3
@ -327,19 +327,19 @@ class MBAlbumInfoTest(MusicBrainzTestCase):
assert d.tracks[0].length == 2.0
def test_no_release_date(self):
release = self._make_release(None)
release = self._make_release(date="")
d = self.mb.album_info(release)
assert not d.original_year
assert not d.original_month
assert not d.original_day
def test_various_artists_defaults_false(self):
release = self._make_release(None)
release = self._make_release()
d = self.mb.album_info(release)
assert not d.va
def test_detect_various_artists(self):
release = self._make_release(None)
release = self._make_release()
release["artist_credit"][0]["artist"]["id"] = (
musicbrainz.VARIOUS_ARTISTS_ID
)
@ -347,43 +347,43 @@ class MBAlbumInfoTest(MusicBrainzTestCase):
assert d.va
def test_parse_artist_sort_name(self):
release = self._make_release(None)
release = self._make_release()
d = self.mb.album_info(release)
assert d.artist_sort == "Artist, The"
def test_parse_releasegroupid(self):
release = self._make_release(None)
release = self._make_release()
d = self.mb.album_info(release)
assert d.releasegroup_id == "RELEASE GROUP ID"
def test_parse_asin(self):
release = self._make_release(None)
release = self._make_release()
d = self.mb.album_info(release)
assert d.asin == "ALBUM ASIN"
def test_parse_catalognum(self):
release = self._make_release(None)
release = self._make_release()
d = self.mb.album_info(release)
assert d.catalognum == "CATALOG NUMBER"
def test_parse_textrepr(self):
release = self._make_release(None)
release = self._make_release()
d = self.mb.album_info(release)
assert d.script == "SCRIPT"
assert d.language == "LANGUAGE"
def test_parse_country(self):
release = self._make_release(None)
release = self._make_release()
d = self.mb.album_info(release)
assert d.country == "US"
def test_parse_status(self):
release = self._make_release(None)
release = self._make_release()
d = self.mb.album_info(release)
assert d.albumstatus == "STATUS"
def test_parse_barcode(self):
release = self._make_release(None)
release = self._make_release()
d = self.mb.album_info(release)
assert d.barcode == "BARCODE"
@ -392,12 +392,12 @@ class MBAlbumInfoTest(MusicBrainzTestCase):
self._make_recording("TITLE ONE", "ID ONE", 100.0 * 1000.0),
self._make_recording("TITLE TWO", "ID TWO", 200.0 * 1000.0),
]
release = self._make_release(None, recordings=recordings)
release = self._make_release(recordings=recordings)
d = self.mb.album_info(release)
assert d.media == "FORMAT"
def test_parse_disambig(self):
release = self._make_release(None)
release = self._make_release()
d = self.mb.album_info(release)
assert d.albumdisambig == "R_DISAMBIGUATION"
assert d.releasegroupdisambig == "RG_DISAMBIGUATION"
@ -407,21 +407,21 @@ class MBAlbumInfoTest(MusicBrainzTestCase):
self._make_recording("TITLE ONE", "ID ONE", 100.0 * 1000.0),
self._make_recording("TITLE TWO", "ID TWO", 200.0 * 1000.0),
]
release = self._make_release(None, recordings=recordings)
release = self._make_release(recordings=recordings)
d = self.mb.album_info(release)
t = d.tracks
assert t[0].disctitle == "MEDIUM TITLE"
assert t[1].disctitle == "MEDIUM TITLE"
def test_missing_language(self):
release = self._make_release(None)
release = self._make_release()
del release["text_representation"]["language"]
d = self.mb.album_info(release)
assert d.language is None
def test_parse_recording_artist(self):
recordings = [self._make_recording("a", "b", 1)]
release = self._make_release(None, recordings=recordings)
release = self._make_release(recordings=recordings)
track = self.mb.album_info(release).tracks[0]
assert track.artist == "Recording Artist"
assert track.artist_id == "00000000-0000-0000-0000-000000000001"
@ -432,7 +432,7 @@ class MBAlbumInfoTest(MusicBrainzTestCase):
recordings = [
self._make_recording("a", "b", 1, multi_artist_credit=True)
]
release = self._make_release(None, recordings=recordings)
release = self._make_release(recordings=recordings)
track = self.mb.album_info(release).tracks[0]
assert track.artist == "Recording Artist & Other Recording Artist"
assert track.artist_id == "00000000-0000-0000-0000-000000000001"
@ -464,9 +464,7 @@ class MBAlbumInfoTest(MusicBrainzTestCase):
def test_track_artist_overrides_recording_artist(self):
recordings = [self._make_recording("a", "b", 1)]
release = self._make_release(
None, recordings=recordings, track_artist=True
)
release = self._make_release(recordings=recordings, track_artist=True)
track = self.mb.album_info(release).tracks[0]
assert track.artist == "Track Artist"
assert track.artist_id == "00000000-0000-0000-0000-000000000001"
@ -478,7 +476,6 @@ class MBAlbumInfoTest(MusicBrainzTestCase):
self._make_recording("a", "b", 1, multi_artist_credit=True)
]
release = self._make_release(
None,
recordings=recordings,
track_artist=True,
multi_artist_credit=True,
@ -510,7 +507,7 @@ class MBAlbumInfoTest(MusicBrainzTestCase):
def test_parse_recording_remixer(self):
recordings = [self._make_recording("a", "b", 1, remixer=True)]
release = self._make_release(None, recordings=recordings)
release = self._make_release(recordings=recordings)
track = self.mb.album_info(release).tracks[0]
assert track.remixer == "Recording Remixer"