diff options
author | Will Kahn-Greene <willg@bluesock.org> | 2012-03-12 21:17:08 -0400 |
---|---|---|
committer | Will Kahn-Greene <willg@bluesock.org> | 2012-05-13 00:00:08 -0400 |
commit | 29b6f91740e68d804612ff68295020f6cfa16071 (patch) | |
tree | 8812f0d9e1fd3894c097c56e5778c21e22d1fa61 /mediagoblin/tools/pluginapi.py | |
parent | f10c3bb8e5fc44b6d580261a05f1e4b4639e0949 (diff) | |
download | mediagoblin-29b6f91740e68d804612ff68295020f6cfa16071.tar.lz mediagoblin-29b6f91740e68d804612ff68295020f6cfa16071.tar.xz mediagoblin-29b6f91740e68d804612ff68295020f6cfa16071.zip |
401. Plugin infrastructure
* implements installing, loading and setup for plugins
* codifies configuration
* has a sample plugin
* docs
* tests
Diffstat (limited to 'mediagoblin/tools/pluginapi.py')
-rw-r--r-- | mediagoblin/tools/pluginapi.py | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/mediagoblin/tools/pluginapi.py b/mediagoblin/tools/pluginapi.py new file mode 100644 index 00000000..194d192e --- /dev/null +++ b/mediagoblin/tools/pluginapi.py @@ -0,0 +1,118 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +""" +This module implements the plugin api bits and provides the plugin +base. + +Two things about things in this module: + +1. they should be excessively well documented because we should pull + from this file for the docs + +2. they should be well tested + + +How do plugins work? +==================== + +You create a Python package. In that package, you define a high-level +``__init__.py`` that either defines or imports modules that define +classes that inherit from the ``Plugin`` class. + + +Lifecycle +========= + +1. All the modules listed as subsections of the ``plugins`` section in + the config file are imported and any ``Plugin`` subclasses are + loaded causing it to be registered with the ``PluginCache``. + +2. After all plugin modules are imported, registered plugins are + instantiated and ``setup_plugin`` is called with the configuration. + + +How to build a plugin +===================== + +See the documentation on building plugins. +""" + +import logging + +from mediagoblin import mg_globals + + +_log = logging.getLogger(__name__) + + +class PluginCache(object): + """Cache of plugin things""" + __state = { + # list of plugin classes + "plugin_classes": [], + + # list of plugin objects + "plugin_objects": [] + } + + def clear(self): + """This is only useful for testing.""" + del self.plugin_classes[:] + del self.plugin_objects[:] + + def __init__(self): + self.__dict__ = self.__state + + def register_plugin_class(self, plugin_class): + """Registers a plugin class""" + self.plugin_classes.append(plugin_class) + + def register_plugin_object(self, plugin_obj): + """Registers a plugin object""" + self.plugin_objects.append(plugin_obj) + + +class MetaPluginClass(type): + """Metaclass for PluginBase derivatives""" + def __new__(cls, name, bases, attrs): + new_class = super(MetaPluginClass, cls).__new__(cls, name, bases, attrs) + parents = [b for b in bases if isinstance(b, MetaPluginClass)] + if not parents: + return new_class + PluginCache().register_plugin_class(new_class) + return new_class + + +class Plugin(object): + __metaclass__ = MetaPluginClass + + def setup_plugin(self): + pass + + +def get_config(key): + """Retrieves the configuration for a specified plugin by key + + Example: + + >>> get_config('mediagoblin.plugins.sampleplugin') + {'foo': 'bar'} + """ + + global_config = mg_globals.global_config + plugin_section = global_config.get('plugins', {}) + return plugin_section.get(key, {}) |