diff --git a/api/funkwhale_api/music/metadata.py b/api/funkwhale_api/music/metadata.py index d2534f6b241ad3e7b6cc98fa8e1e0c49f41f0450..9aa08820ac6e069ff38cd75d95eef79c11c8bd23 100644 --- a/api/funkwhale_api/music/metadata.py +++ b/api/funkwhale_api/music/metadata.py @@ -1,5 +1,6 @@ -import arrow +import datetime import mutagen +import pendulum from django import forms NODEFAULT = object() @@ -101,6 +102,11 @@ class FirstUUIDField(forms.UUIDField): return super().to_python(value) +def get_date(value): + parsed = pendulum.parse(str(value)) + return datetime.date(parsed.year, parsed.month, parsed.day) + + VALIDATION = { "musicbrainz_artistid": FirstUUIDField(), "musicbrainz_albumid": FirstUUIDField(), @@ -118,7 +124,7 @@ CONF = { "title": {}, "artist": {}, "album": {}, - "date": {"field": "date", "to_application": lambda v: arrow.get(v).date()}, + "date": {"field": "date", "to_application": get_date}, "musicbrainz_albumid": {}, "musicbrainz_artistid": {}, "musicbrainz_recordingid": {"field": "musicbrainz_trackid"}, @@ -134,7 +140,7 @@ CONF = { "title": {}, "artist": {}, "album": {}, - "date": {"field": "date", "to_application": lambda v: arrow.get(v).date()}, + "date": {"field": "date", "to_application": get_date}, "musicbrainz_albumid": {"field": "MusicBrainz Album Id"}, "musicbrainz_artistid": {"field": "MusicBrainz Artist Id"}, "musicbrainz_recordingid": {"field": "MusicBrainz Track Id"}, @@ -148,10 +154,7 @@ CONF = { "title": {"field": "TIT2"}, "artist": {"field": "TPE1"}, "album": {"field": "TALB"}, - "date": { - "field": "TDRC", - "to_application": lambda v: arrow.get(str(v)).date(), - }, + "date": {"field": "TDRC", "to_application": get_date}, "musicbrainz_albumid": {"field": "MusicBrainz Album Id"}, "musicbrainz_artistid": {"field": "MusicBrainz Artist Id"}, "musicbrainz_recordingid": { @@ -172,10 +175,7 @@ CONF = { "title": {}, "artist": {}, "album": {}, - "date": { - "field": "date", - "to_application": lambda v: arrow.get(str(v)).date(), - }, + "date": {"field": "date", "to_application": get_date}, "musicbrainz_albumid": {}, "musicbrainz_artistid": {}, "musicbrainz_recordingid": {"field": "musicbrainz_trackid"}, diff --git a/api/funkwhale_api/music/models.py b/api/funkwhale_api/music/models.py index c8dd61313df9e94d392847c5855efe783c2e6775..3aa249f0e9d444e167e3294d0ac0b3d24ebfd39d 100644 --- a/api/funkwhale_api/music/models.py +++ b/api/funkwhale_api/music/models.py @@ -1,11 +1,10 @@ -import datetime import os import shutil import tempfile import uuid -import arrow import markdown +import pendulum from django.conf import settings from django.core.files import File from django.core.files.base import ContentFile @@ -125,9 +124,7 @@ def import_artist(v): def parse_date(v): - if len(v) == 4: - return datetime.date(int(v), 1, 1) - d = arrow.get(v).date() + d = pendulum.parse(v).date() return d diff --git a/api/requirements/base.txt b/api/requirements/base.txt index e4a85d99fae020cf9d64ede59500d3e96132cb20..bb441ac38d99fa721cdd01da2ef2ead289f75db1 100644 --- a/api/requirements/base.txt +++ b/api/requirements/base.txt @@ -35,7 +35,7 @@ djangorestframework>=3.7,<3.8 djangorestframework-jwt>=1.11,<1.12 oauth2client<4 google-api-python-client>=1.6,<1.7 -arrow>=0.12,<0.13 +pendulum>=2,<3 persisting-theory>=0.2,<0.3 django-versatileimagefield>=1.9,<1.10 django-filter>=1.1,<1.2 diff --git a/api/tests/federation/test_actors.py b/api/tests/federation/test_actors.py index 736ec8bf2fb9ea6f4d2a0dd01cd2b8ff326c349a..1244533de785ca227fdaf47258cd25aa10448703 100644 --- a/api/tests/federation/test_actors.py +++ b/api/tests/federation/test_actors.py @@ -1,4 +1,4 @@ -import arrow +import pendulum import pytest from django.urls import reverse from django.utils import timezone @@ -455,7 +455,7 @@ def test_library_actor_handle_create_audio(mocker, factories): assert lt.title == a["metadata"]["recording"]["title"] assert lt.artist_name == a["metadata"]["artist"]["name"] assert lt.album_title == a["metadata"]["release"]["title"] - assert lt.published_date == arrow.get(a["published"]) + assert lt.published_date == pendulum.parse(a["published"]) def test_library_actor_handle_create_audio_autoimport(mocker, factories): @@ -494,7 +494,7 @@ def test_library_actor_handle_create_audio_autoimport(mocker, factories): assert lt.title == a["metadata"]["recording"]["title"] assert lt.artist_name == a["metadata"]["artist"]["name"] assert lt.album_title == a["metadata"]["release"]["title"] - assert lt.published_date == arrow.get(a["published"]) + assert lt.published_date == pendulum.parse(a["published"]) batch = music_models.ImportBatch.objects.latest("id") diff --git a/api/tests/federation/test_serializers.py b/api/tests/federation/test_serializers.py index 6b14656ba988834a3ce2e05a2321f2b897c48105..b42c843ee6e402e19a8c32d88ba816fc2f5421fd 100644 --- a/api/tests/federation/test_serializers.py +++ b/api/tests/federation/test_serializers.py @@ -1,4 +1,4 @@ -import arrow +import pendulum import pytest from django.core.paginator import Paginator @@ -492,7 +492,7 @@ def test_activity_pub_audio_serializer_to_library_track(factories): assert lt.title == audio["metadata"]["recording"]["title"] assert lt.artist_name == audio["metadata"]["artist"]["name"] assert lt.album_title == audio["metadata"]["release"]["title"] - assert lt.published_date == arrow.get(audio["published"]) + assert lt.published_date == pendulum.parse(audio["published"]) def test_activity_pub_audio_serializer_to_library_track_no_duplicate(factories): diff --git a/api/tests/music/test_metadata.py b/api/tests/music/test_metadata.py index fbdf5b81fcbca1532c6716466a5bade62c776d0a..1dfe927a07cde6e69f059d2a50f125a082331198 100644 --- a/api/tests/music/test_metadata.py +++ b/api/tests/music/test_metadata.py @@ -122,3 +122,11 @@ def test_mbid_clean_keeps_only_first(field_name): result = field.to_python("/".join([u1, u2])) assert str(result) == u1 + + +@pytest.mark.parametrize( + "raw,expected", + [("2017", datetime.date(2017, 1, 1)), ("2017-12-31", datetime.date(2017, 12, 31))], +) +def test_date_parsing(raw, expected): + assert metadata.get_date(raw) == expected diff --git a/changes/changelog.d/376.bugfix b/changes/changelog.d/376.bugfix new file mode 100644 index 0000000000000000000000000000000000000000..b5e8379d85115fd2aa80b92e1ec450684dfaf409 --- /dev/null +++ b/changes/changelog.d/376.bugfix @@ -0,0 +1 @@ +Smarter date parsing during import by replacing arrow with pendulum (#376)