mirror of
https://github.com/beetbox/beets.git
synced 2026-02-26 01:09:38 +01:00
first stab at computed fields
The idea is to have uniform access to plugin-provided (computed) fields of items and albums. This also permits queries over these computed fields.
This commit is contained in:
parent
b87de00ba4
commit
13b1e0f115
2 changed files with 72 additions and 5 deletions
|
|
@ -301,6 +301,12 @@ class FlexModel(object):
|
|||
"""
|
||||
return list(self._fields) + self._values_flex.keys()
|
||||
|
||||
def items(self):
|
||||
"""Iterate over (key, value) pairs that this object contains.
|
||||
"""
|
||||
for key in self.keys():
|
||||
yield key, self[key]
|
||||
|
||||
def get(self, key, default=None):
|
||||
"""Get the value for a given key or `default` if it does not
|
||||
exist.
|
||||
|
|
@ -311,10 +317,9 @@ class FlexModel(object):
|
|||
return default
|
||||
|
||||
def __contains__(self, key):
|
||||
"""Determine whether `key` is a fixed or flex attribute on this
|
||||
object.
|
||||
"""Determine whether `key` is an attribute on this object.
|
||||
"""
|
||||
return key in self._fields or key in self._values_flex
|
||||
return key in self.keys()
|
||||
|
||||
|
||||
# Convenient attribute access.
|
||||
|
|
@ -335,7 +340,39 @@ class FlexModel(object):
|
|||
self[key] = value
|
||||
|
||||
|
||||
class LibModel(FlexModel):
|
||||
class PluggableModel(FlexModel):
|
||||
"""A base model class that adds plugin-provided fields to FlexModel.
|
||||
"""
|
||||
@classmethod
|
||||
def _getters(cls):
|
||||
"""Return a mapping from field names to getter functions.
|
||||
"""
|
||||
# We could cache this if it becomes a performance problem to
|
||||
# gather the getter mapping every time.
|
||||
raise NotImplementedError()
|
||||
|
||||
def __getitem__(self, key):
|
||||
"""Get the value for a field, which may be a fixed attribute, a
|
||||
flexible attribute, or a plugin-provided attribute.
|
||||
"""
|
||||
getters = self._getters()
|
||||
if key in getters:
|
||||
return getters[key](self)
|
||||
return super(PluggableModel, self).__getitem__(key)
|
||||
|
||||
def keys(self, computed=False):
|
||||
"""Get the fixed, flexible, and plugin-provided field names for
|
||||
this object. The `computed` parameter controls whether computed
|
||||
(plugin-provided) fields are included in the key list.
|
||||
"""
|
||||
base_keys = super(PluggableModel, self).keys()
|
||||
if computed:
|
||||
return base_keys + self._getters().keys()
|
||||
else:
|
||||
return base_keys
|
||||
|
||||
|
||||
class LibModel(PluggableModel):
|
||||
"""A model base class that includes a reference to a Library object.
|
||||
It knows how to load and store itself from the database.
|
||||
"""
|
||||
|
|
@ -440,6 +477,10 @@ class Item(LibModel):
|
|||
_flex_table = 'item_attributes'
|
||||
_search_fields = ITEM_DEFAULT_FIELDS
|
||||
|
||||
@classmethod
|
||||
def _getters(cls):
|
||||
return plugins.item_field_getters()
|
||||
|
||||
@classmethod
|
||||
def from_path(cls, path):
|
||||
"""Creates a new item from the media file at the specified path.
|
||||
|
|
@ -777,6 +818,10 @@ class Album(LibModel):
|
|||
_flex_table = 'album_attributes'
|
||||
_search_fields = ALBUM_DEFAULT_FIELDS
|
||||
|
||||
@classmethod
|
||||
def _getters(cls):
|
||||
return plugins.album_field_getters()
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
"""Set the value of an album attribute."""
|
||||
if key == 'artpath':
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ class BeetsPlugin(object):
|
|||
commands that should be added to beets' CLI.
|
||||
"""
|
||||
return ()
|
||||
|
||||
|
||||
def queries(self):
|
||||
"""Should return a dict mapping prefixes to PluginQuery
|
||||
subclasses.
|
||||
|
|
@ -346,6 +346,28 @@ def import_stages():
|
|||
return stages
|
||||
|
||||
|
||||
# New-style (lazy) plugin-provided fields.
|
||||
|
||||
def item_field_getters():
|
||||
"""Get a dictionary mapping field names to unary functions that
|
||||
compute the field's value.
|
||||
"""
|
||||
funcs = {}
|
||||
for plugin in find_plugins():
|
||||
if plugin.template_fields:
|
||||
funcs.update(plugin.template_fields)
|
||||
return funcs
|
||||
|
||||
def album_field_getters():
|
||||
"""As above, for album fields.
|
||||
"""
|
||||
funcs = {}
|
||||
for plugin in find_plugins():
|
||||
if plugin.album_template_fields:
|
||||
funcs.update(plugin.album_template_fields)
|
||||
return funcs
|
||||
|
||||
|
||||
# Event dispatch.
|
||||
|
||||
def event_handlers():
|
||||
|
|
|
|||
Loading…
Reference in a new issue