Add Item.any_writable_media_field_query method for BPD search

This commit is contained in:
Šarūnas Nejus 2024-06-16 15:22:52 +01:00
parent d22c497dc0
commit 4650f6513b
No known key found for this signature in database
GPG key ID: DD28F6704DBE3435
2 changed files with 18 additions and 11 deletions

View file

@ -350,6 +350,10 @@ class LibModel(dbcore.Model["Library"]):
# Config key that specifies how an instance should be formatted.
_format_config_key: str
@cached_classproperty
def writable_media_fields(cls) -> set[str]:
return set(MediaFile.fields()) & cls._fields.keys()
def _template_funcs(self):
funcs = DefaultTemplateFunctions(self, self._db).functions()
funcs.update(plugins.template_funcs())
@ -401,6 +405,13 @@ class LibModel(dbcore.Model["Library"]):
[cls.field_query(f, *args, **kwargs) for f in cls._search_fields]
)
@classmethod
def any_writable_media_field_query(cls, *args, **kwargs) -> dbcore.OrQuery:
fields = cls.writable_media_fields
return dbcore.OrQuery(
[cls.field_query(f, *args, **kwargs) for f in fields]
)
def duplicates_query(self, fields: list[str]) -> dbcore.AndQuery:
"""Return a query for entities with same values in the given fields."""
return dbcore.AndQuery(

View file

@ -27,8 +27,6 @@ import time
import traceback
from string import Template
from mediafile import MediaFile
import beets
import beets.ui
from beets import dbcore, vfs
@ -91,8 +89,6 @@ SUBSYSTEMS = [
"partition",
]
ITEM_KEYS_WRITABLE = set(MediaFile.fields()).intersection(Item._fields.keys())
# Gstreamer import error.
class NoGstreamerError(Exception):
@ -1399,7 +1395,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
@ -1411,10 +1407,10 @@ 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_media_field_query(
query_type, value
)
)
else:
@ -1429,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)
@ -1456,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 = (