PathQuery: add 'case_sensitivity' param

- fully tested
- default value is platform-aware
This commit is contained in:
Bruno Cauet 2015-03-01 18:10:07 +01:00
parent cb504ad163
commit 9efcfbb8fa
2 changed files with 26 additions and 10 deletions

View file

@ -45,7 +45,8 @@ log = logging.getLogger('beets')
class PathQuery(dbcore.FieldQuery):
"""A query that matches all items under a given path.
On Windows paths are case-insensitive, contratly to UNIX platforms.
On Windows paths are case-insensitive by default, contrarly to UNIX
platforms.
"""
escape_re = re.compile(r'[\\_%]')
@ -53,11 +54,16 @@ class PathQuery(dbcore.FieldQuery):
_is_windows = platform.system() == 'Windows'
def __init__(self, field, pattern, fast=True):
def __init__(self, field, pattern, fast=True, case_sensitive=None):
super(PathQuery, self).__init__(field, pattern, fast)
if self._is_windows:
if case_sensitive is None:
# setting this value as the default one would make it un-patchable
# and therefore un-testable
case_sensitive = not self._is_windows
if not case_sensitive:
pattern = pattern.lower()
self.case_sensitive = case_sensitive
# Match the path as a single file.
self.file_path = util.bytestring_path(util.normpath(pattern))
@ -65,13 +71,13 @@ class PathQuery(dbcore.FieldQuery):
self.dir_path = util.bytestring_path(os.path.join(self.file_path, b''))
def match(self, item):
path = item.path.lower() if self._is_windows else item.path
path = item.path if self.case_sensitive else item.path.lower()
return (path == self.file_path) or path.startswith(self.dir_path)
def col_clause(self):
file_blob = buffer(self.file_path)
if not self._is_windows:
if self.case_sensitive:
dir_blob = buffer(self.dir_path)
return '({0} = ?) || (substr({0}, 1, ?) = ?)'.format(self.field), \
(file_blob, len(dir_blob), dir_blob)

View file

@ -17,6 +17,7 @@
from __future__ import (division, absolute_import, print_function,
unicode_literals)
from functools import partial
from mock import patch
from test import _common
@ -465,14 +466,23 @@ class PathQueryTest(_common.LibTestCase, TestHelper, AssertsMixin):
def test_case_sensitivity(self):
self.add_album(path='/A/B/C2.mp3', title='caps path')
q = 'path:/A/B'
makeq = partial(beets.library.PathQuery, 'path', '/A/B')
results = self.lib.items(makeq(case_sensitive=True))
self.assert_items_matched(results, ['caps path'])
results = self.lib.items(makeq(case_sensitive=False))
self.assert_items_matched(results, ['path item', 'caps path'])
# test platform-aware default sensitivity
with patch('beets.library.PathQuery._is_windows', False):
results = self.lib.items(q)
self.assert_items_matched(results, ['caps path'])
q = makeq()
self.assertEqual(q.case_sensitive, True)
with patch('beets.library.PathQuery._is_windows', True):
results = self.lib.items(q)
self.assert_items_matched(results, ['path item', 'caps path'])
q = makeq()
self.assertEqual(q.case_sensitive, False)
class IntQueryTest(unittest.TestCase, TestHelper):