mirror of
https://github.com/beetbox/beets.git
synced 2026-02-08 00:14:31 +01:00
Improve path query parts detection: test existence
Detect path parts of a query with `PathQuery.is_path_query()` which tests for `os.sep` presence AND query part existence. Also fix a bug where "my_path/" would not get detected: colon absence would make search for `os.sep` only happen in "my_path". Fix #1385.
This commit is contained in:
parent
e953e6bdcb
commit
ad34642877
2 changed files with 57 additions and 2 deletions
|
|
@ -75,6 +75,17 @@ class PathQuery(dbcore.FieldQuery):
|
|||
# As a directory (prefix).
|
||||
self.dir_path = util.bytestring_path(os.path.join(self.file_path, b''))
|
||||
|
||||
@classmethod
|
||||
def is_path_query(cls, query_part):
|
||||
"""Try to guess whether a unicode query part is a path query.
|
||||
|
||||
Condition: separator precedes colon and the file exists.
|
||||
"""
|
||||
colon = query_part.find(':')
|
||||
if colon != -1:
|
||||
query_part = query_part[:colon]
|
||||
return os.sep in query_part and os.path.exists(query_part)
|
||||
|
||||
def match(self, item):
|
||||
path = item.path if self.case_sensitive else item.path.lower()
|
||||
return (path == self.file_path) or path.startswith(self.dir_path)
|
||||
|
|
@ -1097,8 +1108,7 @@ def parse_query_parts(parts, model_cls):
|
|||
path_parts = []
|
||||
non_path_parts = []
|
||||
for s in parts:
|
||||
if s.find(os.sep, 0, s.find(':')) != -1:
|
||||
# Separator precedes colon.
|
||||
if PathQuery.is_path_query(s):
|
||||
path_parts.append(s)
|
||||
else:
|
||||
non_path_parts.append(s)
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ from __future__ import (division, absolute_import, print_function,
|
|||
unicode_literals)
|
||||
|
||||
from functools import partial
|
||||
from mock import patch
|
||||
import os
|
||||
|
||||
from test import _common
|
||||
from test._common import unittest
|
||||
|
|
@ -374,6 +376,13 @@ class PathQueryTest(_common.LibTestCase, TestHelper, AssertsMixin):
|
|||
self.i.store()
|
||||
self.lib.add_album([self.i])
|
||||
|
||||
self.patcher = patch('beets.library.os.path.exists')
|
||||
self.patcher.start().return_value = True
|
||||
|
||||
def tearDown(self):
|
||||
super(PathQueryTest, self).tearDown()
|
||||
self.patcher.stop()
|
||||
|
||||
def test_path_exact_match(self):
|
||||
q = 'path:/a/b/c.mp3'
|
||||
results = self.lib.items(q)
|
||||
|
|
@ -503,6 +512,42 @@ class PathQueryTest(_common.LibTestCase, TestHelper, AssertsMixin):
|
|||
q = makeq()
|
||||
self.assertEqual(q.case_sensitive, False)
|
||||
|
||||
@patch('beets.library.os')
|
||||
def test_path_sep_detection(self, mock_os):
|
||||
mock_os.sep = '/'
|
||||
is_path = beets.library.PathQuery.is_path_query
|
||||
self.assertTrue(is_path('/foo/bar'))
|
||||
self.assertTrue(is_path('foo/bar'))
|
||||
self.assertTrue(is_path('foo/'))
|
||||
self.assertFalse(is_path('foo'))
|
||||
self.assertTrue(is_path('foo/:bar'))
|
||||
self.assertFalse(is_path('foo:bar/'))
|
||||
self.assertFalse(is_path('foo:/bar'))
|
||||
|
||||
def test_path_detection(self):
|
||||
# cover existence test
|
||||
self.patcher.stop()
|
||||
is_path = beets.library.PathQuery.is_path_query
|
||||
|
||||
try:
|
||||
self.touch(b'foo/bar')
|
||||
# test absolute
|
||||
self.assertTrue(is_path(os.path.join(self.temp_dir, b'foo/bar')))
|
||||
self.assertTrue(is_path(os.path.join(self.temp_dir, b'foo')))
|
||||
self.assertFalse(is_path(b'foo/bar'))
|
||||
|
||||
cur_dir = os.getcwd()
|
||||
try:
|
||||
os.chdir(self.temp_dir)
|
||||
self.assertTrue(is_path(b'foo/'))
|
||||
self.assertTrue(is_path(b'foo/bar'))
|
||||
self.assertTrue(is_path(b'foo/bar:tagada'))
|
||||
self.assertFalse(is_path(b'bar'))
|
||||
finally:
|
||||
os.chdir(cur_dir)
|
||||
finally:
|
||||
self.patcher.start()
|
||||
|
||||
|
||||
class IntQueryTest(unittest.TestCase, TestHelper):
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue