diff --git a/audiorename/meta.py b/audiorename/meta.py index 8393674..9f8549d 100644 --- a/audiorename/meta.py +++ b/audiorename/meta.py @@ -1,317 +1,12 @@ """Extend the class ``MediaFile`` of the package ``phrydy``. - -.. code-block:: Python - - import json - print(json.dumps(result,indent=2)) - -``get_recording_by_id`` with ``work-rels`` - -soundtrack/Pulp-Fiction/01.mp3 - -.. code-block:: JSON - - { - "recording": { - "length": "149000", - "id": "0480672d-4d88-4824-a06b-917ff408eabe", - "title": "Pumpkin and Honey Bunny ..." - } - } - -classical/Mozart_Horn-concertos/01.mp3 - -.. code-block:: JSON - - { - "recording": { - "length": "286826", - "work-relation-list": [ - { - "type-id": "a3005666-a872-32c3-ad06-98af558e99b0", - "begin": "1987-03", - "end": "1987-03", - "target": "21fe0bf0-a040-387c-a39d-369d53c251fe", - "ended": "true", - "work": { - "id": "21fe0bf0-a040-387c-a39d-369d53c251fe", - "language": "zxx", - "title": "Concerto [...] KV 412: I. Allegro" - }, - "type": "performance" - } - ], - "id": "7886ad6c-11af-435b-8ec3-bca5711f7728", - "title": "Konzert f\u00fcr [...] K. 386b/514: I. Allegro" - } - } - -``get_work_by_id`` with ``work-rels`` - -.. code-block:: JSON - - { - "work": { - "work-relation-list": [ - { - "type-id": "ca8d3642-ce5f-49f8-91f2-125d72524e6a", - "direction": "backward", - "target": "5adc213f-700a-4435-9e95-831ed720f348", - "ordering-key": "3", - "work": { - "id": "5adc213f-700a-4435-9e95-831ed720f348", - "language": "deu", - "title": "Die Zauberfl\u00f6te, K. 620: Akt I" - }, - "type": "parts" - }, - { - "type-id": "51975ed8-bbfa-486b-9f28-5947f4370299", - "work": { - "disambiguation": "for piano, arr. Matthias", - "id": "798f4c25-0ab3-44ba-81b6-3d856aedf82a", - "language": "zxx", - "title": "Die Zauberfl\u00f6te, K. 620: Aria ..." - }, - "type": "arrangement", - "target": "798f4c25-0ab3-44ba-81b6-3d856aedf82a" - } - ], - "type": "Aria", - "id": "eafec51f-47c5-3c66-8c36-a524246c85f8", - "language": "deu", - "title": "Die Zauberfl\u00f6te: Act I, Scene II. No. 2 Aria ..", - "artist-relation-list": [ - { - "type-id": "7474ab81-486f-40b5-8685-3a4f8ea624cb", - "direction": "backward", - "type": "librettist", - "target": "86104c7c-cda4-4798-a4ab-104318c7ae9c", - "artist": { - "sort-name": "Schikaneder, Emanuel", - "id": "86104c7c-cda4-4798-a4ab-104318c7ae9c", - "name": "Emanuel Schikaneder" - } - }, - { - "begin": "1791", - "end": "1791", - "target": "b972f589-fb0e-474e-b64a-803b0364fa75", - "artist": { - "sort-name": "Mozart, Wolfgang Amadeus", - "disambiguation": "classical composer", - "id": "b972f589-fb0e-474e-b64a-803b0364fa75", - "name": "Wolfgang Amadeus Mozart" - }, - "direction": "backward", - "type-id": "d59d99ea-23d4-4a80-b066-edca32ee158f", - "ended": "true", - "type": "composer" - } - ] - } - } - - -.. code-block:: JSON - - { - "work": { - "work-relation-list": [ - { - "type-id": "c1dca2cd-194c-36dd-93f8-6a359167e992", - "direction": "backward", - "work": { - "id": "70e53569-258c-463d-9505-5b69dcbf374a", - "title": "Can\u2019t Stop the Classics, Part 2" - }, - "type": "medley", - "target": "70e53569-258c-463d-9505-5b69dcbf374a" - }, - { - "type-id": "ca8d3642-ce5f-49f8-91f2-125d72524e6a", - "direction": "backward", - "target": "73663bd3-392f-45a7-b4ff-e75c01f5926a", - "ordering-key": "1", - "work": { - "id": "73663bd3-392f-45a7-b4ff-e75c01f5926a", - "language": "deu", - "title": "Die Meistersinger von N\u00fcrnberg, WWV 96: Akt I" - }, - "type": "parts" - } - ] - } - } - -``get_release_by_id`` with ``release-groups`` - -soundtrack/Pulp-Fiction/01.mp3 - -.. code-block:: JSON - - { - "release": { - "status": "Bootleg", - "release-event-count": 1, - "title": "Pulp Fiction", - "country": "US", - "cover-art-archive": { - "count": "1", - "front": "true", - "back": "false", - "artwork": "true" - }, - "release-event-list": [ - { - "date": "2005-12-01", - "area": { - "sort-name": "United States", - "iso-3166-1-code-list": [ - "US" - ], - "id": "489ce91b-6658-3307-9877-795b68554c98", - "name": "United States" - } - } - ], - "release-group": { - "first-release-date": "1994-09-27", - "secondary-type-list": [ - "Compilation", - "Soundtrack" - ], - "primary-type": "Album", - "title": "Pulp Fiction: Music From the Motion Picture", - "type": "Soundtrack", - "id": "1703cd63-9401-33c0-87c6-50c4ba2e0ba8" - }, - "text-representation": { - "language": "eng", - "script": "Latn" - }, - "date": "2005-12-01", - "quality": "normal", - "id": "ab81edcb-9525-47cd-8247-db4fa969f525", - "asin": "B000002OTL" - } - } - -classical/Mozart_Horn-concertos/01.mp3 - -.. code-block:: JSON - - { - "release": { - "status": "Official", - "release-event-count": 1, - "title": "4 Hornkonzerte (Concertos for Horn and Orchestra)", - "country": "DE", - "barcode": "028942781429", - "cover-art-archive": { - "count": "0", - "front": "false", - "back": "false", - "artwork": "false" - }, - "release-event-list": [ - { - "date": "1988", - "area": { - "sort-name": "Germany", - "iso-3166-1-code-list": [ - "DE" - ], - "id": "85752fda-13c4-31a3-bee5-0e5cb1f51dad", - "name": "Germany" - } - } - ], - "release-group": { - "first-release-date": "1988", - "title": "4 Hornkonzerte (Concertos for Horn and Orchestra)", - "type": "Album", - "id": "e1fa28f0-e56e-395b-82d3-a8de54e8c627", - "primary-type": "Album" - }, - "text-representation": { - "language": "deu", - "script": "Latn" - }, - "date": "1988", - "quality": "normal", - "id": "5ed650c5-0f72-4b79-80a7-c458c869f53e", - "asin": "B00000E4FA" - } - } - """ -from audiorename._version import get_versions from phrydy import MediaFileExtended from tmep import Functions -import musicbrainzngs as mbrainz import re import typing - -def set_useragent() -> None: - mbrainz.set_useragent( - 'audiorename', - get_versions()['version'], - 'https://github.com/Josef-Friedrich/audiorename', - ) - - -def query_mbrainz( - mb_type: typing.Literal['recording', 'work', 'release'], - mb_id: str) -> typing.Union[typing.Dict[str, typing.Any], None]: - method = 'get_' + mb_type + '_by_id' - query = getattr(mbrainz, method) - - if mb_type == 'recording' or mb_type == 'work': - mb_includes = ['work-rels'] - elif mb_type == 'release': - mb_includes = ['release-groups'] - else: - mb_includes = [] - - if mb_type == 'work': - mb_includes.append('artist-rels') - - try: - result = query(mb_id, includes=mb_includes) - return result[mb_type] - - except mbrainz.ResponseError as err: - if err.cause and err.cause.code == 404: - print('Item of type “' + mb_type + '” with the ID ' - '“' + mb_id + '” not found.') - else: - print("Received bad response from the MusicBrainz server.") - - -def query_works_recursively(work_id: str, works=[]): - work = query_mbrainz('work', work_id) - - if not work: - return works - - works.append(work) - - parent_work = False - if 'work-relation-list' in work: - for relation in work['work-relation-list']: - if 'direction' in relation and \ - relation['direction'] == 'backward' and \ - relation['type'] == 'parts': - parent_work = relation - break - - if parent_work: - query_works_recursively(parent_work['work']['id'], works) - - return works +import audiorename.musicbrainz as musicbrainz def compare_dicts(first: typing.Dict[str, str], @@ -373,17 +68,17 @@ def export_dict(self, sanitize: bool = True) -> typing.Dict[str, str]: return out def enrich_metadata(self) -> None: - set_useragent() + musicbrainz.set_useragent() if self.mb_trackid: - recording = query_mbrainz('recording', self.mb_trackid) + recording = musicbrainz.query('recording', self.mb_trackid) else: print('No music brainz track id found.') return release = None if self.mb_albumid: - release = query_mbrainz('release', self.mb_albumid) + release = musicbrainz.query('release', self.mb_albumid) if release and 'release-group' in release: release_group = release['release-group'] types = [] @@ -405,7 +100,7 @@ def enrich_metadata(self) -> None: except KeyError: pass if work_id: - work_hierarchy = query_works_recursively(work_id, []) + work_hierarchy = musicbrainz.query_works_recursively(work_id, []) if work_hierarchy: work_hierarchy.reverse() work_bottom = work_hierarchy[-1] diff --git a/audiorename/musicbrainz.py b/audiorename/musicbrainz.py new file mode 100644 index 0000000..c2e1782 --- /dev/null +++ b/audiorename/musicbrainz.py @@ -0,0 +1,313 @@ +import typing +import musicbrainzngs as musicbrainz + +from ._version import get_versions + +"""Query the musicbrainz API using the library +`musicbrainzngs `_. + +.. code-block:: Python + + import json + print(json.dumps(result,indent=2)) + +``get_recording_by_id`` with ``work-rels`` + +soundtrack/Pulp-Fiction/01.mp3 + +.. code-block:: JSON + + { + "recording": { + "length": "149000", + "id": "0480672d-4d88-4824-a06b-917ff408eabe", + "title": "Pumpkin and Honey Bunny ..." + } + } + +classical/Mozart_Horn-concertos/01.mp3 + +.. code-block:: JSON + + { + "recording": { + "length": "286826", + "work-relation-list": [ + { + "type-id": "a3005666-a872-32c3-ad06-98af558e99b0", + "begin": "1987-03", + "end": "1987-03", + "target": "21fe0bf0-a040-387c-a39d-369d53c251fe", + "ended": "true", + "work": { + "id": "21fe0bf0-a040-387c-a39d-369d53c251fe", + "language": "zxx", + "title": "Concerto [...] KV 412: I. Allegro" + }, + "type": "performance" + } + ], + "id": "7886ad6c-11af-435b-8ec3-bca5711f7728", + "title": "Konzert f\u00fcr [...] K. 386b/514: I. Allegro" + } + } + +``get_work_by_id`` with ``work-rels`` + +.. code-block:: JSON + + { + "work": { + "work-relation-list": [ + { + "type-id": "ca8d3642-ce5f-49f8-91f2-125d72524e6a", + "direction": "backward", + "target": "5adc213f-700a-4435-9e95-831ed720f348", + "ordering-key": "3", + "work": { + "id": "5adc213f-700a-4435-9e95-831ed720f348", + "language": "deu", + "title": "Die Zauberfl\u00f6te, K. 620: Akt I" + }, + "type": "parts" + }, + { + "type-id": "51975ed8-bbfa-486b-9f28-5947f4370299", + "work": { + "disambiguation": "for piano, arr. Matthias", + "id": "798f4c25-0ab3-44ba-81b6-3d856aedf82a", + "language": "zxx", + "title": "Die Zauberfl\u00f6te, K. 620: Aria ..." + }, + "type": "arrangement", + "target": "798f4c25-0ab3-44ba-81b6-3d856aedf82a" + } + ], + "type": "Aria", + "id": "eafec51f-47c5-3c66-8c36-a524246c85f8", + "language": "deu", + "title": "Die Zauberfl\u00f6te: Act I, Scene II. No. 2 Aria ..", + "artist-relation-list": [ + { + "type-id": "7474ab81-486f-40b5-8685-3a4f8ea624cb", + "direction": "backward", + "type": "librettist", + "target": "86104c7c-cda4-4798-a4ab-104318c7ae9c", + "artist": { + "sort-name": "Schikaneder, Emanuel", + "id": "86104c7c-cda4-4798-a4ab-104318c7ae9c", + "name": "Emanuel Schikaneder" + } + }, + { + "begin": "1791", + "end": "1791", + "target": "b972f589-fb0e-474e-b64a-803b0364fa75", + "artist": { + "sort-name": "Mozart, Wolfgang Amadeus", + "disambiguation": "classical composer", + "id": "b972f589-fb0e-474e-b64a-803b0364fa75", + "name": "Wolfgang Amadeus Mozart" + }, + "direction": "backward", + "type-id": "d59d99ea-23d4-4a80-b066-edca32ee158f", + "ended": "true", + "type": "composer" + } + ] + } + } + + +.. code-block:: JSON + + { + "work": { + "work-relation-list": [ + { + "type-id": "c1dca2cd-194c-36dd-93f8-6a359167e992", + "direction": "backward", + "work": { + "id": "70e53569-258c-463d-9505-5b69dcbf374a", + "title": "Can\u2019t Stop the Classics, Part 2" + }, + "type": "medley", + "target": "70e53569-258c-463d-9505-5b69dcbf374a" + }, + { + "type-id": "ca8d3642-ce5f-49f8-91f2-125d72524e6a", + "direction": "backward", + "target": "73663bd3-392f-45a7-b4ff-e75c01f5926a", + "ordering-key": "1", + "work": { + "id": "73663bd3-392f-45a7-b4ff-e75c01f5926a", + "language": "deu", + "title": "Die Meistersinger von N\u00fcrnberg, WWV 96: Akt I" + }, + "type": "parts" + } + ] + } + } + +``get_release_by_id`` with ``release-groups`` + +soundtrack/Pulp-Fiction/01.mp3 + +.. code-block:: JSON + + { + "release": { + "status": "Bootleg", + "release-event-count": 1, + "title": "Pulp Fiction", + "country": "US", + "cover-art-archive": { + "count": "1", + "front": "true", + "back": "false", + "artwork": "true" + }, + "release-event-list": [ + { + "date": "2005-12-01", + "area": { + "sort-name": "United States", + "iso-3166-1-code-list": [ + "US" + ], + "id": "489ce91b-6658-3307-9877-795b68554c98", + "name": "United States" + } + } + ], + "release-group": { + "first-release-date": "1994-09-27", + "secondary-type-list": [ + "Compilation", + "Soundtrack" + ], + "primary-type": "Album", + "title": "Pulp Fiction: Music From the Motion Picture", + "type": "Soundtrack", + "id": "1703cd63-9401-33c0-87c6-50c4ba2e0ba8" + }, + "text-representation": { + "language": "eng", + "script": "Latn" + }, + "date": "2005-12-01", + "quality": "normal", + "id": "ab81edcb-9525-47cd-8247-db4fa969f525", + "asin": "B000002OTL" + } + } + +classical/Mozart_Horn-concertos/01.mp3 + +.. code-block:: JSON + + { + "release": { + "status": "Official", + "release-event-count": 1, + "title": "4 Hornkonzerte (Concertos for Horn and Orchestra)", + "country": "DE", + "barcode": "028942781429", + "cover-art-archive": { + "count": "0", + "front": "false", + "back": "false", + "artwork": "false" + }, + "release-event-list": [ + { + "date": "1988", + "area": { + "sort-name": "Germany", + "iso-3166-1-code-list": [ + "DE" + ], + "id": "85752fda-13c4-31a3-bee5-0e5cb1f51dad", + "name": "Germany" + } + } + ], + "release-group": { + "first-release-date": "1988", + "title": "4 Hornkonzerte (Concertos for Horn and Orchestra)", + "type": "Album", + "id": "e1fa28f0-e56e-395b-82d3-a8de54e8c627", + "primary-type": "Album" + }, + "text-representation": { + "language": "deu", + "script": "Latn" + }, + "date": "1988", + "quality": "normal", + "id": "5ed650c5-0f72-4b79-80a7-c458c869f53e", + "asin": "B00000E4FA" + } + } + +""" + + +def set_useragent() -> None: + musicbrainz.set_useragent( + 'audiorename', + get_versions()['version'], + 'https://github.com/Josef-Friedrich/audiorename', + ) + + +def query( + mb_type: typing.Literal['recording', 'work', 'release'], + mb_id: str) -> typing.Union[typing.Dict[str, typing.Any], None]: + method = 'get_' + mb_type + '_by_id' + query = getattr(musicbrainz, method) + + if mb_type == 'recording' or mb_type == 'work': + mb_includes = ['work-rels'] + elif mb_type == 'release': + mb_includes = ['release-groups'] + else: + mb_includes = [] + + if mb_type == 'work': + mb_includes.append('artist-rels') + + try: + result = query(mb_id, includes=mb_includes) + return result[mb_type] + + except musicbrainz.ResponseError as err: + if err.cause and err.cause.code == 404: + print('Item of type “' + mb_type + '” with the ID ' + '“' + mb_id + '” not found.') + else: + print("Received bad response from the MusicBrainz server.") + + +def query_works_recursively(work_id: str, works=[]): + work = query('work', work_id) + + if not work: + return works + + works.append(work) + + parent_work = False + if 'work-relation-list' in work: + for relation in work['work-relation-list']: + if 'direction' in relation and \ + relation['direction'] == 'backward' and \ + relation['type'] == 'parts': + parent_work = relation + break + + if parent_work: + query_works_recursively(parent_work['work']['id'], works) + + return works diff --git a/doc/source/audiorename.rst b/doc/source/audiorename.rst index 6dad2d4..4fbb315 100644 --- a/doc/source/audiorename.rst +++ b/doc/source/audiorename.rst @@ -14,11 +14,21 @@ audiorename.args module .. automodule:: audiorename.args +audiorename.audiofile module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. automodule:: audiorename.audiofile + audiorename.batch module ^^^^^^^^^^^^^^^^^^^^^^^^ .. automodule:: audiorename.batch +audiorename.config module +^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. automodule:: audiorename.config + audiorename.job module ^^^^^^^^^^^^^^^^^^^^^^ @@ -35,7 +45,7 @@ audiorename.meta module .. automodule:: audiorename.meta :special-members: -audiorename.audiofile module -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +audiorename.musicbrainz module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. automodule:: audiorename.audiofile +.. automodule:: audiorename.musicbrainz diff --git a/example-config.ini b/example-config.ini index 9c9adc7..31ca169 100644 --- a/example-config.ini +++ b/example-config.ini @@ -35,7 +35,6 @@ format_classical = False [output] color = False -no_color = False debug = False job_info = False mb_track_listing = False diff --git a/test/helper.py b/test/helper.py index 7708e39..0062725 100644 --- a/test/helper.py +++ b/test/helper.py @@ -10,7 +10,7 @@ import musicbrainzngs.musicbrainz from audiorename import Job from audiorename.args import ArgsDefault -from audiorename.meta import set_useragent, query_mbrainz +from audiorename.musicbrainz import set_useragent, query import musicbrainzngs import subprocess from jflib import Capturing @@ -18,7 +18,7 @@ SKIP_API_CALLS = False try: set_useragent() - query_mbrainz('recording', '0480672d-4d88-4824-a06b-917ff408eabe') + query('recording', '0480672d-4d88-4824-a06b-917ff408eabe') except musicbrainzngs.musicbrainz.NetworkError: SKIP_API_CALLS = True diff --git a/test/test_meta.py b/test/test_meta.py index 47338ac..0475885 100644 --- a/test/test_meta.py +++ b/test/test_meta.py @@ -64,77 +64,6 @@ def test_del_attr(self): ) -class TestEnrich(unittest.TestCase): - - def setUp(self): - meta.set_useragent() - - @unittest.skipIf(helper.SKIP_API_CALLS, 'Disable if API not available') - def test_recording_pulp_01(self): - # ['soundtrack', 'Pulp-Fiction', '01.mp3'] - result = meta.query_mbrainz( - 'recording', - '0480672d-4d88-4824-a06b-917ff408eabe', - ) - self.assertEqual(result['id'], - '0480672d-4d88-4824-a06b-917ff408eabe') - - @unittest.skipIf(helper.SKIP_API_CALLS, 'Disable if API not available') - def test_recording_mozart_01(self): - # ['classical', 'Mozart_Horn-concertos', '01.mp3'] - result = meta.query_mbrainz( - 'recording', - '7886ad6c-11af-435b-8ec3-bca5711f7728', - ) - self.assertEqual(result['work-relation-list'][0]['work']['id'], - '21fe0bf0-a040-387c-a39d-369d53c251fe') - - @unittest.skipIf(helper.SKIP_API_CALLS, 'Disable if API not available') - def test_release_pulp_01(self): - # ['soundtrack', 'Pulp-Fiction', '01.mp3'] - result = meta.query_mbrainz( - 'release', - 'ab81edcb-9525-47cd-8247-db4fa969f525', - ) - self.assertEqual(result['release-group']['id'], - '1703cd63-9401-33c0-87c6-50c4ba2e0ba8') - - @unittest.skipIf(helper.SKIP_API_CALLS, 'Disable if API not available') - def test_release_mozart_01(self): - # ['classical', 'Mozart_Horn-concertos', '01.mp3']) - result = meta.query_mbrainz( - 'release', - '5ed650c5-0f72-4b79-80a7-c458c869f53e', - ) - self.assertEqual(result['release-group']['id'], - 'e1fa28f0-e56e-395b-82d3-a8de54e8c627') - - @unittest.skipIf(helper.SKIP_API_CALLS, 'Disable if API not available') - def test_work_mozart_zauberfloete_unit(self): - # recording_id 6a0599ea-5c06-483a-ba66-f3a036da900a - # work_id eafec51f-47c5-3c66-8c36-a524246c85f8 - # Akt 1: 5adc213f-700a-4435-9e95-831ed720f348 - result = meta.query_works_recursively( - 'eafec51f-47c5-3c66-8c36-a524246c85f8', []) - - self.assertEqual(result[0]['id'], - 'eafec51f-47c5-3c66-8c36-a524246c85f8') - self.assertEqual(result[1]['id'], - '5adc213f-700a-4435-9e95-831ed720f348') - self.assertEqual(result[2]['id'], - 'e208c5f5-5d37-3dfc-ac0b-999f207c9e46') - self.assertTrue('artist-relation-list' in result[2]) - - @unittest.skipIf(helper.SKIP_API_CALLS, 'Disable if API not available') - def test_work_kempff_transcription(self): - # work_id 4fba670e-3b8e-4ddf-a3a6-90817c94d6ce - result = meta.query_works_recursively( - '4fba670e-3b8e-4ddf-a3a6-90817c94d6ce', []) - self.assertEqual(result[0]['id'], - '4fba670e-3b8e-4ddf-a3a6-90817c94d6ce') - self.assertEqual(len(result), 1) - - ############################################################################### # Public methods ############################################################################### diff --git a/test/test_musicbrainz.py b/test/test_musicbrainz.py new file mode 100644 index 0000000..2aee828 --- /dev/null +++ b/test/test_musicbrainz.py @@ -0,0 +1,77 @@ +from audiorename.musicbrainz import \ + query, query_works_recursively, set_useragent + +import unittest + +import helper + + +class TestEnrich(unittest.TestCase): + + def setUp(self): + set_useragent() + + @unittest.skipIf(helper.SKIP_API_CALLS, 'Disable if API not available') + def test_recording_pulp_01(self): + # ['soundtrack', 'Pulp-Fiction', '01.mp3'] + result = query( + 'recording', + '0480672d-4d88-4824-a06b-917ff408eabe', + ) + self.assertEqual(result['id'], + '0480672d-4d88-4824-a06b-917ff408eabe') + + @unittest.skipIf(helper.SKIP_API_CALLS, 'Disable if API not available') + def test_recording_mozart_01(self): + # ['classical', 'Mozart_Horn-concertos', '01.mp3'] + result = query( + 'recording', + '7886ad6c-11af-435b-8ec3-bca5711f7728', + ) + self.assertEqual(result['work-relation-list'][0]['work']['id'], + '21fe0bf0-a040-387c-a39d-369d53c251fe') + + @unittest.skipIf(helper.SKIP_API_CALLS, 'Disable if API not available') + def test_release_pulp_01(self): + # ['soundtrack', 'Pulp-Fiction', '01.mp3'] + result = query( + 'release', + 'ab81edcb-9525-47cd-8247-db4fa969f525', + ) + self.assertEqual(result['release-group']['id'], + '1703cd63-9401-33c0-87c6-50c4ba2e0ba8') + + @unittest.skipIf(helper.SKIP_API_CALLS, 'Disable if API not available') + def test_release_mozart_01(self): + # ['classical', 'Mozart_Horn-concertos', '01.mp3']) + result = query( + 'release', + '5ed650c5-0f72-4b79-80a7-c458c869f53e', + ) + self.assertEqual(result['release-group']['id'], + 'e1fa28f0-e56e-395b-82d3-a8de54e8c627') + + @unittest.skipIf(helper.SKIP_API_CALLS, 'Disable if API not available') + def test_work_mozart_zauberfloete_unit(self): + # recording_id 6a0599ea-5c06-483a-ba66-f3a036da900a + # work_id eafec51f-47c5-3c66-8c36-a524246c85f8 + # Akt 1: 5adc213f-700a-4435-9e95-831ed720f348 + result = query_works_recursively( + 'eafec51f-47c5-3c66-8c36-a524246c85f8', []) + + self.assertEqual(result[0]['id'], + 'eafec51f-47c5-3c66-8c36-a524246c85f8') + self.assertEqual(result[1]['id'], + '5adc213f-700a-4435-9e95-831ed720f348') + self.assertEqual(result[2]['id'], + 'e208c5f5-5d37-3dfc-ac0b-999f207c9e46') + self.assertTrue('artist-relation-list' in result[2]) + + @unittest.skipIf(helper.SKIP_API_CALLS, 'Disable if API not available') + def test_work_kempff_transcription(self): + # work_id 4fba670e-3b8e-4ddf-a3a6-90817c94d6ce + result = query_works_recursively( + '4fba670e-3b8e-4ddf-a3a6-90817c94d6ce', []) + self.assertEqual(result[0]['id'], + '4fba670e-3b8e-4ddf-a3a6-90817c94d6ce') + self.assertEqual(len(result), 1)