From dc054907d5de4f99c8bd4ecb8e2ecb914ff448c5 Mon Sep 17 00:00:00 2001 From: Adrian Sampson Date: Sun, 9 Sep 2012 12:17:13 -0700 Subject: [PATCH] fix non-string value matching in SubstringQuery --- beets/library.py | 13 +++---------- beets/util/__init__.py | 9 +++++++++ docs/changelog.rst | 2 +- test/test_query.py | 12 ++++++++++++ 4 files changed, 25 insertions(+), 11 deletions(-) diff --git a/beets/library.py b/beets/library.py index 6450af9c7..ef97161a6 100644 --- a/beets/library.py +++ b/beets/library.py @@ -166,10 +166,7 @@ def _regexp(expr, val): """ if expr is None: return False - if val is None: - val = u'' - if not isinstance(val, basestring): - val = unicode(val) + val = util.as_string(val) try: res = re.search(expr, val) except re.error: @@ -436,7 +433,7 @@ class SubstringQuery(FieldQuery): return clause, subvals def match(self, item): - value = getattr(item, self.field) or '' + value = util.as_string(getattr(item, self.field)) return self.pattern.lower() in value.lower() class RegexpQuery(FieldQuery): @@ -451,11 +448,7 @@ class RegexpQuery(FieldQuery): return clause, subvals def match(self, item): - value = getattr(item, self.field) or '' - if value is None: - value = u'' - elif not isinstance(value, basestring): - value = unicode(value) + value = util.as_string(getattr(item, self.field)) return self.regexp.search(value) is not None class BooleanQuery(MatchQuery): diff --git a/beets/util/__init__.py b/beets/util/__init__.py index 380bfaf8e..6c29c7c0e 100644 --- a/beets/util/__init__.py +++ b/beets/util/__init__.py @@ -467,6 +467,15 @@ def str2bool(value): else: return False +def as_string(value): + """Convert a value to a Unicode object for matching with a query. + None becomes the empty string. + """ + if value is None: + return u'' + else: + return unicode(value) + def levenshtein(s1, s2): """A nice DP edit distance implementation from Wikibooks: http://en.wikibooks.org/wiki/Algorithm_implementation/Strings/ diff --git a/docs/changelog.rst b/docs/changelog.rst index bc4815dcf..03aab8744 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -12,7 +12,7 @@ Changelog * Fix album queries for ``artpath`` and other non-item fields. * Null values in the database can now be matched with the empty-string regular expression, ``^$``. -* Regular expressions more reliably match non-string values. +* Queries now correctly match non-string values in path format predicates. * :doc:`/plugins/fetchart`: Fix a bug where cover art filenames could lack a ``.jpg`` extension. * :doc:`/plugins/lyrics`: Fix an exception with non-ASCII lyrics. diff --git a/test/test_query.py b/test/test_query.py index 6dc212a8a..eae9abced 100644 --- a/test/test_query.py +++ b/test/test_query.py @@ -318,6 +318,18 @@ class MatchTest(unittest.TestCase): q = beets.library.RegexpQuery('disc', '^6$') self.assertTrue(q.match(self.item)) + def test_substring_match_positive(self): + q = beets.library.SubstringQuery('album', 'album') + self.assertTrue(q.match(self.item)) + + def test_substring_match_negative(self): + q = beets.library.SubstringQuery('album', 'ablum') + self.assertFalse(q.match(self.item)) + + def test_substring_match_non_string_value(self): + q = beets.library.SubstringQuery('disc', '6') + self.assertTrue(q.match(self.item)) + class PathQueryTest(unittest.TestCase, AssertsMixin): def setUp(self): self.lib = beets.library.Library(':memory:')