Test queries building sort management in smartplaylist

Slighly modify Sort parsing: avoid building MultiplSort() instances
comptised of a single sort, but return that sort instead, since it wraps
things with any gain.
This commit is contained in:
Bruno Cauet 2015-03-18 18:46:24 +01:00
parent 45c0c9b3cb
commit bcd57bd2b5
5 changed files with 67 additions and 13 deletions

View file

@ -625,6 +625,12 @@ class Sort(object):
"""
return False
def __hash__(self):
return 0
def __eq__(self, other):
return type(self) == type(other)
class MultipleSort(Sort):
"""Sort that encapsulates multiple sub-sorts.
@ -686,6 +692,13 @@ class MultipleSort(Sort):
def __repr__(self):
return u'MultipleSort({0})'.format(repr(self.sorts))
def __hash__(self):
return hash(tuple(self.sorts))
def __eq__(self, other):
return super(MultipleSort, self).__eq__(other) and \
self.sorts == other.sorts
class FieldSort(Sort):
"""An abstract sort criterion that orders by a specific field (of
@ -709,6 +722,14 @@ class FieldSort(Sort):
'+' if self.ascending else '-',
)
def __hash__(self):
return hash((self.field, self.ascending))
def __eq__(self, other):
return super(FieldSort, self).__eq__(other) and \
self.field == other.field and \
self.ascending == other.ascending
class FixedFieldSort(FieldSort):
"""Sort object to sort on a fixed field.

View file

@ -152,12 +152,14 @@ def sort_from_strings(model_cls, sort_parts):
"""Create a `Sort` from a list of sort criteria (strings).
"""
if not sort_parts:
return query.NullSort()
sort = query.NullSort()
elif len(sort_parts) == 1:
sort = construct_sort_part(model_cls, sort_parts[0])
else:
sort = query.MultipleSort()
for part in sort_parts:
sort.add_sort(construct_sort_part(model_cls, part))
return sort
return sort
def parse_sorted_query(model_cls, parts, prefixes={},

View file

@ -107,14 +107,19 @@ class SmartPlaylistPlugin(BeetsPlugin):
queries, sorts = zip(*(parse_query_string(q, Model)
for q in qs))
query = OrQuery(queries)
sort = MultipleSort()
final_sorts = []
for s in sorts:
if s:
sort.add_sort(s)
if not sort.sorts:
if isinstance(s, MultipleSort):
final_sorts += s.sorts
else:
final_sorts.append(s)
if not final_sorts:
sort = None
elif len(sort.sorts) == 1:
sort = sort.sorts[0]
elif len(final_sorts) == 1:
sort, = final_sorts
else:
sort = MultipleSort(final_sorts)
query_and_sort = query, sort
playlist_data += (query_and_sort,)

View file

@ -449,6 +449,7 @@ class SortFromStringsTest(unittest.TestCase):
def test_zero_parts(self):
s = self.sfs([])
self.assertIsInstance(s, dbcore.query.NullSort)
self.assertEqual(s, dbcore.query.NullSort())
def test_one_parts(self):
s = self.sfs(['field+'])
@ -461,17 +462,17 @@ class SortFromStringsTest(unittest.TestCase):
def test_fixed_field_sort(self):
s = self.sfs(['field_one+'])
self.assertIsInstance(s, dbcore.query.MultipleSort)
self.assertIsInstance(s.sorts[0], dbcore.query.FixedFieldSort)
self.assertIsInstance(s, dbcore.query.FixedFieldSort)
self.assertEqual(s, dbcore.query.FixedFieldSort('field_one'))
def test_flex_field_sort(self):
s = self.sfs(['flex_field+'])
self.assertIsInstance(s, dbcore.query.MultipleSort)
self.assertIsInstance(s.sorts[0], dbcore.query.SlowFieldSort)
self.assertIsInstance(s, dbcore.query.SlowFieldSort)
self.assertEqual(s, dbcore.query.SlowFieldSort('flex_field'))
def test_special_sort(self):
s = self.sfs(['some_sort+'])
self.assertIsInstance(s.sorts[0], TestSort)
self.assertIsInstance(s, TestSort)
class ResultsIteratorTest(unittest.TestCase):

View file

@ -24,7 +24,7 @@ from mock import Mock, MagicMock
from beetsplug.smartplaylist import SmartPlaylistPlugin
from beets.library import Item, Album, parse_query_string
from beets.dbcore import OrQuery
from beets.dbcore.query import NullSort
from beets.dbcore.query import NullSort, MultipleSort, FixedFieldSort
from beets.util import syspath
from beets.ui import UserError
from beets import config
@ -66,6 +66,31 @@ class SmartPlaylistTest(unittest.TestCase):
('bar', (None, None), (bar_bar, None)),
]))
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 = {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 test_db_changes(self):
spl = SmartPlaylistPlugin()