mirror of
https://github.com/beetbox/beets.git
synced 2026-01-04 23:12:51 +01:00
Merge pull request #1387 from brunal/improve-path-query
Improve path query: autodetect only if the target exists
This commit is contained in:
commit
882723a0bf
4 changed files with 63 additions and 4 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)
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ Changelog
|
|||
|
||||
Features:
|
||||
|
||||
* :ref:`pathquery` are automatically triggered only if the
|
||||
path targeted by the query exists.
|
||||
* :doc:`/plugins/duplicates` now accepts a ``--strict`` option that
|
||||
will only report duplicates if all attributes are explicitly set.
|
||||
:bug:`1000`
|
||||
|
|
|
|||
|
|
@ -166,6 +166,8 @@ Find all items with a file modification time between 2008-12-01 and
|
|||
$ beet ls 'mtime:2008-12-01..2008-12-02'
|
||||
|
||||
|
||||
.. _pathquery:
|
||||
|
||||
Path Queries
|
||||
------------
|
||||
|
||||
|
|
@ -175,8 +177,8 @@ Sometimes it's useful to find all the items in your library that are
|
|||
$ beet list path:/my/music/directory
|
||||
|
||||
In fact, beets automatically recognizes any query term containing a path
|
||||
separator (``/`` on POSIX systems) as a path query, so this command is
|
||||
equivalent::
|
||||
separator (``/`` on POSIX systems) as a path query if that path exists, so this
|
||||
command is equivalent as long as ``/my/music/directory`` exist::
|
||||
|
||||
$ beet list /my/music/directory
|
||||
|
||||
|
|
|
|||
|
|
@ -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