From 95a036d510ca5253ce19a9eb2b056446d2a12777 Mon Sep 17 00:00:00 2001 From: Adrian Sampson Date: Sat, 24 May 2014 16:52:16 -0700 Subject: [PATCH] Move implicit path query identification out (#649) This is not the most elegant solution, but it does let us move most of the query-parsing logic out of library.py. It would still be nice to get rid of most of beets.library.get_query, but I don't yet know how to do that. --- beets/library.py | 44 ++++++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/beets/library.py b/beets/library.py index abe087ef7..0d665f73d 100644 --- a/beets/library.py +++ b/beets/library.py @@ -932,10 +932,7 @@ def construct_query_part(model_cls, prefixes, query_part): # No key specified. if key is None: - if os.sep in pattern and 'path' in model_cls._fields: - # This looks like a path. - return PathQuery('path', pattern) - elif issubclass(query_class, dbcore.FieldQuery): + if issubclass(query_class, dbcore.FieldQuery): # The query type matches a specific field, but none was # specified. So we use a version of the query that matches # any field. @@ -963,7 +960,7 @@ def query_from_strings(query_cls, model_cls, prefixes, query_parts): return query_cls(subqueries) -def _get_query_helper(val, model_cls, prefixes): +def get_query(val, model_cls): """Take a value which may be None, a query string, a query string list, or a Query object, and return a suitable Query object. @@ -971,6 +968,10 @@ def _get_query_helper(val, model_cls, prefixes): is a query for (i.e., Album or Item) and is used to determine which fields are searched. """ + # Get query types and their prefix characters. + prefixes = {':': dbcore.query.RegexpQuery} + prefixes.update(plugins.queries()) + # Convert a single string into a list of space-separated # criteria. if isinstance(val, basestring): @@ -984,23 +985,34 @@ def _get_query_helper(val, model_cls, prefixes): if val is None: return dbcore.query.TrueQuery() elif isinstance(val, list) or isinstance(val, tuple): - return query_from_strings(dbcore.AndQuery, model_cls, prefixes, val) + # Special-case path-like queries, which are non-field queries + # containing path separators (/). + if 'path' in model_cls._fields: + path_parts = [] + non_path_parts = [] + for s in val: + if s.find(os.sep, 0, s.find(':')) != -1: + # Separator precedes colon. + path_parts.append(s) + else: + non_path_parts.append(s) + else: + path_parts = () + non_path_parts = val + + query = query_from_strings(dbcore.AndQuery, model_cls, prefixes, + non_path_parts) + + # Add path queries to aggregate query. + if path_parts: + query.subqueries += [PathQuery('path', s) for s in path_parts] + return query elif isinstance(val, dbcore.Query): return val else: raise ValueError('query must be None or have type Query or str') -def get_query(val, model_cls): - """Given a string or sequence or None, get a Query object. - """ - # Get query types and their prefix characters. - prefixes = {':': dbcore.query.RegexpQuery} - prefixes.update(plugins.queries()) - - return _get_query_helper(val, model_cls, prefixes) - - # The Library: interface to the database. class Library(dbcore.Database):