def test_build_queries_with_sorts(self): spl = SmartPlaylistPlugin() config['smartplaylist']['playlists'].set([ {'name': 'no_sort', 'query': 'foo'}, {'name': 'one_sort', 'query': 'foo year+'}, {'name': 'only_empty_sorts', 'query': ['foo', 'bar']}, {'name': 'one_non_empty_sort', 'query': ['foo year+', 'bar']}, {'name': 'multiple_sorts', 'query': ['foo year+', 'bar genre-']}, {'name': 'mixed', 'query': ['foo year+', 'bar', 'baz genre+ id-']} ]) spl.build_queries() sorts = dict((name, sort) for name, (_, sort), _ in spl._unmatched_playlists) asseq = self.assertEqual # less cluttered code S = FixedFieldSort # short cut since we're only dealing with this asseq(sorts["no_sort"], NullSort()) asseq(sorts["one_sort"], S('year')) asseq(sorts["only_empty_sorts"], None) asseq(sorts["one_non_empty_sort"], S('year')) asseq(sorts["multiple_sorts"], MultipleSort([S('year'), S('genre', False)])) asseq(sorts["mixed"], MultipleSort([S('year'), S('genre'), S('id', False)]))
def build_queries(self): """ Instanciate queries for the playlists. Each playlist has 2 queries: one or items one for albums, each with a sort. We must also remember its name. _unmatched_playlists is a set of tuples (name, (q, q_sort), (album_q, album_q_sort)). sort may be any sort, or NullSort, or None. None and NullSort are equivalent and both eval to False. More precisely - it will be NullSort when a playlist query ('query' or 'album_query') is a single item or a list with 1 element - it will be None when there are multiple items i a query """ self._unmatched_playlists = set() self._matched_playlists = set() for playlist in self.config['playlists'].get(list): playlist_data = (playlist['name'], ) for key, Model in (('query', Item), ('album_query', Album)): qs = playlist.get(key) if qs is None: query_and_sort = None, None elif isinstance(qs, basestring): query_and_sort = parse_query_string(qs, Model) elif len(qs) == 1: query_and_sort = parse_query_string(qs[0], Model) else: # multiple queries and sorts queries, sorts = zip(*(parse_query_string(q, Model) for q in qs)) query = OrQuery(queries) final_sorts = [] for s in sorts: if s: if isinstance(s, MultipleSort): final_sorts += s.sorts else: final_sorts.append(s) if not final_sorts: sort = None elif len(final_sorts) == 1: sort, = final_sorts else: sort = MultipleSort(final_sorts) query_and_sort = query, sort playlist_data += (query_and_sort, ) self._unmatched_playlists.add(playlist_data)
def setupModelData(self, query): sort = FixedFieldSort msort = MultipleSort([ sort(u'albumartist'), sort('year', False), sort('month', False), sort('day', False), sort(u'album'), sort('disc'), sort('track') ]) try: items = self.library.items(query, msort) except: return False self.rootItem.reset() for item in items: self.rootItem.appendChild(item) return True
def translate_sorts(self, sort_arg): """Translate an AURA sort parameter into a beets Sort. Args: sort_arg: The value of the 'sort' query parameter; a comma separated list of fields to sort by, in order. E.g. "-year,title". """ # Change HTTP query parameter to a list aura_sorts = sort_arg.strip(",").split(",") sorts = [] for aura_attr in aura_sorts: if aura_attr[0] == "-": ascending = False # Remove leading "-" aura_attr = aura_attr[1:] else: # JSON:API default ascending = True # Get the beets version of the attribute name beets_attr = self.attribute_map.get(aura_attr, aura_attr) # Use slow sort so it works with all fields (inc. computed) sorts.append(SlowFieldSort(beets_attr, ascending=ascending)) return MultipleSort(sorts)
def build_queries(self): """ Instantiate queries for the playlists. Each playlist has 2 queries: one or items one for albums, each with a sort. We must also remember its name. _unmatched_playlists is a set of tuples (name, (q, q_sort), (album_q, album_q_sort)). sort may be any sort, or NullSort, or None. None and NullSort are equivalent and both eval to False. More precisely - it will be NullSort when a playlist query ('query' or 'album_query') is a single item or a list with 1 element - it will be None when there are multiple items i a query """ self._unmatched_playlists = set() self._matched_playlists = set() for playlist in self.config['playlists'].get(list): if 'name' not in playlist: self._log.warning(u"playlist configuration is missing name") continue playlist_data = (playlist['name'], ) try: for key, model_cls in (('query', Item), ('album_query', Album)): qs = playlist.get(key) if qs is None: query_and_sort = None, None elif isinstance(qs, six.string_types): query_and_sort = parse_query_string(qs, model_cls) elif len(qs) == 1: query_and_sort = parse_query_string(qs[0], model_cls) else: # multiple queries and sorts queries, sorts = zip( *(parse_query_string(q, model_cls) for q in qs)) query = OrQuery(queries) final_sorts = [] for s in sorts: if s: if isinstance(s, MultipleSort): final_sorts += s.sorts else: final_sorts.append(s) if not final_sorts: sort = None elif len(final_sorts) == 1: sort, = final_sorts else: sort = MultipleSort(final_sorts) query_and_sort = query, sort playlist_data += (query_and_sort, ) except ParsingError as exc: self._log.warning(u"invalid query in playlist {}: {}", playlist['name'], exc) continue self._unmatched_playlists.add(playlist_data)