def test_scan(self, mock_scan):
        mock_scan.return_value = {
            'tags': {
                'image': [GIF_DATA, PNG_DATA],
                'preview-image': [JPEG_DATA]
            }
        }

        album = Album(name='foo')
        track = Track(uri=b'local:track:foo.mp3', album=album)
        images = ['/images/' + name for name in GIF_NAME, PNG_NAME, JPEG_NAME]
        image_track = track.copy(album=album.copy(images=images))

        self.library.add(track)
        mock_library.add.assert_called_with(image_track, None, None)
        self.assertTrue(os.path.isfile(os.path.join(self.tempdir, GIF_NAME)))
        self.assertTrue(os.path.isfile(os.path.join(self.tempdir, PNG_NAME)))
        self.assertTrue(os.path.isfile(os.path.join(self.tempdir, JPEG_NAME)))

        self.library.close()
        self.assertEqual(os.listdir(self.tempdir), [])
示例#2
0
 def test_images(self):
     image = 'data:foobar'
     album = Album(images=[image])
     self.assertIn(image, album.images)
     self.assertRaises(AttributeError, setattr, album, 'images', None)
示例#3
0
 def test_date(self):
     date = '1977-01-01'
     album = Album(date=date)
     self.assertEqual(album.date, date)
     self.assertRaises(AttributeError, setattr, album, 'date', None)
示例#4
0
 def test_num_tracks(self):
     num_tracks = 11
     album = Album(num_tracks=num_tracks)
     self.assertEqual(album.num_tracks, num_tracks)
     self.assertRaises(AttributeError, setattr, album, 'num_tracks', None)
示例#5
0
 def test_artists(self):
     artist = Artist()
     album = Album(artists=[artist])
     self.assertIn(artist, album.artists)
     self.assertRaises(AttributeError, setattr, album, 'artists', None)
示例#6
0
 def test_uri(self):
     uri = 'an_uri'
     album = Album(uri=uri)
     self.assertEqual(album.uri, uri)
     self.assertRaises(AttributeError, setattr, album, 'uri', None)
示例#7
0
 def test_albums(self):
     albums = [Album(), Album(), Album()]
     result = SearchResult(albums=albums)
     self.assertEqual(list(result.albums), albums)
     self.assertRaises(AttributeError, setattr, result, 'albums', None)
示例#8
0
 def test_uri(self):
     uri = 'an_uri'
     album = Album(uri=uri)
     self.assertEqual(album.uri, uri)
     with self.assertRaises(AttributeError):
         album.uri = None
示例#9
0
 def test_images(self):
     image = 'data:foobar'
     album = Album(images=[image])
     self.assertIn(image, album.images)
     with self.assertRaises(AttributeError):
         album.images = None
示例#10
0
 def test_musicbrainz_id(self):
     mb_id = 'mb-id'
     album = Album(musicbrainz_id=mb_id)
     self.assertEqual(album.musicbrainz_id, mb_id)
     with self.assertRaises(AttributeError):
         album.musicbrainz_id = None
示例#11
0
 def test_date(self):
     date = '1977-01-01'
     album = Album(date=date)
     self.assertEqual(album.date, date)
     with self.assertRaises(AttributeError):
         album.date = None
示例#12
0
 def test_num_discs(self):
     num_discs = 2
     album = Album(num_discs=num_discs)
     self.assertEqual(album.num_discs, num_discs)
     with self.assertRaises(AttributeError):
         album.num_discs = None
示例#13
0
 def test_num_tracks(self):
     num_tracks = 11
     album = Album(num_tracks=num_tracks)
     self.assertEqual(album.num_tracks, num_tracks)
     with self.assertRaises(AttributeError):
         album.num_tracks = None
示例#14
0
 def test_artists(self):
     artist = Artist()
     album = Album(artists=[artist])
     self.assertIn(artist, album.artists)
     with self.assertRaises(AttributeError):
         album.artists = None
示例#15
0
 def test_name(self):
     name = 'a name'
     album = Album(name=name)
     self.assertEqual(album.name, name)
     with self.assertRaises(AttributeError):
         album.name = None
示例#16
0
 def test_invalid_kwarg(self):
     test = lambda: Album(foo='baz')
     self.assertRaises(TypeError, test)
示例#17
0
 def test_copying_album(self):
     album = Album()
     self.compare(album, album.copy())
示例#18
0
 def test_replace_album(self):
     album = Album()
     self.compare(album, album.replace())
示例#19
0
 def station_to_track(self, station):
     ref = self.station_to_ref(station)
     return Track(uri=ref.uri, name=ref.name, album=Album(uri=ref.uri, name=ref.name),
                  artists=[Artist(uri=ref.uri, name=ref.name)])
示例#20
0
 def test_ne_album(self):
     track1 = Track(album=Album(name='name1'))
     track2 = Track(album=Album(name='name2'))
     self.assertNotEqual(track1, track2)
     self.assertNotEqual(hash(track1), hash(track2))
示例#21
0
 def test_copying_album(self):
     album = Album()
     self.compare(album, album.copy())
示例#22
0
    def parse_track(self, data, remote_url=False):
        if not data:
            return None
        if not data['streamable']:
            logger.info(
                "'%s' can't be streamed from SoundCloud" % data.get('title'))
            return None
        if not data['kind'] == 'track':
            logger.debug('%s is not track' % data.get('title'))
            return None

        # NOTE kwargs dict keys must be bytestrings to work on Python < 2.6.5
        # See https://github.com/mopidy/mopidy/issues/302 for details.

        track_kwargs = {}
        artist_kwargs = {}
        album_kwargs = {}

        if 'title' in data:
            name = data['title']
            label_name = data.get('label_name')

            if bool(label_name):
                track_kwargs[b'name'] = name
                artist_kwargs[b'name'] = label_name
            else:
                track_kwargs[b'name'] = name
                artist_kwargs[b'name'] = data.get('user').get('username')

            album_kwargs[b'name'] = 'SoundCloud'

        if 'date' in data:
            track_kwargs[b'date'] = data['date']

        if remote_url:
            if not self.can_be_streamed(data['stream_url']):
                logger.info(
                    "'%s' can't be streamed from SoundCloud" % data.get(
                        'title'))
                return None
            track_kwargs[b'uri'] = self.get_streamble_url(data['stream_url'])
        else:
            track_kwargs[b'uri'] = 'soundcloud:song/%s.%s' % (
                readable_url(data.get('title')), data.get('id')
            )

        track_kwargs[b'length'] = int(data.get('duration', 0))
        track_kwargs[b'comment'] = data.get('permalink_url', '')

        if artist_kwargs:
            artist = Artist(**artist_kwargs)
            track_kwargs[b'artists'] = [artist]

        if album_kwargs:
            if 'artwork_url' in data and data['artwork_url']:
                album_kwargs[b'images'] = [data['artwork_url']]
            else:
                image = data.get('user').get('avatar_url')
                album_kwargs[b'images'] = [image]

            album = Album(**album_kwargs)
            track_kwargs[b'album'] = album

        track = Track(**track_kwargs)
        return track
示例#23
0
 def test_name(self):
     name = 'a name'
     album = Album(name=name)
     self.assertEqual(album.name, name)
     self.assertRaises(AttributeError, setattr, album, 'name', None)
示例#24
0
    def test_encoding_is_latin1(self):
        uris = parse_m3u(path_to_data_dir('encoding.m3u'), data_dir)
        self.assertEqual([encoded_uri], uris)

    def test_open_missing_file(self):
        uris = parse_m3u(path_to_data_dir('non-existant.m3u'), data_dir)
        self.assertEqual([], uris)


class URItoM3UTest(unittest.TestCase):
    pass


expected_artists = [Artist(name='name')]
expected_albums = [
    Album(name='albumname', artists=expected_artists, num_tracks=2)
]
expected_tracks = []


def generate_track(path, ident):
    uri = path_to_uri(path_to_data_dir(path))
    track = Track(uri=uri,
                  name='trackname',
                  artists=expected_artists,
                  album=expected_albums[0],
                  track_no=1,
                  date='2006',
                  length=4000)
    expected_tracks.append(track)
示例#25
0
 def test_artists_none(self):
     self.assertEqual(set(), Album(artists=None).artists)
示例#26
0
def find_exact(tracks, query=None, uris=None):
    # TODO Only return results within URI roots given by ``uris``

    if query is None:
        query = {}

    _validate_query(query)

    for (field, values) in query.iteritems():
        if not hasattr(values, '__iter__'):
            values = [values]
        # FIXME this is bound to be slow for large libraries
        for value in values:
            if field == 'track_no':
                q = _convert_to_int(value)
            else:
                q = value.strip()

            uri_filter = lambda t: q == t.uri
            track_name_filter = lambda t: q == t.name
            album_filter = lambda t: q == getattr(t, 'album', Album()).name
            artist_filter = lambda t: filter(lambda a: q == a.name, t.artists)
            albumartist_filter = lambda t: any(
                [q == a.name for a in getattr(t.album, 'artists', [])])
            composer_filter = lambda t: any(
                [q == a.name for a in getattr(t, 'composers', [])])
            performer_filter = lambda t: any(
                [q == a.name for a in getattr(t, 'performers', [])])
            track_no_filter = lambda t: q == t.track_no
            genre_filter = lambda t: t.genre and q == t.genre
            date_filter = lambda t: q == t.date
            comment_filter = lambda t: q == t.comment
            any_filter = lambda t: (
                uri_filter(t) or track_name_filter(t) or album_filter(t) or
                artist_filter(t) or albumartist_filter(t) or composer_filter(t)
                or performer_filter(t) or track_no_filter(t) or genre_filter(
                    t) or date_filter(t) or comment_filter(t))

            if field == 'uri':
                tracks = filter(uri_filter, tracks)
            elif field == 'track_name':
                tracks = filter(track_name_filter, tracks)
            elif field == 'album':
                tracks = filter(album_filter, tracks)
            elif field == 'artist':
                tracks = filter(artist_filter, tracks)
            elif field == 'albumartist':
                tracks = filter(albumartist_filter, tracks)
            elif field == 'composer':
                tracks = filter(composer_filter, tracks)
            elif field == 'performer':
                tracks = filter(performer_filter, tracks)
            elif field == 'track_no':
                tracks = filter(track_no_filter, tracks)
            elif field == 'genre':
                tracks = filter(genre_filter, tracks)
            elif field == 'date':
                tracks = filter(date_filter, tracks)
            elif field == 'comment':
                tracks = filter(comment_filter, tracks)
            elif field == 'any':
                tracks = filter(any_filter, tracks)
            else:
                raise LookupError('Invalid lookup field: %s' % field)

    # TODO: add local:search:<query>
    return SearchResult(uri='local:search', tracks=tracks)
示例#27
0
 def test_num_discs(self):
     num_discs = 2
     album = Album(num_discs=num_discs)
     self.assertEqual(album.num_discs, num_discs)
     self.assertRaises(AttributeError, setattr, album, 'num_discs', None)
示例#28
0
 def to_mopidy_album(cls, spotify_album):
     if spotify_album is None or not spotify_album.is_loaded():
         return Album(name=u'[loading...]')
     # TODO pyspotify got much more data on albums than this
     return Album(name=spotify_album.name())
示例#29
0
 def test_musicbrainz_id(self):
     mb_id = 'mb-id'
     album = Album(musicbrainz_id=mb_id)
     self.assertEqual(album.musicbrainz_id, mb_id)
     self.assertRaises(AttributeError, setattr, album, 'musicbrainz_id',
                       None)
示例#30
0
class TrackMpdFormatTest(unittest.TestCase):
    track = Track(
        uri='à uri',
        artists=[Artist(name='an artist')],
        name='a nàme',
        album=Album(name='an album',
                    num_tracks=13,
                    artists=[Artist(name='an other artist')],
                    uri='urischeme:àlbum:12345',
                    images=['image1']),
        track_no=7,
        composers=[Artist(name='a composer')],
        performers=[Artist(name='a performer')],
        genre='a genre',
        date='1977-01-01',
        disc_no=1,
        comment='a comment',
        length=137000,
    )

    def setUp(self):  # noqa: N802
        self.media_dir = '/dir/subdir'
        path.mtime.set_fake_time(1234567)

    def tearDown(self):  # noqa: N802
        path.mtime.undo_fake()

    def test_track_to_mpd_format_for_empty_track(self):
        result = translator.track_to_mpd_format(
            Track(uri='a uri', length=137000))
        self.assertIn(('file', 'a uri'), result)
        self.assertIn(('Time', 137), result)
        self.assertNotIn(('Artist', ''), result)
        self.assertNotIn(('Title', ''), result)
        self.assertNotIn(('Album', ''), result)
        self.assertNotIn(('Track', 0), result)
        self.assertNotIn(('Date', ''), result)
        self.assertEqual(len(result), 2)

    def test_track_to_mpd_format_with_position(self):
        result = translator.track_to_mpd_format(Track(), position=1)
        self.assertNotIn(('Pos', 1), result)

    def test_track_to_mpd_format_with_tlid(self):
        result = translator.track_to_mpd_format(TlTrack(1, Track()))
        self.assertNotIn(('Id', 1), result)

    def test_track_to_mpd_format_with_position_and_tlid(self):
        result = translator.track_to_mpd_format(TlTrack(2, Track(uri='a uri')),
                                                position=1)
        self.assertIn(('Pos', 1), result)
        self.assertIn(('Id', 2), result)

    def test_track_to_mpd_format_for_nonempty_track(self):
        result = translator.track_to_mpd_format(TlTrack(122, self.track),
                                                position=9)
        self.assertIn(('file', 'à uri'), result)
        self.assertIn(('Time', 137), result)
        self.assertIn(('Artist', 'an artist'), result)
        self.assertIn(('Title', 'a nàme'), result)
        self.assertIn(('Album', 'an album'), result)
        self.assertIn(('AlbumArtist', 'an other artist'), result)
        self.assertIn(('Composer', 'a composer'), result)
        self.assertIn(('Performer', 'a performer'), result)
        self.assertIn(('Genre', 'a genre'), result)
        self.assertIn(('Track', '7/13'), result)
        self.assertIn(('Date', '1977-01-01'), result)
        self.assertIn(('Disc', 1), result)
        self.assertIn(('Pos', 9), result)
        self.assertIn(('Id', 122), result)
        self.assertIn(('X-AlbumUri', 'urischeme:àlbum:12345'), result)
        self.assertIn(('X-AlbumImage', 'image1'), result)
        self.assertNotIn(('Comment', 'a comment'), result)
        self.assertEqual(len(result), 16)

    def test_track_to_mpd_format_with_last_modified(self):
        track = self.track.replace(last_modified=995303899000)
        result = translator.track_to_mpd_format(track)
        self.assertIn(('Last-Modified', '2001-07-16T17:18:19Z'), result)

    def test_track_to_mpd_format_with_last_modified_of_zero(self):
        track = self.track.replace(last_modified=0)
        result = translator.track_to_mpd_format(track)
        keys = [k for k, v in result]
        self.assertNotIn('Last-Modified', keys)

    def test_track_to_mpd_format_musicbrainz_trackid(self):
        track = self.track.replace(musicbrainz_id='foo')
        result = translator.track_to_mpd_format(track)
        self.assertIn(('MUSICBRAINZ_TRACKID', 'foo'), result)

    def test_track_to_mpd_format_musicbrainz_albumid(self):
        album = self.track.album.replace(musicbrainz_id='foo')
        track = self.track.replace(album=album)
        result = translator.track_to_mpd_format(track)
        self.assertIn(('MUSICBRAINZ_ALBUMID', 'foo'), result)

    def test_track_to_mpd_format_musicbrainz_albumartistid(self):
        artist = list(self.track.artists)[0].replace(musicbrainz_id='foo')
        album = self.track.album.replace(artists=[artist])
        track = self.track.replace(album=album)
        result = translator.track_to_mpd_format(track)
        self.assertIn(('MUSICBRAINZ_ALBUMARTISTID', 'foo'), result)

    def test_track_to_mpd_format_musicbrainz_artistid(self):
        artist = list(self.track.artists)[0].replace(musicbrainz_id='foo')
        track = self.track.replace(artists=[artist])
        result = translator.track_to_mpd_format(track)
        self.assertIn(('MUSICBRAINZ_ARTISTID', 'foo'), result)

    def test_concat_multi_values(self):
        artists = [Artist(name='ABBA'), Artist(name='Beatles')]
        translated = translator.concat_multi_values(artists, 'name')
        self.assertEqual(translated, 'ABBA;Beatles')

    def test_concat_multi_values_artist_with_no_name(self):
        artists = [Artist(name=None)]
        translated = translator.concat_multi_values(artists, 'name')
        self.assertEqual(translated, '')

    def test_concat_multi_values_artist_with_no_musicbrainz_id(self):
        artists = [Artist(name='Jah Wobble')]
        translated = translator.concat_multi_values(artists, 'musicbrainz_id')
        self.assertEqual(translated, '')

    def test_track_to_mpd_format_with_stream_title(self):
        result = translator.track_to_mpd_format(self.track, stream_title='foo')
        self.assertIn(('Name', 'a nàme'), result)
        self.assertIn(('Title', 'foo'), result)

    def test_track_to_mpd_format_with_empty_stream_title(self):
        result = translator.track_to_mpd_format(self.track, stream_title='')
        self.assertIn(('Name', 'a nàme'), result)
        self.assertNotIn(('Title', ''), result)

    def test_track_to_mpd_format_with_stream_and_no_track_name(self):
        track = self.track.replace(name=None)
        result = translator.track_to_mpd_format(track, stream_title='foo')
        self.assertNotIn(('Name', ''), result)
        self.assertIn(('Title', 'foo'), result)
示例#31
0
 def test_images_none(self):
     self.assertEqual(set(), Album(images=None).images)
示例#32
0
class LocalLibraryProviderTest(unittest.TestCase):
    artists = [
        Artist(name='artist1'),
        Artist(name='artist2'),
        Artist(name='artist3'),
        Artist(name='artist4'),
        Artist(name='artist5'),
        Artist(name='artist6'),
        Artist(),
    ]

    albums = [
        Album(name='album1', artists=[artists[0]]),
        Album(name='album2', artists=[artists[1]]),
        Album(name='album3', artists=[artists[2]]),
        Album(name='album4'),
        Album(artists=[artists[-1]]),
    ]

    tracks = [
        Track(
            uri='local:track:path1', name='track1',
            artists=[artists[0]], album=albums[0],
            date='2001-02-03', length=4000, track_no=1),
        Track(
            uri='local:track:path2', name='track2',
            artists=[artists[1]], album=albums[1],
            date='2002', length=4000, track_no=2),
        Track(
            uri='local:track:path3', name='track3',
            artists=[artists[3]], album=albums[2],
            date='2003', length=4000, track_no=3),
        Track(
            uri='local:track:path4', name='track4',
            artists=[artists[2]], album=albums[3],
            date='2004', length=60000, track_no=4,
            comment='This is a fantastic track'),
        Track(
            uri='local:track:path5', name='track5', genre='genre1',
            album=albums[3], length=4000, composers=[artists[4]]),
        Track(
            uri='local:track:path6', name='track6', genre='genre2',
            album=albums[3], length=4000, performers=[artists[5]]),
        Track(uri='local:track:nameless', album=albums[-1]),
    ]

    config = {
        'local': {
            'media_dir': path_to_data_dir(''),
            'data_dir': path_to_data_dir(''),
            'playlists_dir': b'',
            'library': 'json',
        },
    }

    def setUp(self):  # noqa: N802
        actor.LocalBackend.libraries = [json.JsonLibrary]
        self.backend = actor.LocalBackend.start(
            config=self.config, audio=None).proxy()
        self.core = core.Core(backends=[self.backend])
        self.library = self.core.library

    def tearDown(self):  # noqa: N802
        pykka.ActorRegistry.stop_all()
        actor.LocalBackend.libraries = []

    def test_refresh(self):
        self.library.refresh()

    @unittest.SkipTest
    def test_refresh_uri(self):
        pass

    def test_refresh_missing_uri(self):
        # Verifies that https://github.com/mopidy/mopidy/issues/500
        # has been fixed.

        tmpdir = tempfile.mkdtemp()
        try:
            tmplib = os.path.join(tmpdir, 'library.json.gz')
            shutil.copy(path_to_data_dir('library.json.gz'), tmplib)

            config = {'local': self.config['local'].copy()}
            config['local']['data_dir'] = tmpdir
            backend = actor.LocalBackend(config=config, audio=None)

            # Sanity check that value is in the library
            result = backend.library.lookup(self.tracks[0].uri)
            self.assertEqual(result, self.tracks[0:1])

            # Clear and refresh.
            open(tmplib, 'w').close()
            backend.library.refresh()

            # Now it should be gone.
            result = backend.library.lookup(self.tracks[0].uri)
            self.assertEqual(result, [])

        finally:
            shutil.rmtree(tmpdir)

    @unittest.SkipTest
    def test_browse(self):
        pass  # TODO

    def test_lookup(self):
        tracks = self.library.lookup(self.tracks[0].uri)
        self.assertEqual(tracks, self.tracks[0:1])

    def test_lookup_unknown_track(self):
        tracks = self.library.lookup('fake uri')
        self.assertEqual(tracks, [])

    # test backward compatibility with local libraries returning a
    # single Track
    @mock.patch.object(json.JsonLibrary, 'lookup')
    def test_lookup_return_single_track(self, mock_lookup):
        backend = actor.LocalBackend(config=self.config, audio=None)

        mock_lookup.return_value = self.tracks[0]
        tracks = backend.library.lookup(self.tracks[0].uri)
        mock_lookup.assert_called_with(self.tracks[0].uri)
        self.assertEqual(tracks, self.tracks[0:1])

        mock_lookup.return_value = None
        tracks = backend.library.lookup('fake uri')
        mock_lookup.assert_called_with('fake uri')
        self.assertEqual(tracks, [])

    # TODO: move to search_test module
    def test_find_exact_no_hits(self):
        result = self.library.find_exact(track_name=['unknown track'])
        self.assertEqual(list(result[0].tracks), [])

        result = self.library.find_exact(artist=['unknown artist'])
        self.assertEqual(list(result[0].tracks), [])

        result = self.library.find_exact(albumartist=['unknown albumartist'])
        self.assertEqual(list(result[0].tracks), [])

        result = self.library.find_exact(composer=['unknown composer'])
        self.assertEqual(list(result[0].tracks), [])

        result = self.library.find_exact(performer=['unknown performer'])
        self.assertEqual(list(result[0].tracks), [])

        result = self.library.find_exact(album=['unknown album'])
        self.assertEqual(list(result[0].tracks), [])

        result = self.library.find_exact(date=['1990'])
        self.assertEqual(list(result[0].tracks), [])

        result = self.library.find_exact(genre=['unknown genre'])
        self.assertEqual(list(result[0].tracks), [])

        result = self.library.find_exact(track_no=['9'])
        self.assertEqual(list(result[0].tracks), [])

        result = self.library.find_exact(track_no=['no_match'])
        self.assertEqual(list(result[0].tracks), [])

        result = self.library.find_exact(comment=['fake comment'])
        self.assertEqual(list(result[0].tracks), [])

        result = self.library.find_exact(uri=['fake uri'])
        self.assertEqual(list(result[0].tracks), [])

        result = self.library.find_exact(any=['unknown any'])
        self.assertEqual(list(result[0].tracks), [])

    def test_find_exact_uri(self):
        track_1_uri = 'local:track:path1'
        result = self.library.find_exact(uri=track_1_uri)
        self.assertEqual(list(result[0].tracks), self.tracks[:1])

        track_2_uri = 'local:track:path2'
        result = self.library.find_exact(uri=track_2_uri)
        self.assertEqual(list(result[0].tracks), self.tracks[1:2])

    def test_find_exact_track_name(self):
        result = self.library.find_exact(track_name=['track1'])
        self.assertEqual(list(result[0].tracks), self.tracks[:1])

        result = self.library.find_exact(track_name=['track2'])
        self.assertEqual(list(result[0].tracks), self.tracks[1:2])

    def test_find_exact_artist(self):
        result = self.library.find_exact(artist=['artist1'])
        self.assertEqual(list(result[0].tracks), self.tracks[:1])

        result = self.library.find_exact(artist=['artist2'])
        self.assertEqual(list(result[0].tracks), self.tracks[1:2])

        result = self.library.find_exact(artist=['artist3'])
        self.assertEqual(list(result[0].tracks), self.tracks[3:4])

    def test_find_exact_composer(self):
        result = self.library.find_exact(composer=['artist5'])
        self.assertEqual(list(result[0].tracks), self.tracks[4:5])

        result = self.library.find_exact(composer=['artist6'])
        self.assertEqual(list(result[0].tracks), [])

    def test_find_exact_performer(self):
        result = self.library.find_exact(performer=['artist6'])
        self.assertEqual(list(result[0].tracks), self.tracks[5:6])

        result = self.library.find_exact(performer=['artist5'])
        self.assertEqual(list(result[0].tracks), [])

    def test_find_exact_album(self):
        result = self.library.find_exact(album=['album1'])
        self.assertEqual(list(result[0].tracks), self.tracks[:1])

        result = self.library.find_exact(album=['album2'])
        self.assertEqual(list(result[0].tracks), self.tracks[1:2])

    def test_find_exact_albumartist(self):
        # Artist is both track artist and album artist
        result = self.library.find_exact(albumartist=['artist1'])
        self.assertEqual(list(result[0].tracks), [self.tracks[0]])

        # Artist is both track and album artist
        result = self.library.find_exact(albumartist=['artist2'])
        self.assertEqual(list(result[0].tracks), [self.tracks[1]])

        # Artist is just album artist
        result = self.library.find_exact(albumartist=['artist3'])
        self.assertEqual(list(result[0].tracks), [self.tracks[2]])

    def test_find_exact_track_no(self):
        result = self.library.find_exact(track_no=['1'])
        self.assertEqual(list(result[0].tracks), self.tracks[:1])

        result = self.library.find_exact(track_no=['2'])
        self.assertEqual(list(result[0].tracks), self.tracks[1:2])

    def test_find_exact_genre(self):
        result = self.library.find_exact(genre=['genre1'])
        self.assertEqual(list(result[0].tracks), self.tracks[4:5])

        result = self.library.find_exact(genre=['genre2'])
        self.assertEqual(list(result[0].tracks), self.tracks[5:6])

    def test_find_exact_date(self):
        result = self.library.find_exact(date=['2001'])
        self.assertEqual(list(result[0].tracks), [])

        result = self.library.find_exact(date=['2001-02-03'])
        self.assertEqual(list(result[0].tracks), self.tracks[:1])

        result = self.library.find_exact(date=['2002'])
        self.assertEqual(list(result[0].tracks), self.tracks[1:2])

    def test_find_exact_comment(self):
        result = self.library.find_exact(
            comment=['This is a fantastic track'])
        self.assertEqual(list(result[0].tracks), self.tracks[3:4])

        result = self.library.find_exact(
            comment=['This is a fantastic'])
        self.assertEqual(list(result[0].tracks), [])

    def test_find_exact_any(self):
        # Matches on track artist
        result = self.library.find_exact(any=['artist1'])
        self.assertEqual(list(result[0].tracks), self.tracks[:1])

        result = self.library.find_exact(any=['artist2'])
        self.assertEqual(list(result[0].tracks), self.tracks[1:2])

        # Matches on track name
        result = self.library.find_exact(any=['track1'])
        self.assertEqual(list(result[0].tracks), self.tracks[:1])

        result = self.library.find_exact(any=['track2'])
        self.assertEqual(list(result[0].tracks), self.tracks[1:2])

        # Matches on track album
        result = self.library.find_exact(any=['album1'])
        self.assertEqual(list(result[0].tracks), self.tracks[:1])

        # Matches on track album artists
        result = self.library.find_exact(any=['artist3'])
        self.assertEqual(len(result[0].tracks), 2)
        self.assertIn(self.tracks[2], result[0].tracks)
        self.assertIn(self.tracks[3], result[0].tracks)

        # Matches on track composer
        result = self.library.find_exact(any=['artist5'])
        self.assertEqual(list(result[0].tracks), self.tracks[4:5])

        # Matches on track performer
        result = self.library.find_exact(any=['artist6'])
        self.assertEqual(list(result[0].tracks), self.tracks[5:6])

        # Matches on track genre
        result = self.library.find_exact(any=['genre1'])
        self.assertEqual(list(result[0].tracks), self.tracks[4:5])

        result = self.library.find_exact(any=['genre2'])
        self.assertEqual(list(result[0].tracks), self.tracks[5:6])

        # Matches on track date
        result = self.library.find_exact(any=['2002'])
        self.assertEqual(list(result[0].tracks), self.tracks[1:2])

        # Matches on track comment
        result = self.library.find_exact(
            any=['This is a fantastic track'])
        self.assertEqual(list(result[0].tracks), self.tracks[3:4])

        # Matches on URI
        result = self.library.find_exact(any=['local:track:path1'])
        self.assertEqual(list(result[0].tracks), self.tracks[:1])

    def test_find_exact_wrong_type(self):
        with self.assertRaises(LookupError):
            self.library.find_exact(wrong=['test'])

    def test_find_exact_with_empty_query(self):
        with self.assertRaises(LookupError):
            self.library.find_exact(artist=[''])

        with self.assertRaises(LookupError):
            self.library.find_exact(albumartist=[''])

        with self.assertRaises(LookupError):
            self.library.find_exact(track_name=[''])

        with self.assertRaises(LookupError):
            self.library.find_exact(composer=[''])

        with self.assertRaises(LookupError):
            self.library.find_exact(performer=[''])

        with self.assertRaises(LookupError):
            self.library.find_exact(album=[''])

        with self.assertRaises(LookupError):
            self.library.find_exact(track_no=[''])

        with self.assertRaises(LookupError):
            self.library.find_exact(genre=[''])

        with self.assertRaises(LookupError):
            self.library.find_exact(date=[''])

        with self.assertRaises(LookupError):
            self.library.find_exact(comment=[''])

        with self.assertRaises(LookupError):
            self.library.find_exact(any=[''])

    def test_search_no_hits(self):
        result = self.library.search(track_name=['unknown track'])
        self.assertEqual(list(result[0].tracks), [])

        result = self.library.search(artist=['unknown artist'])
        self.assertEqual(list(result[0].tracks), [])

        result = self.library.search(albumartist=['unknown albumartist'])
        self.assertEqual(list(result[0].tracks), [])

        result = self.library.search(composer=['unknown composer'])
        self.assertEqual(list(result[0].tracks), [])

        result = self.library.search(performer=['unknown performer'])
        self.assertEqual(list(result[0].tracks), [])

        result = self.library.search(album=['unknown album'])
        self.assertEqual(list(result[0].tracks), [])

        result = self.library.search(track_no=['9'])
        self.assertEqual(list(result[0].tracks), [])

        result = self.library.search(track_no=['no_match'])
        self.assertEqual(list(result[0].tracks), [])

        result = self.library.search(genre=['unknown genre'])
        self.assertEqual(list(result[0].tracks), [])

        result = self.library.search(date=['unknown date'])
        self.assertEqual(list(result[0].tracks), [])

        result = self.library.search(comment=['unknown comment'])
        self.assertEqual(list(result[0].tracks), [])

        result = self.library.search(uri=['unknown uri'])
        self.assertEqual(list(result[0].tracks), [])

        result = self.library.search(any=['unknown anything'])
        self.assertEqual(list(result[0].tracks), [])

    def test_search_uri(self):
        result = self.library.search(uri=['TH1'])
        self.assertEqual(list(result[0].tracks), self.tracks[:1])

        result = self.library.search(uri=['TH2'])
        self.assertEqual(list(result[0].tracks), self.tracks[1:2])

    def test_search_track_name(self):
        result = self.library.search(track_name=['Rack1'])
        self.assertEqual(list(result[0].tracks), self.tracks[:1])

        result = self.library.search(track_name=['Rack2'])
        self.assertEqual(list(result[0].tracks), self.tracks[1:2])

    def test_search_artist(self):
        result = self.library.search(artist=['Tist1'])
        self.assertEqual(list(result[0].tracks), self.tracks[:1])

        result = self.library.search(artist=['Tist2'])
        self.assertEqual(list(result[0].tracks), self.tracks[1:2])

    def test_search_albumartist(self):
        # Artist is both track artist and album artist
        result = self.library.search(albumartist=['Tist1'])
        self.assertEqual(list(result[0].tracks), [self.tracks[0]])

        # Artist is both track artist and album artist
        result = self.library.search(albumartist=['Tist2'])
        self.assertEqual(list(result[0].tracks), [self.tracks[1]])

        # Artist is just album artist
        result = self.library.search(albumartist=['Tist3'])
        self.assertEqual(list(result[0].tracks), [self.tracks[2]])

    def test_search_composer(self):
        result = self.library.search(composer=['Tist5'])
        self.assertEqual(list(result[0].tracks), self.tracks[4:5])

    def test_search_performer(self):
        result = self.library.search(performer=['Tist6'])
        self.assertEqual(list(result[0].tracks), self.tracks[5:6])

    def test_search_album(self):
        result = self.library.search(album=['Bum1'])
        self.assertEqual(list(result[0].tracks), self.tracks[:1])

        result = self.library.search(album=['Bum2'])
        self.assertEqual(list(result[0].tracks), self.tracks[1:2])

    def test_search_genre(self):
        result = self.library.search(genre=['Enre1'])
        self.assertEqual(list(result[0].tracks), self.tracks[4:5])

        result = self.library.search(genre=['Enre2'])
        self.assertEqual(list(result[0].tracks), self.tracks[5:6])

    def test_search_date(self):
        result = self.library.search(date=['2001'])
        self.assertEqual(list(result[0].tracks), self.tracks[:1])

        result = self.library.search(date=['2001-02-03'])
        self.assertEqual(list(result[0].tracks), self.tracks[:1])

        result = self.library.search(date=['2001-02-04'])
        self.assertEqual(list(result[0].tracks), [])

        result = self.library.search(date=['2002'])
        self.assertEqual(list(result[0].tracks), self.tracks[1:2])

    def test_search_track_no(self):
        result = self.library.search(track_no=['1'])
        self.assertEqual(list(result[0].tracks), self.tracks[:1])

        result = self.library.search(track_no=['2'])
        self.assertEqual(list(result[0].tracks), self.tracks[1:2])

    def test_search_comment(self):
        result = self.library.search(comment=['fantastic'])
        self.assertEqual(list(result[0].tracks), self.tracks[3:4])

        result = self.library.search(comment=['antasti'])
        self.assertEqual(list(result[0].tracks), self.tracks[3:4])

    def test_search_any(self):
        # Matches on track artist
        result = self.library.search(any=['Tist1'])
        self.assertEqual(list(result[0].tracks), self.tracks[:1])

        # Matches on track composer
        result = self.library.search(any=['Tist5'])
        self.assertEqual(list(result[0].tracks), self.tracks[4:5])

        # Matches on track performer
        result = self.library.search(any=['Tist6'])
        self.assertEqual(list(result[0].tracks), self.tracks[5:6])

        # Matches on track
        result = self.library.search(any=['Rack1'])
        self.assertEqual(list(result[0].tracks), self.tracks[:1])

        result = self.library.search(any=['Rack2'])
        self.assertEqual(list(result[0].tracks), self.tracks[1:2])

        # Matches on track album
        result = self.library.search(any=['Bum1'])
        self.assertEqual(list(result[0].tracks), self.tracks[:1])

        # Matches on track album artists
        result = self.library.search(any=['Tist3'])
        self.assertEqual(len(result[0].tracks), 2)
        self.assertIn(self.tracks[2], result[0].tracks)
        self.assertIn(self.tracks[3], result[0].tracks)

        # Matches on track genre
        result = self.library.search(any=['Enre1'])
        self.assertEqual(list(result[0].tracks), self.tracks[4:5])

        result = self.library.search(any=['Enre2'])
        self.assertEqual(list(result[0].tracks), self.tracks[5:6])

        # Matches on track comment
        result = self.library.search(any=['fanta'])
        self.assertEqual(list(result[0].tracks), self.tracks[3:4])

        result = self.library.search(any=['is a fan'])
        self.assertEqual(list(result[0].tracks), self.tracks[3:4])

        # Matches on URI
        result = self.library.search(any=['TH1'])
        self.assertEqual(list(result[0].tracks), self.tracks[:1])

    def test_search_wrong_type(self):
        with self.assertRaises(LookupError):
            self.library.search(wrong=['test'])

    def test_search_with_empty_query(self):
        with self.assertRaises(LookupError):
            self.library.search(artist=[''])

        with self.assertRaises(LookupError):
            self.library.search(albumartist=[''])

        with self.assertRaises(LookupError):
            self.library.search(composer=[''])

        with self.assertRaises(LookupError):
            self.library.search(performer=[''])

        with self.assertRaises(LookupError):
            self.library.search(track_name=[''])

        with self.assertRaises(LookupError):
            self.library.search(album=[''])

        with self.assertRaises(LookupError):
            self.library.search(genre=[''])

        with self.assertRaises(LookupError):
            self.library.search(date=[''])

        with self.assertRaises(LookupError):
            self.library.search(comment=[''])

        with self.assertRaises(LookupError):
            self.library.search(uri=[''])

        with self.assertRaises(LookupError):
            self.library.search(any=[''])

    def test_default_get_images_impl_no_images(self):
        result = self.library.get_images([track.uri for track in self.tracks])
        self.assertEqual(result, {track.uri: tuple() for track in self.tracks})

    @mock.patch.object(json.JsonLibrary, 'lookup')
    def test_default_get_images_impl_album_images(self, mock_lookup):
        library = actor.LocalBackend(config=self.config, audio=None).library

        image = Image(uri='imageuri')
        album = Album(images=[image.uri])
        track = Track(uri='trackuri', album=album)
        mock_lookup.return_value = [track]

        result = library.get_images([track.uri])
        self.assertEqual(result, {track.uri: [image]})

    @mock.patch.object(json.JsonLibrary, 'lookup')
    def test_default_get_images_impl_single_track(self, mock_lookup):
        library = actor.LocalBackend(config=self.config, audio=None).library

        image = Image(uri='imageuri')
        album = Album(images=[image.uri])
        track = Track(uri='trackuri', album=album)
        mock_lookup.return_value = track

        result = library.get_images([track.uri])
        self.assertEqual(result, {track.uri: [image]})

    @mock.patch.object(json.JsonLibrary, 'get_images')
    def test_local_library_get_images(self, mock_get_images):
        library = actor.LocalBackend(config=self.config, audio=None).library

        image = Image(uri='imageuri')
        track = Track(uri='trackuri')
        mock_get_images.return_value = {track.uri: [image]}

        result = library.get_images([track.uri])
        self.assertEqual(result, {track.uri: [image]})
示例#33
0
 def test_repr_without_artists(self):
     self.assertEquals(
         "Album(artists=[], images=[], name=u'name', uri=u'uri')",
         repr(Album(uri='uri', name='name')))
示例#34
0
 def test_serialize_with_album(self):
     album = Album(name='foo')
     self.assertDictEqual(
         {'__model__': 'Track', 'uri': 'uri', 'name': 'name',
             'album': album.serialize()},
         Track(uri='uri', name='name', album=album).serialize())
示例#35
0
 def test_serialize_with_album(self):
     album = Album(name="foo")
     self.assertDictEqual(
         {"__model__": "Track", "uri": "uri", "name": "name", "album": album.serialize()},
         Track(uri="uri", name="name", album=album).serialize(),
     )
示例#36
0
    def lookup(self, uri):
        logger.info('youtube LibraryProvider.lookup "%s"', uri)

        video_id = playlist_id = None

        if "youtube.com" in uri:
            url = urlparse(uri.replace("yt:", "").replace("youtube:", ""))
            req = parse_qs(url.query)

            if "list" in req:
                playlist_id = req.get("list")[0]
            else:
                video_id = req.get("v")[0]
        elif "video/" in uri:
            video_id = extract_id(uri)
        else:
            playlist_id = extract_id(uri)

        if video_id:
            video = youtube.Video.get(video_id)
            video.audio_url  # start loading

            return [
                Track(
                    name=video.title.get().replace(";", ""),
                    comment=video.id,
                    length=video.length.get() * 1000,
                    artists=[Artist(name=video.channel.get())],
                    album=Album(name="YouTube Video",),
                    uri="youtube:video/%s.%s"
                    % (safe_url(video.title.get()), video.id),
                )
            ]
        else:
            playlist = youtube.Playlist.get(playlist_id)
            if not playlist.videos.get():
                logger.error('Cannot load "%s"', uri)
                return []

            # ignore videos for which no info was found (removed, etc)
            videos = [
                v for v in playlist.videos.get() if v.length.get() is not None
            ]

            # load audio_url in the background to be ready for playback
            for video in videos:
                video.audio_url  # start loading

            return [
                Track(
                    name=video.title.get().replace(";", ""),
                    comment=video.id,
                    length=video.length.get() * 1000,
                    track_no=count,
                    artists=[Artist(name=video.channel.get())],
                    album=Album(name=playlist.title.get(),),
                    uri="youtube:video/%s.%s"
                    % (safe_url(video.title.get()), video.id),
                )
                for count, video in enumerate(videos, 1)
            ]