diff --git a/beets/library.py b/beets/library.py index a2848f280..80ffb4576 100644 --- a/beets/library.py +++ b/beets/library.py @@ -397,6 +397,10 @@ class LibModel(dbcore.Model): def shared_model_db_fields(cls) -> Set[str]: return cls._fields.keys() & cls._relation._fields.keys() + @cached_classproperty + def writable_fields(cls) -> Set[str]: + return MediaFile.fields() & cls._relation._fields.keys() + def _template_funcs(self): funcs = DefaultTemplateFunctions(self, self._db).functions() funcs.update(plugins.template_funcs()) @@ -453,6 +457,17 @@ class LibModel(dbcore.Model): ] ) + @classmethod + def any_writable_field_query( + cls, query_class: Type[dbcore.FieldQuery], pattern: str + ) -> dbcore.OrQuery: + return dbcore.OrQuery( + [ + cls.field_query(f, pattern, query_class) + for f in cls.writable_fields + ] + ) + @classmethod def match_all_query( cls, pattern_by_field: Mapping[str, str] diff --git a/beetsplug/bpd/__init__.py b/beetsplug/bpd/__init__.py index a4cb4d291..4171d02d1 100644 --- a/beetsplug/bpd/__init__.py +++ b/beetsplug/bpd/__init__.py @@ -29,8 +29,6 @@ import traceback from string import Template from typing import List -from mediafile import MediaFile - import beets import beets.ui from beets import dbcore, vfs @@ -93,8 +91,6 @@ SUBSYSTEMS = [ "partition", ] -ITEM_KEYS_WRITABLE = set(MediaFile.fields()).intersection(Item._fields.keys()) - # Gstreamer import error. class NoGstreamerError(Exception): @@ -1401,7 +1397,7 @@ class Server(BaseServer): return test_tag, key raise BPDError(ERROR_UNKNOWN, "no such tagtype") - def _metadata_query(self, query_type, any_query_type, kv): + def _metadata_query(self, query_type, kv, allow_any_query: bool = False): """Helper function returns a query object that will find items according to the library query type provided and the key-value pairs specified. The any_query_type is used for queries of @@ -1413,11 +1409,9 @@ class Server(BaseServer): it = iter(kv) for tag, value in zip(it, it): if tag.lower() == "any": - if any_query_type: + if allow_any_query: queries.append( - any_query_type( - value, ITEM_KEYS_WRITABLE, query_type - ) + Item.any_writable_field_query(query_type, value) ) else: raise BPDError(ERROR_UNKNOWN, "no such tagtype") @@ -1431,14 +1425,14 @@ class Server(BaseServer): def cmd_search(self, conn, *kv): """Perform a substring match for items.""" query = self._metadata_query( - dbcore.query.SubstringQuery, dbcore.query.AnyFieldQuery, kv + dbcore.query.SubstringQuery, kv, allow_any_query=True ) for item in self.lib.items(query): yield self._item_info(item) def cmd_find(self, conn, *kv): """Perform an exact match for items.""" - query = self._metadata_query(dbcore.query.MatchQuery, None, kv) + query = self._metadata_query(dbcore.query.MatchQuery, kv) for item in self.lib.items(query): yield self._item_info(item) @@ -1458,7 +1452,7 @@ class Server(BaseServer): raise BPDError(ERROR_ARG, 'should be "Album" for 3 arguments') elif len(kv) % 2 != 0: raise BPDError(ERROR_ARG, "Incorrect number of filter arguments") - query = self._metadata_query(dbcore.query.MatchQuery, None, kv) + query = self._metadata_query(dbcore.query.MatchQuery, kv) clause, subvals = query.clause() statement = (