<commit_before>from __future__ import unicode_literals

import logging
import hashlib

from mopidy import backend
from mopidy.models import Artist, Album, Track, SearchResult

logger = logging.getLogger(__name__)


class GMusicLibraryProvider(backend.LibraryProvider):

    def set_all_access(self, all_access):
        self.all_access = all_access

    def lookup(self, uri):
        if uri.startswith('gmusic:track:'):
            return self._lookup_track(uri)
        elif uri.startswith('gmusic:album:'):
            return self._lookup_album(uri)
        elif uri.startswith('gmusic:artist:'):
            return self._lookup_artist(uri)
        else:
            return []

    def _lookup_track(self, uri):        
        is_all_access = uri.startswith('gmusic:track:T')
        
        if is_all_access and self.all_access:
            song = self.backend.session.get_track_info(uri.split(':')[2])
            if song is None:
                return []
            return [self._aa_to_mopidy_track(song)]
        elif not is_all_access:
            try:
                return [self.tracks[uri]]
            except KeyError:
                logger.debug('Failed to lookup %r', uri)
                return []
        else:
            return []

    def _lookup_album(self, uri):
        is_all_access = uri.startswith('gmusic:album:B')
        if self.all_access and is_all_access:
            album = self.backend.session.get_album_info(uri.split(':')[2], include_tracks=True)
            if album['tracks'] is None:
                return []
            tracks = [self._aa_to_mopidy_track(track) for track in album['tracks']]
            return sorted(tracks, key=lambda t: (t.disc_no,
                                                 t.track_no))
        elif not is_all_access:
            try:
                album = self.albums[uri]
            except KeyError:
                logger.debug('Failed to lookup %r', uri)
                return []
            tracks = self.find_exact(
                dict(album=album.name,
                     artist=[artist.name for artist in album.artists],
                     date=album.date)).tracks
            return sorted(tracks, key=lambda t: (t.disc_no,
                                                 t.track_no))
        else:
            logger.debug('Failed to lookup %r', uri)
            return []

    def _lookup_artist(self, uri):        
        sorter = lambda t: (t.album.date,
                            t.album.name,
                            t.disc_no,
                            t.track_no)
        if self.all_access:
            try:
                all_access_id = self.aa_artists[uri.split(':')[2]]
                artist_infos = self.backend.session.get_artist_info(all_access_id, max_top_tracks=0, max_rel_artist=0)
                tracks = [self._lookup_album('gmusic:album:' + album['albumId']) for album in artist_infos['albums']]
                tracks = reduce(lambda a, b: (a + b), tracks)
                return sorted(tracks, key=sorter)
            except KeyError:
                pass
        try:
            artist = self.artists[uri]
        except KeyError:
            logger.debug('Failed to lookup %r', uri)
            return []

        tracks = self.find_exact(
            dict(artist=artist.name)).tracks
        return sorted(tracks, key=sorter)

    def refresh(self, uri=None):
        self.tracks = {}
        self.albums = {}
        self.artists = {}
        self.aa_artists = {}
        for song in self.backend.session.get_all_songs():
            self._to_mopidy_track(song)

    def search(self, query=None, uris=None):
        lib_tracks, lib_artists, lib_albums = self._search_library(query, uris)

        if query and self.all_access:
            aa_tracks, aa_artists, aa_albums = self._search_all_access(query, uris)
            for aa_artist in aa_artists:
                lib_artists.add(aa_artist)

            for aa_album in aa_albums:
                lib_albums.add(aa_album)

            lib_tracks = set(lib_tracks)

            for aa_track in aa_tracks:
                lib_tracks.add(aa_track)

        return SearchResult(uri='gmusic:search',
                            tracks=lib_tracks,
                            artists=lib_artists,
                            albums=lib_albums)

    def find_exact(self, query=None, uris=None):
        # Find exact can only be done on gmusic library, 
        # since one can't filter all access searches
        lib_tracks, lib_artists, lib_albums = self._search_library(query, uris)

        return SearchResult(uri='gmusic:search',
                            tracks=lib_tracks,
                            artists=lib_artists,
                            albums=lib_albums)

    def _search_all_access(self, query=None, uris=None):
        for (field, values) in query.iteritems():
            if not hasattr(values, '__iter__'):
                values = [values]

            # Since gmusic does not support search filters, just search for the
            # first 'searchable' filter
            if field in ['track_name', 'album', 'artist', 'albumartist', 'any']:
                print "searching all access for " + values[0]
                res = self.backend.session.search_all_access(values[0], max_results=50)

                albums = [self._aa_search_album_to_mopidy_album(album_res) for album_res in res['album_hits']]
                artists = [self._aa_search_artist_to_mopidy_artist(artist_res) for artist_res in res['artist_hits']]
                tracks = [self._aa_search_track_to_mopidy_track(track_res) for track_res in res['song_hits']]

                return tracks, artists, albums

    def _search_library(self, query=None, uris=None):
        if query is None:
            query = {}
        self._validate_query(query)
        result_tracks = self.tracks.values()

        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 = self._convert_to_int(value)
                else:
                    q = value.strip().lower()

                uri_filter = lambda t: q in t.uri.lower()<commit_msg>fix error where _search_all_access() in library.py would return None if no searchable filters where passed. _search_all_access() now returns an empty search result if the search could not be performed.<commit_after>from __future__ import unicode_literals

import logging
import hashlib

from mopidy import backend
from mopidy.models import Artist, Album, Track, SearchResult

logger = logging.getLogger(__name__)


class GMusicLibraryProvider(backend.LibraryProvider):

    def set_all_access(self, all_access):
        self.all_access = all_access

    def lookup(self, uri):
        if uri.startswith('gmusic:track:'):
            return self._lookup_track(uri)
        elif uri.startswith('gmusic:album:'):
            return self._lookup_album(uri)
        elif uri.startswith('gmusic:artist:'):
            return self._lookup_artist(uri)
        else:
            return []

    def _lookup_track(self, uri):        
        is_all_access = uri.startswith('gmusic:track:T')
        
        if is_all_access and self.all_access:
            song = self.backend.session.get_track_info(uri.split(':')[2])
            if song is None:
                return []
            return [self._aa_to_mopidy_track(song)]
        elif not is_all_access:
            try:
                return [self.tracks[uri]]
            except KeyError:
                logger.debug('Failed to lookup %r', uri)
                return []
        else:
            return []

    def _lookup_album(self, uri):
        is_all_access = uri.startswith('gmusic:album:B')
        if self.all_access and is_all_access:
            album = self.backend.session.get_album_info(uri.split(':')[2], include_tracks=True)
            if album['tracks'] is None:
                return []
            tracks = [self._aa_to_mopidy_track(track) for track in album['tracks']]
            return sorted(tracks, key=lambda t: (t.disc_no,
                                                 t.track_no))
        elif not is_all_access:
            try:
                album = self.albums[uri]
            except KeyError:
                logger.debug('Failed to lookup %r', uri)
                return []
            tracks = self.find_exact(
                dict(album=album.name,
                     artist=[artist.name for artist in album.artists],
                     date=album.date)).tracks
            return sorted(tracks, key=lambda t: (t.disc_no,
                                                 t.track_no))
        else:
            logger.debug('Failed to lookup %r', uri)
            return []

    def _lookup_artist(self, uri):        
        sorter = lambda t: (t.album.date,
                            t.album.name,
                            t.disc_no,
                            t.track_no)
        if self.all_access:
            try:
                all_access_id = self.aa_artists[uri.split(':')[2]]
                artist_infos = self.backend.session.get_artist_info(all_access_id, max_top_tracks=0, max_rel_artist=0)
                tracks = [self._lookup_album('gmusic:album:' + album['albumId']) for album in artist_infos['albums']]
                tracks = reduce(lambda a, b: (a + b), tracks)
                return sorted(tracks, key=sorter)
            except KeyError:
                pass
        try:
            artist = self.artists[uri]
        except KeyError:
            logger.debug('Failed to lookup %r', uri)
            return []

        tracks = self.find_exact(
            dict(artist=artist.name)).tracks
        return sorted(tracks, key=sorter)

    def refresh(self, uri=None):
        self.tracks = {}
        self.albums = {}
        self.artists = {}
        self.aa_artists = {}
        for song in self.backend.session.get_all_songs():
            self._to_mopidy_track(song)

    def search(self, query=None, uris=None):
        lib_tracks, lib_artists, lib_albums = self._search_library(query, uris)

        if query and self.all_access:
            aa_tracks, aa_artists, aa_albums = self._search_all_access(query, uris)
            for aa_artist in aa_artists:
                lib_artists.add(aa_artist)

            for aa_album in aa_albums:
                lib_albums.add(aa_album)

            lib_tracks = set(lib_tracks)

            for aa_track in aa_tracks:
                lib_tracks.add(aa_track)

        return SearchResult(uri='gmusic:search',
                            tracks=lib_tracks,
                            artists=lib_artists,
                            albums=lib_albums)

    def find_exact(self, query=None, uris=None):
        # Find exact can only be done on gmusic library, 
        # since one can't filter all access searches
        lib_tracks, lib_artists, lib_albums = self._search_library(query, uris)

        return SearchResult(uri='gmusic:search',
                            tracks=lib_tracks,
                            artists=lib_artists,
                            albums=lib_albums)

    def _search_all_access(self, query=None, uris=None):
        for (field, values) in query.iteritems():
            if not hasattr(values, '__iter__'):
                values = [values]

            # Since gmusic does not support search filters, just search for the
            # first 'searchable' filter
            if field in ['track_name', 'album', 'artist', 'albumartist', 'any']:
                print "searching all access for " + values[0]
                res = self.backend.session.search_all_access(values[0], max_results=50)

                albums = [self._aa_search_album_to_mopidy_album(album_res) for album_res in res['album_hits']]
                artists = [self._aa_search_artist_to_mopidy_artist(artist_res) for artist_res in res['artist_hits']]
                tracks = [self._aa_search_track_to_mopidy_track(track_res) for track_res in res['song_hits']]

                return tracks, artists, albums

        return [], [], []

    def _search_library(self, query=None, uris=None):
        if query is None:
            query = {}
        self._validate_query(query)
        result_tracks = self.tracks.values()

        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 = self._convert_to_int(value)
                else:
                    q = value.strip().lower()

                uri_filter = lambda t: q in t.uri.lower()
{'fraction_non_alphanumeric': 0.09319469232559945, 'fraction_numerical': 0.0013967564211996586, 'mean_word_length': 1.7710169855944957, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '323164', 'n_tokens_mistral': 3806, 'n_tokens_neox': 3600, 'n_words': 830}