From f474f3aed2a8d19592fb6cc95c461537b1fbc125 Mon Sep 17 00:00:00 2001 From: Adrian Sampson Date: Thu, 14 Mar 2013 10:00:30 -0700 Subject: [PATCH] split FieldQuery into base and registered versions --- beets/library.py | 15 ++++++++++----- beetsplug/fuzzy.py | 4 ++-- docs/plugins/writing.rst | 26 ++++++++++++++------------ 3 files changed, 26 insertions(+), 19 deletions(-) diff --git a/beets/library.py b/beets/library.py index 4525581a3..c8460955d 100644 --- a/beets/library.py +++ b/beets/library.py @@ -456,9 +456,8 @@ class FieldQuery(Query): """An abstract query that searches in a specific field for a pattern. Subclasses must provide a `value_match` class method, which determines whether a certain pattern string matches a certain value - string. They may then either override the `clause` method to use - native SQLite functionality or get registered to use a callback into - Python. + string. Subclasses also need to provide `clause` to implement the + same matching functionality in SQLite. """ def __init__(self, field, pattern): self.field = field @@ -481,6 +480,11 @@ class FieldQuery(Query): def match(self, item): return self._raw_value_match(self.pattern, getattr(item, self.field)) +class RegisteredFieldQuery(FieldQuery): + """A FieldQuery that uses a registered SQLite callback function. + Before it can be used to execute queries, the `register` method must + be called. + """ def clause(self): # Invoke the registered SQLite function. clause = "{name}(?, {field})".format(name=self.__class__.__name__, @@ -522,7 +526,7 @@ class SubstringQuery(FieldQuery): def value_match(cls, pattern, value): return pattern.lower() in value.lower() -class RegexpQuery(FieldQuery): +class RegexpQuery(RegisteredFieldQuery): """A query that matches a regular expression in a specific item field. """ @@ -1112,7 +1116,8 @@ class Library(BaseLibrary): # Register plugin queries. RegexpQuery.register(conn) for prefix, query_class in plugins.queries().items(): - query_class.register(conn) + if issubclass(query_class, RegisteredFieldQuery): + query_class.register(conn) self._connections[thread_id] = conn return conn diff --git a/beetsplug/fuzzy.py b/beetsplug/fuzzy.py index 8fb7724cc..14ae54ffc 100644 --- a/beetsplug/fuzzy.py +++ b/beetsplug/fuzzy.py @@ -16,12 +16,12 @@ """ from beets.plugins import BeetsPlugin -from beets.library import FieldQuery +from beets.library import RegisteredFieldQuery import beets import difflib -class FuzzyQuery(FieldQuery): +class FuzzyQuery(RegisteredFieldQuery): @classmethod def value_match(self, pattern, val): # smartcase diff --git a/docs/plugins/writing.rst b/docs/plugins/writing.rst index fbec02ed6..d92ea8374 100644 --- a/docs/plugins/writing.rst +++ b/docs/plugins/writing.rst @@ -334,26 +334,28 @@ You can add new kinds of queries to beets' :doc:`query syntax supports regular expression queries, which are indicated by a colon prefix---plugins can do the same. -To do so, define a subclass of the ``FieldQuery`` type from the -``beets.library`` module. In this subclass, you should override the -``value_match`` class method. (Remember the ``@classmethod`` decorator!) Then, -in the ``queries`` method of your plugin class, return a dictionary mapping -prefix strings to query classes. +To do so, define a subclass of the ``Query`` type from the ``beets.library`` +module. Then, in the ``queries`` method of your plugin class, return a +dictionary mapping prefix strings to query classes. -The following example plugins declares a query using the ``@`` prefix. So the -plugin will be called if we issue a command like ``beet ls @something`` or -``beet ls artist:@something``:: +One simple kind of query you can extend is the ``RegisteredFieldQuery``, which +implements string comparisons. To use it, create a subclass inheriting from +that class and override the ``value_match`` class method. (Remember the +``@classmethod`` decorator!) The following example plugin declares a query +using the ``@`` prefix to delimit exact string matches. The plugin will be +used if we issue a command like ``beet ls @something`` or ``beet ls +artist:@something``:: from beets.plugins import BeetsPlugin from beets.library import PluginQuery - class ExampleQuery(PluginQuery): + class ExactMatchQuery(PluginQuery): @classmethod def value_match(self, pattern, val): - return True # This will just match everything. + return pattern == val - class ExamplePlugin(BeetsPlugin): + class ExactMatchPlugin(BeetsPlugin): def queries(): return { - '@': ExampleQuery + '@': ExactMatchQuery }