fix crash when using an item-only field in an album query

This commit is contained in:
Adrian Sampson 2011-06-13 21:27:13 -07:00
parent ac9147928a
commit efa704f61e
3 changed files with 37 additions and 10 deletions

1
NEWS
View file

@ -43,6 +43,7 @@
* Fix a "broken pipe" error when piping beets' standard output.
* A better error message is given when the database file is unopenable.
* Suppress errors due to timeouts and bad responses from MusicBrainz.
* Fix a crash on album queries with item-only field names.
1.0b8
-----

View file

@ -411,7 +411,7 @@ class CollectionQuery(Query):
return out
@classmethod
def from_string(cls, query_string, default_fields=None):
def from_string(cls, query_string, default_fields=None, all_keys=ITEM_KEYS):
"""Creates a query from a string in the format used by
_parse_query. If default_fields are specified, they are the
fields to be searched by unqualified search terms. Otherwise,
@ -423,7 +423,7 @@ class CollectionQuery(Query):
subqueries.append(AnySubstringQuery(pattern, default_fields))
elif key.lower() == 'comp': # a boolean field
subqueries.append(BooleanQuery(key.lower(), pattern))
elif key.lower() in ITEM_KEYS: # ignore unrecognized keys
elif key.lower() in all_keys: # ignore unrecognized keys
subqueries.append(SubstringQuery(key.lower(), pattern))
elif key.lower() == 'singleton':
subqueries.append(SingletonQuery(util.str2bool(pattern)))
@ -522,16 +522,22 @@ class BaseLibrary(object):
# Helpers.
@classmethod
def _get_query(cls, val=None, default_fields=None):
def _get_query(cls, val=None, album=False):
"""Takes a value which may be None, a query string, or a Query
object, and returns a suitable Query object. If default_fields
is specified, then it restricts the list of fields to search
for unqualified terms in query strings.
object, and returns a suitable Query object. album determines
whether the query is to match items or albums.
"""
if album:
default_fields = ALBUM_DEFAULT_FIELDS
all_keys = ALBUM_KEYS
else:
default_fields = ITEM_DEFAULT_FIELDS
all_keys = ITEM_KEYS
if val is None:
return TrueQuery()
elif isinstance(val, basestring):
return AndQuery.from_string(val, default_fields)
return AndQuery.from_string(val, default_fields, all_keys)
elif isinstance(val, Query):
return val
elif not isinstance(val, Query):
@ -919,7 +925,7 @@ class Library(BaseLibrary):
# Querying.
def albums(self, query=None, artist=None):
query = self._get_query(query, ALBUM_DEFAULT_FIELDS)
query = self._get_query(query, True)
if artist is not None:
# "Add" the artist to the query.
query = AndQuery((query, MatchQuery('albumartist', artist)))
@ -931,7 +937,7 @@ class Library(BaseLibrary):
return [Album(self, dict(res)) for res in c.fetchall()]
def items(self, query=None, artist=None, album=None, title=None):
queries = [self._get_query(query, ITEM_DEFAULT_FIELDS)]
queries = [self._get_query(query, False)]
if artist is not None:
queries.append(MatchQuery('artist', artist))
if album is not None:

View file

@ -180,7 +180,7 @@ class MemoryGetTest(unittest.TestCase, AssertsMixin):
self.lib = beets.library.Library(':memory:')
self.lib.add(self.single_item)
self.lib.add_album([self.album_item])
self.album = self.lib.add_album([self.album_item])
def test_singleton_true(self):
q = 'singleton:true'
@ -206,6 +206,26 @@ class MemoryGetTest(unittest.TestCase, AssertsMixin):
self.assert_matched(results, 'singleton item')
self.assert_done(results)
def test_unknown_field_name_ignored(self):
q = 'xyzzy:nonsense'
results = self.lib.items(q)
titles = [i.title for i in results]
self.assertTrue('singleton item' in titles)
self.assertTrue('album item' in titles)
self.assertEqual(len(titles), 2)
def test_unknown_field_name_ignored_in_album_query(self):
q = 'xyzzy:nonsense'
results = self.lib.albums(q)
names = [a.album for a in results]
self.assertEqual(names, ['the album'])
def test_item_field_name_ignored_in_album_query(self):
q = 'format:nonsense'
results = self.lib.albums(q)
names = [a.album for a in results]
self.assertEqual(names, ['the album'])
class BrowseTest(unittest.TestCase, AssertsMixin):
def setUp(self):
self.lib = beets.library.Library(