beets / test / test_mb.py

The default branch has multiple heads

# This file is part of beets.
# Copyright 2013, Adrian Sampson.
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.

"""Tests for MusicBrainz API wrapper.
"""
from _common import unittest
from beets.autotag import mb

class MBAlbumInfoTest(unittest.TestCase):
    def _make_release(self, date_str='2009', tracks=None):
        release = {
            'title': 'ALBUM TITLE',
            'id': 'ALBUM ID',
            'asin': 'ALBUM ASIN',
            'disambiguation': 'R_DISAMBIGUATION',
            'release-group': {
                'type': 'Album',
                'first-release-date': date_str,
                'id': 'RELEASE GROUP ID',
                'disambiguation': 'RG_DISAMBIGUATION',
            },
            'artist-credit': [
                {
                    'artist': {
                        'name': 'ARTIST NAME',
                        'id': 'ARTIST ID',
                        'sort-name': 'ARTIST SORT NAME',
                    },
                    'name': 'ARTIST CREDIT',
                }
            ],
            'date': '3001',
            'medium-list': [],
            'label-info-list': [{
                'catalog-number': 'CATALOG NUMBER',
                'label': {'name': 'LABEL NAME'},
            }],
            'text-representation': {
                'script': 'SCRIPT',
                'language': 'LANGUAGE',
            },
            'country': 'COUNTRY',
            'status': 'STATUS',
        }
        if tracks:
            track_list = []
            for i, track in enumerate(tracks):
                track_list.append({
                    'recording': track,
                    'position': str(i+1),
                })
            release['medium-list'].append({
                'position': '1',
                'track-list': track_list,
                'format': 'FORMAT',
                'title': 'MEDIUM TITLE',
            })
        return release

    def _make_track(self, title, tr_id, duration, artist=False):
        track = {
            'title': title,
            'id': tr_id,
        }
        if duration is not None:
            track['length'] = duration
        if artist:
            track['artist-credit'] = [
                {
                    'artist': {
                        'name': 'TRACK ARTIST NAME',
                        'id': 'TRACK ARTIST ID',
                        'sort-name': 'TRACK ARTIST SORT NAME',
                    },
                    'name': 'TRACK ARTIST CREDIT',
                }
            ]
        return track

    def test_parse_release_with_year(self):
        release = self._make_release('1984')
        d = mb.album_info(release)
        self.assertEqual(d.album, 'ALBUM TITLE')
        self.assertEqual(d.album_id, 'ALBUM ID')
        self.assertEqual(d.artist, 'ARTIST NAME')
        self.assertEqual(d.artist_id, 'ARTIST ID')
        self.assertEqual(d.original_year, 1984)
        self.assertEqual(d.year, 3001)
        self.assertEqual(d.artist_credit, 'ARTIST CREDIT')

    def test_parse_release_type(self):
        release = self._make_release('1984')
        d = mb.album_info(release)
        self.assertEqual(d.albumtype, 'album')

    def test_parse_release_full_date(self):
        release = self._make_release('1987-03-31')
        d = mb.album_info(release)
        self.assertEqual(d.original_year, 1987)
        self.assertEqual(d.original_month, 3)
        self.assertEqual(d.original_day, 31)

    def test_parse_tracks(self):
        tracks = [self._make_track('TITLE ONE', 'ID ONE', 100.0 * 1000.0),
                  self._make_track('TITLE TWO', 'ID TWO', 200.0 * 1000.0)]
        release = self._make_release(tracks=tracks)

        d = mb.album_info(release)
        t = d.tracks
        self.assertEqual(len(t), 2)
        self.assertEqual(t[0].title, 'TITLE ONE')
        self.assertEqual(t[0].track_id, 'ID ONE')
        self.assertEqual(t[0].length, 100.0)
        self.assertEqual(t[1].title, 'TITLE TWO')
        self.assertEqual(t[1].track_id, 'ID TWO')
        self.assertEqual(t[1].length, 200.0)

    def test_parse_track_indices(self):
        tracks = [self._make_track('TITLE ONE', 'ID ONE', 100.0 * 1000.0),
                  self._make_track('TITLE TWO', 'ID TWO', 200.0 * 1000.0)]
        release = self._make_release(tracks=tracks)

        d = mb.album_info(release)
        t = d.tracks
        self.assertEqual(t[0].medium_index, 1)
        self.assertEqual(t[0].index, 1)
        self.assertEqual(t[1].medium_index, 2)
        self.assertEqual(t[1].index, 2)

    def test_parse_medium_numbers_single_medium(self):
        tracks = [self._make_track('TITLE ONE', 'ID ONE', 100.0 * 1000.0),
                  self._make_track('TITLE TWO', 'ID TWO', 200.0 * 1000.0)]
        release = self._make_release(tracks=tracks)

        d = mb.album_info(release)
        self.assertEqual(d.mediums, 1)
        t = d.tracks
        self.assertEqual(t[0].medium, 1)
        self.assertEqual(t[1].medium, 1)

    def test_parse_medium_numbers_two_mediums(self):
        tracks = [self._make_track('TITLE ONE', 'ID ONE', 100.0 * 1000.0),
                  self._make_track('TITLE TWO', 'ID TWO', 200.0 * 1000.0)]
        release = self._make_release(tracks=[tracks[0]])
        second_track_list = [{
            'recording': tracks[1],
            'position': '1',
        }]
        release['medium-list'].append({
            'position': '2',
            'track-list': second_track_list,
        })

        d = mb.album_info(release)
        self.assertEqual(d.mediums, 2)
        t = d.tracks
        self.assertEqual(t[0].medium, 1)
        self.assertEqual(t[0].medium_index, 1)
        self.assertEqual(t[0].index, 1)
        self.assertEqual(t[1].medium, 2)
        self.assertEqual(t[1].medium_index, 1)
        self.assertEqual(t[1].index, 2)

    def test_parse_release_year_month_only(self):
        release = self._make_release('1987-03')
        d = mb.album_info(release)
        self.assertEqual(d.original_year, 1987)
        self.assertEqual(d.original_month, 3)

    def test_no_durations(self):
        tracks = [self._make_track('TITLE', 'ID', None)]
        release = self._make_release(tracks=tracks)
        d = mb.album_info(release)
        self.assertEqual(d.tracks[0].length, None)

    def test_no_release_date(self):
        release = self._make_release(None)
        d = mb.album_info(release)
        self.assertFalse(d.original_year)
        self.assertFalse(d.original_month)
        self.assertFalse(d.original_day)

    def test_various_artists_defaults_false(self):
        release = self._make_release(None)
        d = mb.album_info(release)
        self.assertFalse(d.va)

    def test_detect_various_artists(self):
        release = self._make_release(None)
        release['artist-credit'][0]['artist']['id'] = \
            mb.VARIOUS_ARTISTS_ID
        d = mb.album_info(release)
        self.assertTrue(d.va)

    def test_parse_artist_sort_name(self):
        release = self._make_release(None)
        d = mb.album_info(release)
        self.assertEqual(d.artist_sort, 'ARTIST SORT NAME')

    def test_parse_releasegroupid(self):
        release = self._make_release(None)
        d = mb.album_info(release)
        self.assertEqual(d.releasegroup_id, 'RELEASE GROUP ID')

    def test_parse_asin(self):
        release = self._make_release(None)
        d = mb.album_info(release)
        self.assertEqual(d.asin, 'ALBUM ASIN')

    def test_parse_catalognum(self):
        release = self._make_release(None)
        d = mb.album_info(release)
        self.assertEqual(d.catalognum, 'CATALOG NUMBER')

    def test_parse_textrepr(self):
        release = self._make_release(None)
        d = mb.album_info(release)
        self.assertEqual(d.script, 'SCRIPT')
        self.assertEqual(d.language, 'LANGUAGE')

    def test_parse_country(self):
        release = self._make_release(None)
        d = mb.album_info(release)
        self.assertEqual(d.country, 'COUNTRY')

    def test_parse_status(self):
        release = self._make_release(None)
        d = mb.album_info(release)
        self.assertEqual(d.albumstatus, 'STATUS')

    def test_parse_media(self):
        tracks = [self._make_track('TITLE ONE', 'ID ONE', 100.0 * 1000.0),
                  self._make_track('TITLE TWO', 'ID TWO', 200.0 * 1000.0)]
        release = self._make_release(None, tracks=tracks)
        d = mb.album_info(release)
        self.assertEqual(d.media, 'FORMAT')

    def test_parse_disambig(self):
        release = self._make_release(None)
        d = mb.album_info(release)
        self.assertEqual(d.albumdisambig,
                         'RG_DISAMBIGUATION, R_DISAMBIGUATION')

    def test_parse_disctitle(self):
        tracks = [self._make_track('TITLE ONE', 'ID ONE', 100.0 * 1000.0),
                  self._make_track('TITLE TWO', 'ID TWO', 200.0 * 1000.0)]
        release = self._make_release(None, tracks=tracks)
        d = mb.album_info(release)
        t = d.tracks
        self.assertEqual(t[0].disctitle, 'MEDIUM TITLE')
        self.assertEqual(t[1].disctitle, 'MEDIUM TITLE')

    def test_missing_language(self):
        release = self._make_release(None)
        del release['text-representation']['language']
        d = mb.album_info(release)
        self.assertEqual(d.language, None)

    def test_parse_track_artist(self):
        tracks = [self._make_track('a', 'b', 1, True)]
        release = self._make_release(None, tracks=tracks)
        track = mb.album_info(release).tracks[0]
        self.assertEqual(track.artist, 'TRACK ARTIST NAME')
        self.assertEqual(track.artist_id, 'TRACK ARTIST ID')
        self.assertEqual(track.artist_sort, 'TRACK ARTIST SORT NAME')
        self.assertEqual(track.artist_credit, 'TRACK ARTIST CREDIT')

class ArtistFlatteningTest(unittest.TestCase):
    def _credit_dict(self, suffix=''):
        return {
            'artist': {
                'name': 'NAME' + suffix,
                'sort-name': 'SORT' + suffix,
            },
            'name': 'CREDIT' + suffix,
        }

    def test_single_artist(self):
        a, s, c = mb._flatten_artist_credit([self._credit_dict()])
        self.assertEqual(a, 'NAME')
        self.assertEqual(s, 'SORT')
        self.assertEqual(c, 'CREDIT')

    def test_two_artists(self):
        a, s, c = mb._flatten_artist_credit(
            [self._credit_dict('a'), ' AND ', self._credit_dict('b')]
        )
        self.assertEqual(a, 'NAMEa AND NAMEb')
        self.assertEqual(s, 'SORTa AND SORTb')
        self.assertEqual(c, 'CREDITa AND CREDITb')

def suite():
    return unittest.TestLoader().loadTestsFromName(__name__)

if __name__ == '__main__':
    unittest.main(defaultTest='suite')
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.