diff --git a/beets/plugins.py b/beets/plugins.py index 3dca22a97..eaaf9e9f7 100755 --- a/beets/plugins.py +++ b/beets/plugins.py @@ -31,6 +31,14 @@ LASTFM_KEY = '2dc3914abf35f0d9c92d97d8f8e42b43' log = logging.getLogger('beets') +class PluginConflictException(Exception): + """Indicates that the services provided by one plugin conflict with + those of another. + + For example two plugins may define different types for flexible fields. + """ + + # Managing the plugins themselves. class BeetsPlugin(object): @@ -247,6 +255,22 @@ def queries(): return out +def types(model_cls): + # Gives us `item_types` and `album_types` + attr_name = '{0}_types'.format(model_cls.__name__.lower()) + types = {} + for plugin in find_plugins(): + plugin_types = getattr(plugin, attr_name, {}) + for field in plugin_types: + if field in types: + raise PluginConflictException( + u'Plugin {0} defines flexible field {1} ' + 'which has already been defined.' + .format(plugin.name,)) + types.update(plugin_types) + return types + + def track_distance(item, info): """Gets the track distance calculated by all loaded plugins. Returns a Distance object. diff --git a/beets/ui/__init__.py b/beets/ui/__init__.py index 7e3e7559c..c3bb7a158 100644 --- a/beets/ui/__init__.py +++ b/beets/ui/__init__.py @@ -869,6 +869,8 @@ def _setup(options, lib=None): if lib is None: lib = _open_library(config) plugins.send("library_opened", lib=lib) + library.Item._types = plugins.types(library.Item) + library.Album._types = plugins.types(library.Album) return subcommands, plugins, lib