Skip to content

Commit 5a4e33c

Browse files
committed
Remove NamedQuery
Remove 'NamedQuery' since it is not being used by any queries any more. This simplifies query parsing logic in 'queryparse.py'. We know that this logic can only receive 'FieldQuery' thus I adjusted types and removed the logic that handles other cases. Effectively, this means that the query parsing logic does not any more care whether the query is named by the corresponding DB field. Instead, queries like 'SingletonQuery' and 'PlaylistQuery' are responsible for translating 'singleton' and 'playlist' to the underlying DB filters.
1 parent afe9043 commit 5a4e33c

File tree

5 files changed

+19
-54
lines changed

5 files changed

+19
-54
lines changed

beets/dbcore/__init__.py

-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
FieldQuery,
2323
InvalidQueryError,
2424
MatchQuery,
25-
NamedQuery,
2625
OrQuery,
2726
Query,
2827
)

beets/dbcore/db.py

+4-8
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@
1212
# The above copyright notice and this permission notice shall be
1313
# included in all copies or substantial portions of the Software.
1414

15-
"""The central Model and Database constructs for DBCore.
16-
"""
15+
"""The central Model and Database constructs for DBCore."""
1716

1817
from __future__ import annotations
1918

@@ -308,7 +307,7 @@ class Model(ABC):
308307
are subclasses of `Sort`.
309308
"""
310309

311-
_queries: Dict[str, Type[Query]] = {}
310+
_queries: Dict[str, Type[FieldQuery]] = {}
312311
"""Named queries that use a field-like `name:value` syntax but which
313312
do not relate to any specific field.
314313
"""
@@ -598,8 +597,7 @@ def store(self, fields: Optional[Iterable[str]] = None):
598597
# Deleted flexible attributes.
599598
for key in self._dirty:
600599
tx.mutate(
601-
"DELETE FROM {} "
602-
"WHERE entity_id=? AND key=?".format(self._flex_table),
600+
f"DELETE FROM {self._flex_table} WHERE entity_id=? AND key=?",
603601
(self.id, key),
604602
)
605603

@@ -1188,9 +1186,7 @@ def _make_attribute_table(self, flex_table: str):
11881186
UNIQUE(entity_id, key) ON CONFLICT REPLACE);
11891187
CREATE INDEX IF NOT EXISTS {0}_by_entity
11901188
ON {0} (entity_id);
1191-
""".format(
1192-
flex_table
1193-
)
1189+
""".format(flex_table)
11941190
)
11951191

11961192
# Querying.

beets/dbcore/query.py

-9
Original file line numberDiff line numberDiff line change
@@ -115,15 +115,6 @@ def __hash__(self) -> int:
115115
return hash(type(self))
116116

117117

118-
class NamedQuery(Query):
119-
"""Non-field query, i.e. the query prefix is not a field but identifies the
120-
query class.
121-
"""
122-
123-
@abstractmethod
124-
def __init__(self, pattern): ...
125-
126-
127118
P = TypeVar("P")
128119
SQLiteType = Union[str, float, int, memoryview]
129120
AnySQLiteType = TypeVar("AnySQLiteType", bound=SQLiteType)

beets/dbcore/queryparse.py

+12-26
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,14 @@
1212
# The above copyright notice and this permission notice shall be
1313
# included in all copies or substantial portions of the Software.
1414

15-
"""Parsing of strings into DBCore queries.
16-
"""
15+
"""Parsing of strings into DBCore queries."""
1716

1817
import itertools
1918
import re
2019
from typing import Collection, Dict, List, Optional, Sequence, Tuple, Type
2120

2221
from . import Model, query
23-
from .query import Query, Sort
22+
from .query import Sort
2423

2524
PARSE_QUERY_PART_REGEX = re.compile(
2625
# Non-capturing optional segment for the keyword.
@@ -36,10 +35,10 @@
3635

3736
def parse_query_part(
3837
part: str,
39-
query_classes: Dict = {},
38+
query_classes: Dict[str, Type[query.FieldQuery]] = {},
4039
prefixes: Dict = {},
4140
default_class: Type[query.SubstringQuery] = query.SubstringQuery,
42-
) -> Tuple[Optional[str], str, Type[query.Query], bool]:
41+
) -> Tuple[Optional[str], str, Type[query.FieldQuery], bool]:
4342
"""Parse a single *query part*, which is a chunk of a complete query
4443
string representing a single criterion.
4544
@@ -128,7 +127,7 @@ def construct_query_part(
128127

129128
# Use `model_cls` to build up a map from field (or query) names to
130129
# `Query` classes.
131-
query_classes: Dict[str, Type[Query]] = {}
130+
query_classes: Dict[str, Type[query.FieldQuery]] = {}
132131
for k, t in itertools.chain(
133132
model_cls._fields.items(), model_cls._types.items()
134133
):
@@ -143,30 +142,17 @@ def construct_query_part(
143142
# If there's no key (field name) specified, this is a "match
144143
# anything" query.
145144
if key is None:
146-
if issubclass(query_class, query.FieldQuery):
147-
# The query type matches a specific field, but none was
148-
# specified. So we use a version of the query that matches
149-
# any field.
150-
out_query = query.AnyFieldQuery(
151-
pattern, model_cls._search_fields, query_class
152-
)
153-
elif issubclass(query_class, query.NamedQuery):
154-
# Non-field query type.
155-
out_query = query_class(pattern)
156-
else:
157-
assert False, "Unexpected query type"
145+
# The query type matches a specific field, but none was
146+
# specified. So we use a version of the query that matches
147+
# any field.
148+
out_query = query.AnyFieldQuery(
149+
pattern, model_cls._search_fields, query_class
150+
)
158151

159152
# Field queries get constructed according to the name of the field
160153
# they are querying.
161-
elif issubclass(query_class, query.FieldQuery):
162-
key = key.lower()
163-
out_query = query_class(key.lower(), pattern, key in model_cls._fields)
164-
165-
# Non-field (named) query.
166-
elif issubclass(query_class, query.NamedQuery):
167-
out_query = query_class(pattern)
168154
else:
169-
assert False, "Unexpected query type"
155+
out_query = query_class(key.lower(), pattern, key in model_cls._fields)
170156

171157
# Apply negation.
172158
if negate:

test/test_dbcore.py

+3-10
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@
1212
# The above copyright notice and this permission notice shall be
1313
# included in all copies or substantial portions of the Software.
1414

15-
"""Tests for the DBCore database abstraction.
16-
"""
15+
"""Tests for the DBCore database abstraction."""
1716

1817
import os
1918
import shutil
@@ -32,7 +31,7 @@ class SortFixture(dbcore.query.FieldSort):
3231
pass
3332

3433

35-
class QueryFixture(dbcore.query.NamedQuery):
34+
class QueryFixture(dbcore.query.FieldQuery):
3635
def __init__(self, pattern):
3736
self.pattern = pattern
3837

@@ -516,9 +515,7 @@ def pqp(self, part):
516515
part,
517516
{"year": dbcore.query.NumericQuery},
518517
{":": dbcore.query.RegexpQuery},
519-
)[
520-
:-1
521-
] # remove the negate flag
518+
)[:-1] # remove the negate flag
522519

523520
def test_one_basic_term(self):
524521
q = "test"
@@ -605,10 +602,6 @@ def test_empty_query_part(self):
605602
q = self.qfs([""])
606603
self.assertIsInstance(q.subqueries[0], dbcore.query.TrueQuery)
607604

608-
def test_parse_named_query(self):
609-
q = self.qfs(["some_query:foo"])
610-
self.assertIsInstance(q.subqueries[0], QueryFixture)
611-
612605

613606
class SortFromStringsTest(unittest.TestCase):
614607
def sfs(self, strings):

0 commit comments

Comments
 (0)