Better error handling on display for import errors (#718, #583, #501, #252, #544)

This commit is contained in:
Eliot Berriot 2019-04-04 16:07:43 +02:00
commit 05f0129025
9 changed files with 915 additions and 396 deletions

View file

@ -11,45 +11,22 @@ from funkwhale_api.music import metadata
DATA_DIR = os.path.dirname(os.path.abspath(__file__))
def test_get_all_metadata_at_once():
path = os.path.join(DATA_DIR, "test.ogg")
data = metadata.Metadata(path)
expected = {
"title": "Peer Gynt Suite no. 1, op. 46: I. Morning",
"artist": "Edvard Grieg",
"album_artist": "Edvard Grieg",
"album": "Peer Gynt Suite no. 1, op. 46",
"date": datetime.date(2012, 8, 15),
"track_number": 1,
"disc_number": 1,
"musicbrainz_albumid": uuid.UUID("a766da8b-8336-47aa-a3ee-371cc41ccc75"),
"musicbrainz_recordingid": uuid.UUID("bd21ac48-46d8-4e78-925f-d9cc2a294656"),
"musicbrainz_artistid": uuid.UUID("013c8e5b-d72a-4cd3-8dee-6c64d6125823"),
"musicbrainz_albumartistid": uuid.UUID("013c8e5b-d72a-4cd3-8dee-6c64d6125823"),
"license": "Dummy license: http://creativecommons.org/licenses/by-sa/4.0/",
"copyright": "Someone",
}
assert data.all() == expected
@pytest.mark.parametrize(
"field,value",
[
("title", "Peer Gynt Suite no. 1, op. 46: I. Morning"),
("artist", "Edvard Grieg"),
("album_artist", "Edvard Grieg"),
("album_artist", "Edvard Grieg; Musopen Symphony Orchestra"),
("album", "Peer Gynt Suite no. 1, op. 46"),
("date", datetime.date(2012, 8, 15)),
("track_number", 1),
("disc_number", 1),
("musicbrainz_albumid", uuid.UUID("a766da8b-8336-47aa-a3ee-371cc41ccc75")),
("musicbrainz_recordingid", uuid.UUID("bd21ac48-46d8-4e78-925f-d9cc2a294656")),
("musicbrainz_artistid", uuid.UUID("013c8e5b-d72a-4cd3-8dee-6c64d6125823")),
("date", "2012-08-15"),
("position", "1"),
("disc_number", "1"),
("musicbrainz_albumid", "a766da8b-8336-47aa-a3ee-371cc41ccc75"),
("mbid", "bd21ac48-46d8-4e78-925f-d9cc2a294656"),
("musicbrainz_artistid", "013c8e5b-d72a-4cd3-8dee-6c64d6125823"),
(
"musicbrainz_albumartistid",
uuid.UUID("013c8e5b-d72a-4cd3-8dee-6c64d6125823"),
"013c8e5b-d72a-4cd3-8dee-6c64d6125823;5b4d7d2d-36df-4b38-95e3-a964234f520f",
),
("license", "Dummy license: http://creativecommons.org/licenses/by-sa/4.0/"),
("copyright", "Someone"),
@ -62,22 +39,44 @@ def test_can_get_metadata_from_ogg_file(field, value):
assert data.get(field) == value
def test_can_get_metadata_all():
path = os.path.join(DATA_DIR, "test.ogg")
data = metadata.Metadata(path)
expected = {
"title": "Peer Gynt Suite no. 1, op. 46: I. Morning",
"artist": "Edvard Grieg",
"album_artist": "Edvard Grieg; Musopen Symphony Orchestra",
"album": "Peer Gynt Suite no. 1, op. 46",
"date": "2012-08-15",
"position": "1",
"disc_number": "1",
"musicbrainz_albumid": "a766da8b-8336-47aa-a3ee-371cc41ccc75",
"mbid": "bd21ac48-46d8-4e78-925f-d9cc2a294656",
"musicbrainz_artistid": "013c8e5b-d72a-4cd3-8dee-6c64d6125823",
"musicbrainz_albumartistid": "013c8e5b-d72a-4cd3-8dee-6c64d6125823;5b4d7d2d-36df-4b38-95e3-a964234f520f",
"license": "Dummy license: http://creativecommons.org/licenses/by-sa/4.0/",
"copyright": "Someone",
}
assert data.all() == expected
@pytest.mark.parametrize(
"field,value",
[
("title", "Peer Gynt Suite no. 1, op. 46: I. Morning"),
("artist", "Edvard Grieg"),
("album_artist", "Edvard Grieg"),
("album_artist", "Edvard Grieg; Musopen Symphony Orchestra"),
("album", "Peer Gynt Suite no. 1, op. 46"),
("date", datetime.date(2012, 8, 15)),
("track_number", 1),
("disc_number", 1),
("musicbrainz_albumid", uuid.UUID("a766da8b-8336-47aa-a3ee-371cc41ccc75")),
("musicbrainz_recordingid", uuid.UUID("bd21ac48-46d8-4e78-925f-d9cc2a294656")),
("musicbrainz_artistid", uuid.UUID("013c8e5b-d72a-4cd3-8dee-6c64d6125823")),
("date", "2012-08-15"),
("position", "1"),
("disc_number", "1"),
("musicbrainz_albumid", "a766da8b-8336-47aa-a3ee-371cc41ccc75"),
("mbid", "bd21ac48-46d8-4e78-925f-d9cc2a294656"),
("musicbrainz_artistid", "013c8e5b-d72a-4cd3-8dee-6c64d6125823"),
(
"musicbrainz_albumartistid",
uuid.UUID("013c8e5b-d72a-4cd3-8dee-6c64d6125823"),
"013c8e5b-d72a-4cd3-8dee-6c64d6125823;5b4d7d2d-36df-4b38-95e3-a964234f520f",
),
("license", "Dummy license: http://creativecommons.org/licenses/by-sa/4.0/"),
("copyright", "Someone"),
@ -97,16 +96,13 @@ def test_can_get_metadata_from_opus_file(field, value):
("artist", "Die Toten Hosen"),
("album_artist", "Die Toten Hosen"),
("album", "Ballast der Republik"),
("date", datetime.date(2012, 5, 4)),
("track_number", 1),
("disc_number", 1),
("musicbrainz_albumid", uuid.UUID("1f0441ad-e609-446d-b355-809c445773cf")),
("musicbrainz_recordingid", uuid.UUID("124d0150-8627-46bc-bc14-789a3bc960c8")),
("musicbrainz_artistid", uuid.UUID("c3bc80a6-1f4a-4e17-8cf0-6b1efe8302f1")),
(
"musicbrainz_albumartistid",
uuid.UUID("c3bc80a6-1f4a-4e17-8cf0-6b1efe8302f1"),
),
("date", "2012-05-04"),
("position", "1/16"),
("disc_number", "1/2"),
("musicbrainz_albumid", "1f0441ad-e609-446d-b355-809c445773cf"),
("mbid", "124d0150-8627-46bc-bc14-789a3bc960c8"),
("musicbrainz_artistid", "c3bc80a6-1f4a-4e17-8cf0-6b1efe8302f1"),
("musicbrainz_albumartistid", "c3bc80a6-1f4a-4e17-8cf0-6b1efe8302f1"),
# somehow, I cannot successfully create an ogg theora file
# with the proper license field
# ("license", "Dummy license: http://creativecommons.org/licenses/by-sa/4.0/"),
@ -126,16 +122,13 @@ def test_can_get_metadata_from_ogg_theora_file(field, value):
("artist", "Binärpilot"),
("album_artist", "Binärpilot"),
("album", "You Can't Stop Da Funk"),
("date", datetime.date(2006, 2, 7)),
("track_number", 2),
("disc_number", 1),
("musicbrainz_albumid", uuid.UUID("ce40cdb1-a562-4fd8-a269-9269f98d4124")),
("musicbrainz_recordingid", uuid.UUID("f269d497-1cc0-4ae4-a0c4-157ec7d73fcb")),
("musicbrainz_artistid", uuid.UUID("9c6bddde-6228-4d9f-ad0d-03f6fcb19e13")),
(
"musicbrainz_albumartistid",
uuid.UUID("9c6bddde-6228-4d9f-ad0d-03f6fcb19e13"),
),
("date", "2006-02-07"),
("position", "2/4"),
("disc_number", "1/1"),
("musicbrainz_albumid", "ce40cdb1-a562-4fd8-a269-9269f98d4124"),
("mbid", "f269d497-1cc0-4ae4-a0c4-157ec7d73fcb"),
("musicbrainz_artistid", "9c6bddde-6228-4d9f-ad0d-03f6fcb19e13"),
("musicbrainz_albumartistid", "9c6bddde-6228-4d9f-ad0d-03f6fcb19e13"),
("license", "https://creativecommons.org/licenses/by-nc-nd/2.5/"),
("copyright", "Someone"),
],
@ -144,7 +137,7 @@ def test_can_get_metadata_from_id3_mp3_file(field, value):
path = os.path.join(DATA_DIR, "test.mp3")
data = metadata.Metadata(path)
assert data.get(field) == value
assert str(data.get(field)) == value
@pytest.mark.parametrize(
@ -170,16 +163,13 @@ def test_can_get_pictures(name):
("artist", "Nine Inch Nails"),
("album_artist", "Nine Inch Nails"),
("album", "The Slip"),
("date", datetime.date(2008, 5, 5)),
("track_number", 1),
("disc_number", 1),
("musicbrainz_albumid", uuid.UUID("12b57d46-a192-499e-a91f-7da66790a1c1")),
("musicbrainz_recordingid", uuid.UUID("30f3f33e-8d0c-4e69-8539-cbd701d18f28")),
("musicbrainz_artistid", uuid.UUID("b7ffd2af-418f-4be2-bdd1-22f8b48613da")),
(
"musicbrainz_albumartistid",
uuid.UUID("b7ffd2af-418f-4be2-bdd1-22f8b48613da"),
),
("date", "2008-05-05"),
("position", "1"),
("disc_number", "1"),
("musicbrainz_albumid", "12b57d46-a192-499e-a91f-7da66790a1c1"),
("mbid", "30f3f33e-8d0c-4e69-8539-cbd701d18f28"),
("musicbrainz_artistid", "b7ffd2af-418f-4be2-bdd1-22f8b48613da"),
("musicbrainz_albumartistid", "b7ffd2af-418f-4be2-bdd1-22f8b48613da"),
("license", "http://creativecommons.org/licenses/by-nc-sa/3.0/us/"),
("copyright", "2008 nin"),
],
@ -199,54 +189,18 @@ def test_can_get_metadata_from_flac_file_not_crash_if_empty():
data.get("test")
@pytest.mark.parametrize(
"field_name",
[
"musicbrainz_artistid",
"musicbrainz_albumid",
"musicbrainz_recordingid",
"musicbrainz_albumartistid",
],
)
def test_mbid_clean_keeps_only_first(field_name):
u1 = str(uuid.uuid4())
u2 = str(uuid.uuid4())
field = metadata.VALIDATION[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)),
("2017-14-01 01:32", datetime.date(2017, 1, 14)), # deezer format
("2017-02", datetime.date(2017, 1, 1)), # weird format that exists
("nonsense", None),
],
)
def test_date_parsing(raw, expected):
assert metadata.get_date(raw) == expected
def test_date_parsing_failure():
with pytest.raises(metadata.ParseError):
metadata.get_date("noop")
def test_metadata_all_ignore_parse_errors_true(mocker):
path = os.path.join(DATA_DIR, "sample.flac")
data = metadata.Metadata(path)
mocker.patch.object(data, "get", side_effect=metadata.ParseError("Failure"))
assert data.all()["date"] is None
def test_metadata_all_ignore_parse_errors_false(mocker):
path = os.path.join(DATA_DIR, "sample.flac")
data = metadata.Metadata(path)
mocker.patch.object(data, "get", side_effect=metadata.ParseError("Failure"))
with pytest.raises(metadata.ParseError):
data.all(ignore_parse_errors=False)
assert metadata.PermissiveDateField().to_internal_value(raw) == expected
def test_metadata_fallback_ogg_theora(mocker):
@ -264,3 +218,247 @@ def test_metadata_fallback_ogg_theora(mocker):
assert data.get("pictures", "default") == expected_result
fallback_get.assert_called_once_with("pictures", "default")
@pytest.mark.parametrize(
"path, expected",
[
(
"test.mp3",
{
"title": "Bend",
"artists": [
{
"name": "Binärpilot",
"mbid": uuid.UUID("9c6bddde-6228-4d9f-ad0d-03f6fcb19e13"),
}
],
"album": {
"title": "You Can't Stop Da Funk",
"mbid": uuid.UUID("ce40cdb1-a562-4fd8-a269-9269f98d4124"),
"release_date": datetime.date(2006, 2, 7),
"artists": [
{
"name": "Binärpilot",
"mbid": uuid.UUID("9c6bddde-6228-4d9f-ad0d-03f6fcb19e13"),
}
],
},
"position": 2,
"disc_number": 1,
"mbid": uuid.UUID("f269d497-1cc0-4ae4-a0c4-157ec7d73fcb"),
"license": "https://creativecommons.org/licenses/by-nc-nd/2.5/",
"copyright": "Someone",
},
),
(
"test.ogg",
{
"title": "Peer Gynt Suite no. 1, op. 46: I. Morning",
"artists": [
{
"name": "Edvard Grieg",
"mbid": uuid.UUID("013c8e5b-d72a-4cd3-8dee-6c64d6125823"),
}
],
"album": {
"title": "Peer Gynt Suite no. 1, op. 46",
"mbid": uuid.UUID("a766da8b-8336-47aa-a3ee-371cc41ccc75"),
"release_date": datetime.date(2012, 8, 15),
"artists": [
{
"name": "Edvard Grieg",
"mbid": uuid.UUID("013c8e5b-d72a-4cd3-8dee-6c64d6125823"),
},
{
"name": "Musopen Symphony Orchestra",
"mbid": uuid.UUID("5b4d7d2d-36df-4b38-95e3-a964234f520f"),
},
],
},
"position": 1,
"disc_number": 1,
"mbid": uuid.UUID("bd21ac48-46d8-4e78-925f-d9cc2a294656"),
"license": "Dummy license: http://creativecommons.org/licenses/by-sa/4.0/",
"copyright": "Someone",
},
),
(
"test.opus",
{
"title": "Peer Gynt Suite no. 1, op. 46: I. Morning",
"artists": [
{
"name": "Edvard Grieg",
"mbid": uuid.UUID("013c8e5b-d72a-4cd3-8dee-6c64d6125823"),
}
],
"album": {
"title": "Peer Gynt Suite no. 1, op. 46",
"mbid": uuid.UUID("a766da8b-8336-47aa-a3ee-371cc41ccc75"),
"release_date": datetime.date(2012, 8, 15),
"artists": [
{
"name": "Edvard Grieg",
"mbid": uuid.UUID("013c8e5b-d72a-4cd3-8dee-6c64d6125823"),
},
{
"name": "Musopen Symphony Orchestra",
"mbid": uuid.UUID("5b4d7d2d-36df-4b38-95e3-a964234f520f"),
},
],
},
"position": 1,
"disc_number": 1,
"mbid": uuid.UUID("bd21ac48-46d8-4e78-925f-d9cc2a294656"),
"license": "Dummy license: http://creativecommons.org/licenses/by-sa/4.0/",
"copyright": "Someone",
},
),
(
"test_theora.ogg",
{
"title": "Drei Kreuze (dass wir hier sind)",
"artists": [
{
"name": "Die Toten Hosen",
"mbid": uuid.UUID("c3bc80a6-1f4a-4e17-8cf0-6b1efe8302f1"),
}
],
"album": {
"title": "Ballast der Republik",
"mbid": uuid.UUID("1f0441ad-e609-446d-b355-809c445773cf"),
"release_date": datetime.date(2012, 5, 4),
"artists": [
{
"name": "Die Toten Hosen",
"mbid": uuid.UUID("c3bc80a6-1f4a-4e17-8cf0-6b1efe8302f1"),
}
],
},
"position": 1,
"disc_number": 1,
"mbid": uuid.UUID("124d0150-8627-46bc-bc14-789a3bc960c8"),
# somehow, I cannot successfully create an ogg theora file
# with the proper license field
# ("license", "Dummy license: http://creativecommons.org/licenses/by-sa/4.0/"),
"copyright": "℗ 2012 JKP GmbH & Co. KG",
},
),
(
"sample.flac",
{
"title": "999,999",
"artists": [
{
"name": "Nine Inch Nails",
"mbid": uuid.UUID("b7ffd2af-418f-4be2-bdd1-22f8b48613da"),
}
],
"album": {
"title": "The Slip",
"mbid": uuid.UUID("12b57d46-a192-499e-a91f-7da66790a1c1"),
"release_date": datetime.date(2008, 5, 5),
"artists": [
{
"name": "Nine Inch Nails",
"mbid": uuid.UUID("b7ffd2af-418f-4be2-bdd1-22f8b48613da"),
}
],
},
"position": 1,
"disc_number": 1,
"mbid": uuid.UUID("30f3f33e-8d0c-4e69-8539-cbd701d18f28"),
"license": "http://creativecommons.org/licenses/by-nc-sa/3.0/us/",
"copyright": "2008 nin",
},
),
],
)
def test_track_metadata_serializer(path, expected, mocker):
path = os.path.join(DATA_DIR, path)
data = metadata.Metadata(path)
get_picture = mocker.patch.object(data, "get_picture")
expected["cover_data"] = get_picture.return_value
serializer = metadata.TrackMetadataSerializer(data=data)
assert serializer.is_valid(raise_exception=True) is True
assert serializer.validated_data == expected
get_picture.assert_called_once_with("cover_front", "other")
@pytest.mark.parametrize(
"raw, expected",
[
(
{
"names": "Hello; World",
"mbids": "f269d497-1cc0-4ae4-a0c4-157ec7d73fcb; f269d497-1cc0-4ae4-a0c4-157ec7d73fcd ",
},
[
{
"name": "Hello",
"mbid": uuid.UUID("f269d497-1cc0-4ae4-a0c4-157ec7d73fcb"),
},
{
"name": "World",
"mbid": uuid.UUID("f269d497-1cc0-4ae4-a0c4-157ec7d73fcd"),
},
],
),
(
{
"names": "Hello; World; Foo",
"mbids": "f269d497-1cc0-4ae4-a0c4-157ec7d73fcb; f269d497-1cc0-4ae4-a0c4-157ec7d73fcd ",
},
[
{
"name": "Hello",
"mbid": uuid.UUID("f269d497-1cc0-4ae4-a0c4-157ec7d73fcb"),
},
{
"name": "World",
"mbid": uuid.UUID("f269d497-1cc0-4ae4-a0c4-157ec7d73fcd"),
},
{"name": "Foo", "mbid": None},
],
),
],
)
def test_artists_cleaning(raw, expected):
field = metadata.ArtistField()
assert field.to_internal_value(raw) == expected
@pytest.mark.parametrize(
"data, errored_field",
[
({"name": "Hello", "mbid": "wrong-uuid"}, "mbid"), # wrong uuid
({"name": "", "mbid": "f269d497-1cc0-4ae4-a0c4-157ec7d73fcd"}, "name"),
],
)
def test_artist_serializer_validation(data, errored_field):
serializer = metadata.ArtistSerializer(data=data)
assert serializer.is_valid() is False
assert len(serializer.errors) == 1
assert errored_field in serializer.errors
@pytest.mark.parametrize(
"data, errored_field",
[
({"title": "Hello", "mbid": "wrong"}, "mbid"), # wrong uuid
(
{"title": "", "mbid": "f269d497-1cc0-4ae4-a0c4-157ec7d73fcd"},
"title",
), # empty title
],
)
def test_album_serializer_validation(data, errored_field):
serializer = metadata.AlbumSerializer(data=data)
assert serializer.is_valid() is False
assert len(serializer.errors) == 1
assert errored_field in serializer.errors

View file

@ -20,15 +20,13 @@ DATA_DIR = os.path.dirname(os.path.abspath(__file__))
def test_can_create_track_from_file_metadata_no_mbid(db, mocker):
metadata = {
"title": "Test track",
"artist": "Test artist",
"album": "Test album",
"date": datetime.date(2012, 8, 15),
"track_number": 4,
"artists": [{"name": "Test artist"}],
"album": {"title": "Test album", "release_date": datetime.date(2012, 8, 15)},
"position": 4,
"disc_number": 2,
"license": "Hello world: http://creativecommons.org/licenses/by-sa/4.0/",
"copyright": "2018 Someone",
}
mocker.patch("funkwhale_api.music.metadata.Metadata.all", return_value=metadata)
match_license = mocker.spy(licenses, "match")
track = tasks.get_track_from_import_metadata(metadata)
@ -39,10 +37,10 @@ def test_can_create_track_from_file_metadata_no_mbid(db, mocker):
assert track.disc_number == 2
assert track.license.code == "cc-by-sa-4.0"
assert track.copyright == metadata["copyright"]
assert track.album.title == metadata["album"]
assert track.album.title == metadata["album"]["title"]
assert track.album.mbid is None
assert track.album.release_date == datetime.date(2012, 8, 15)
assert track.artist.name == metadata["artist"]
assert track.artist.name == metadata["artists"][0]["name"]
assert track.artist.mbid is None
match_license.assert_called_once_with(metadata["license"], metadata["copyright"])
@ -50,33 +48,38 @@ def test_can_create_track_from_file_metadata_no_mbid(db, mocker):
def test_can_create_track_from_file_metadata_mbid(factories, mocker):
metadata = {
"title": "Test track",
"artist": "Test artist",
"album_artist": "Test album artist",
"album": "Test album",
"date": datetime.date(2012, 8, 15),
"track_number": 4,
"musicbrainz_albumid": "ce40cdb1-a562-4fd8-a269-9269f98d4124",
"musicbrainz_recordingid": "f269d497-1cc0-4ae4-a0c4-157ec7d73fcb",
"musicbrainz_artistid": "9c6bddde-6228-4d9f-ad0d-03f6fcb19e13",
"musicbrainz_albumartistid": "9c6bddde-6478-4d9f-ad0d-03f6fcb19e13",
"artists": [
{"name": "Test artist", "mbid": "9c6bddde-6228-4d9f-ad0d-03f6fcb19e13"}
],
"album": {
"title": "Test album",
"release_date": datetime.date(2012, 8, 15),
"mbid": "9c6bddde-6478-4d9f-ad0d-03f6fcb19e15",
"artists": [
{
"name": "Test album artist",
"mbid": "9c6bddde-6478-4d9f-ad0d-03f6fcb19e13",
}
],
},
"position": 4,
"mbid": "f269d497-1cc0-4ae4-a0c4-157ec7d73fcb",
"cover_data": {"content": b"image_content", "mimetype": "image/png"},
}
mocker.patch("funkwhale_api.music.metadata.Metadata.all", return_value=metadata)
track = tasks.get_track_from_import_metadata(metadata)
assert track.title == metadata["title"]
assert track.mbid == metadata["musicbrainz_recordingid"]
assert track.mbid == metadata["mbid"]
assert track.position == 4
assert track.disc_number is None
assert track.album.title == metadata["album"]
assert track.album.mbid == metadata["musicbrainz_albumid"]
assert track.album.artist.mbid == metadata["musicbrainz_albumartistid"]
assert track.album.artist.name == metadata["album_artist"]
assert track.album.title == metadata["album"]["title"]
assert track.album.mbid == metadata["album"]["mbid"]
assert track.album.artist.mbid == metadata["album"]["artists"][0]["mbid"]
assert track.album.artist.name == metadata["album"]["artists"][0]["name"]
assert track.album.release_date == datetime.date(2012, 8, 15)
assert track.artist.name == metadata["artist"]
assert track.artist.mbid == metadata["musicbrainz_artistid"]
assert track.artist.name == metadata["artists"][0]["name"]
assert track.artist.mbid == metadata["artists"][0]["mbid"]
def test_can_create_track_from_file_metadata_mbid_existing_album_artist(
@ -85,22 +88,21 @@ def test_can_create_track_from_file_metadata_mbid_existing_album_artist(
artist = factories["music.Artist"]()
album = factories["music.Album"]()
metadata = {
"artist": "",
"album": "",
"album": {
"mbid": album.mbid,
"title": "",
"artists": [{"name": "", "mbid": album.artist.mbid}],
},
"title": "Hello",
"track_number": 4,
"musicbrainz_albumid": album.mbid,
"musicbrainz_recordingid": "f269d497-1cc0-4ae4-a0c4-157ec7d73fcb",
"musicbrainz_artistid": artist.mbid,
"musicbrainz_albumartistid": album.artist.mbid,
"position": 4,
"artists": [{"mbid": artist.mbid, "name": ""}],
"mbid": "f269d497-1cc0-4ae4-a0c4-157ec7d73fcb",
}
mocker.patch("funkwhale_api.music.metadata.Metadata.all", return_value=metadata)
track = tasks.get_track_from_import_metadata(metadata)
assert track.title == metadata["title"]
assert track.mbid == metadata["musicbrainz_recordingid"]
assert track.mbid == metadata["mbid"]
assert track.position == 4
assert track.album == album
assert track.artist == artist
@ -112,18 +114,17 @@ def test_can_create_track_from_file_metadata_fid_existing_album_artist(
artist = factories["music.Artist"]()
album = factories["music.Album"]()
metadata = {
"artist": "",
"album": "",
"artists": [{"name": "", "fid": artist.fid}],
"album": {
"title": "",
"fid": album.fid,
"artists": [{"name": "", "fid": album.artist.fid}],
},
"title": "Hello",
"track_number": 4,
"position": 4,
"fid": "https://hello",
"album_fid": album.fid,
"artist_fid": artist.fid,
"album_artist_fid": album.artist.fid,
}
mocker.patch("funkwhale_api.music.metadata.Metadata.all", return_value=metadata)
track = tasks.get_track_from_import_metadata(metadata)
assert track.title == metadata["title"]
@ -139,13 +140,11 @@ def test_can_create_track_from_file_metadata_distinct_release_mbid(factories):
album = factories["music.Album"](artist=artist)
track = factories["music.Track"](album=album, artist=artist)
metadata = {
"artist": artist.name,
"album": album.title,
"artists": [{"name": artist.name, "mbid": artist.mbid}],
"album": {"title": album.title, "mbid": str(uuid.uuid4())},
"title": track.title,
"track_number": 4,
"position": 4,
"fid": "https://hello",
"musicbrainz_artistid": artist.mbid,
"musicbrainz_albumid": str(uuid.uuid4()),
}
new_track = tasks.get_track_from_import_metadata(metadata)
@ -162,12 +161,10 @@ def test_can_create_track_from_file_metadata_distinct_position(factories):
album = factories["music.Album"](artist=artist)
track = factories["music.Track"](album=album, artist=artist)
metadata = {
"artist": artist.name,
"album": album.title,
"artists": [{"name": artist.name, "mbid": artist.mbid}],
"album": {"title": album.title, "mbid": album.mbid},
"title": track.title,
"track_number": track.position + 1,
"musicbrainz_artistid": artist.mbid,
"musicbrainz_albumid": album.mbid,
"position": track.position + 1,
}
new_track = tasks.get_track_from_import_metadata(metadata)
@ -177,23 +174,28 @@ def test_can_create_track_from_file_metadata_distinct_position(factories):
def test_can_create_track_from_file_metadata_federation(factories, mocker, r_mock):
metadata = {
"artist": "Artist",
"album": "Album",
"album_artist": "Album artist",
"artists": [
{"name": "Artist", "fid": "https://artist.fid", "fdate": timezone.now()}
],
"album": {
"title": "Album",
"fid": "https://album.fid",
"fdate": timezone.now(),
"artists": [
{
"name": "Album artist",
"fid": "https://album.artist.fid",
"fdate": timezone.now(),
}
],
},
"title": "Hello",
"track_number": 4,
"position": 4,
"fid": "https://hello",
"album_fid": "https://album.fid",
"artist_fid": "https://artist.fid",
"album_artist_fid": "https://album.artist.fid",
"fdate": timezone.now(),
"album_fdate": timezone.now(),
"album_artist_fdate": timezone.now(),
"artist_fdate": timezone.now(),
"cover_data": {"url": "https://cover/hello.png", "mimetype": "image/png"},
}
r_mock.get(metadata["cover_data"]["url"], body=io.BytesIO(b"coucou"))
mocker.patch("funkwhale_api.music.metadata.Metadata.all", return_value=metadata)
track = tasks.get_track_from_import_metadata(metadata, update_cover=True)
@ -203,15 +205,15 @@ def test_can_create_track_from_file_metadata_federation(factories, mocker, r_moc
assert track.position == 4
assert track.album.cover.read() == b"coucou"
assert track.album.cover.path.endswith(".png")
assert track.album.fid == metadata["album_fid"]
assert track.album.title == metadata["album"]
assert track.album.creation_date == metadata["album_fdate"]
assert track.album.artist.fid == metadata["album_artist_fid"]
assert track.album.artist.name == metadata["album_artist"]
assert track.album.artist.creation_date == metadata["album_artist_fdate"]
assert track.artist.fid == metadata["artist_fid"]
assert track.artist.name == metadata["artist"]
assert track.artist.creation_date == metadata["artist_fdate"]
assert track.album.fid == metadata["album"]["fid"]
assert track.album.title == metadata["album"]["title"]
assert track.album.creation_date == metadata["album"]["fdate"]
assert track.album.artist.fid == metadata["album"]["artists"][0]["fid"]
assert track.album.artist.name == metadata["album"]["artists"][0]["name"]
assert track.album.artist.creation_date == metadata["album"]["artists"][0]["fdate"]
assert track.artist.fid == metadata["artists"][0]["fid"]
assert track.artist.name == metadata["artists"][0]["name"]
assert track.artist.creation_date == metadata["artists"][0]["fdate"]
def test_sort_candidates(factories):
@ -391,7 +393,38 @@ def test_upload_import_error(factories, now, temp_signal):
assert upload.import_status == "errored"
assert upload.import_date == now
assert upload.import_details == {"error_code": "track_uuid_not_found"}
assert upload.import_details == {
"error_code": "track_uuid_not_found",
"detail": None,
}
handler.assert_called_once_with(
upload=upload,
old_status="pending",
new_status="errored",
sender=None,
signal=signals.upload_import_status_updated,
)
def test_upload_import_error_metadata(factories, now, temp_signal, mocker):
path = os.path.join(DATA_DIR, "test.ogg")
upload = factories["music.Upload"](audio_file__frompath=path)
mocker.patch.object(
metadata.AlbumField,
"to_internal_value",
side_effect=metadata.serializers.ValidationError("Hello"),
)
with temp_signal(signals.upload_import_status_updated) as handler:
tasks.process_upload(upload_id=upload.pk)
upload.refresh_from_db()
assert upload.import_status == "errored"
assert upload.import_date == now
assert upload.import_details == {
"error_code": "invalid_metadata",
"detail": {"album": ["Hello"]},
"file_metadata": metadata.Metadata(path).all(),
}
handler.assert_called_once_with(
upload=upload,
old_status="pending",
@ -494,31 +527,43 @@ def test_federation_audio_track_to_metadata(now):
serializer = federation_serializers.TrackSerializer(data=payload)
serializer.is_valid(raise_exception=True)
expected = {
"artist": payload["artists"][0]["name"],
"album": payload["album"]["name"],
"album_artist": payload["album"]["artists"][0]["name"],
"title": payload["name"],
"date": released,
"track_number": payload["position"],
"position": payload["position"],
"disc_number": payload["disc"],
"license": "http://creativecommons.org/licenses/by-sa/4.0/",
"copyright": "2018 Someone",
# musicbrainz
"musicbrainz_albumid": payload["album"]["musicbrainzId"],
"musicbrainz_recordingid": payload["musicbrainzId"],
"musicbrainz_artistid": payload["artists"][0]["musicbrainzId"],
"musicbrainz_albumartistid": payload["album"]["artists"][0]["musicbrainzId"],
# federation
"fid": payload["id"],
"album_fid": payload["album"]["id"],
"artist_fid": payload["artists"][0]["id"],
"album_artist_fid": payload["album"]["artists"][0]["id"],
"mbid": payload["musicbrainzId"],
"fdate": serializer.validated_data["published"],
"artist_fdate": serializer.validated_data["artists"][0]["published"],
"album_artist_fdate": serializer.validated_data["album"]["artists"][0][
"published"
"fid": payload["id"],
"album": {
"title": payload["album"]["name"],
"release_date": released,
"mbid": payload["album"]["musicbrainzId"],
"fid": payload["album"]["id"],
"fdate": serializer.validated_data["album"]["published"],
"artists": [
{
"name": a["name"],
"mbid": a["musicbrainzId"],
"fid": a["id"],
"fdate": serializer.validated_data["album"]["artists"][i][
"published"
],
}
for i, a in enumerate(payload["album"]["artists"])
],
},
# musicbrainz
# federation
"artists": [
{
"name": a["name"],
"mbid": a["musicbrainzId"],
"fid": a["id"],
"fdate": serializer.validated_data["artists"][i]["published"],
}
for i, a in enumerate(payload["artists"])
],
"album_fdate": serializer.validated_data["album"]["published"],
"cover_data": {
"mimetype": serializer.validated_data["album"]["cover"]["mediaType"],
"url": serializer.validated_data["album"]["cover"]["href"],
@ -528,10 +573,6 @@ def test_federation_audio_track_to_metadata(now):
result = tasks.federation_audio_track_to_metadata(serializer.validated_data)
assert result == expected
# ensure we never forget to test a mandatory field
for k in metadata.ALL_FIELDS:
assert k in result
def test_scan_library_fetches_page_and_calls_scan_page(now, mocker, factories, r_mock):
scan = factories["music.LibraryScan"]()