Browse Source

Moved to Flask-Plugins

sh4nks 11 years ago
parent
commit
64544057e1

+ 3 - 2
flaskbb/admin/views.py

@@ -14,12 +14,13 @@ from datetime import datetime
 from flask import (Blueprint, current_app, request, redirect, url_for, flash,
                    __version__ as flask_version)
 from flask.ext.login import current_user
+from flask.ext.plugins import get_plugins_list
 
 from flaskbb import __version__ as flaskbb_version
 from flaskbb.forum.forms import UserSearchForm
 from flaskbb.utils.helpers import render_template
 from flaskbb.utils.decorators import admin_required
-from flaskbb.extensions import db, plugin_manager
+from flaskbb.extensions import db
 from flaskbb.user.models import User, Group
 from flaskbb.forum.models import Post, Topic, Forum, Category, Report
 from flaskbb.admin.forms import (AddUserForm, EditUserForm, AddGroupForm,
@@ -97,7 +98,7 @@ def reports():
 @admin.route("/plugins")
 @admin_required
 def plugins():
-    return render_template("admin/plugins.html", plugins=plugin_manager.plugins)
+    return render_template("admin/plugins.html", plugins=get_plugins_list())
 
 
 @admin.route("/reports/unread")

+ 12 - 15
flaskbb/app.py

@@ -37,7 +37,7 @@ from flaskbb.utils.helpers import format_date, time_since, crop_title, \
 from flaskbb.utils.permissions import can_post_reply, can_post_topic, \
     can_delete_topic, can_delete_post, can_edit_post, can_lock_topic, \
     can_move_topic
-from flaskbb.plugins import hooks
+from flaskbb.hooks import hooks
 
 
 def create_app(config=None):
@@ -54,6 +54,7 @@ def create_app(config=None):
     # try to update the config via the environment variable
     app.config.from_envvar("FLASKBB_SETTINGS", silent=True)
 
+    configure_hooks(app)
     configure_blueprints(app)
     configure_extensions(app)
     configure_template_filters(app)
@@ -61,20 +62,6 @@ def create_app(config=None):
     configure_errorhandlers(app)
     configure_logging(app)
 
-    app.logger.debug("Loading plugins...")
-
-    plugin_manager.init_app(app)
-    # Just a temporary solution to enable the plugins.
-    plugin_manager.enable_plugins()
-
-    app.logger.debug(
-        "({}) {} Plugins loaded."
-        .format(len(plugin_manager.plugins),
-                plugin_manager.plugins)
-    )
-
-    app.jinja_env.globals.update(hooks=hooks)
-
     return app
 
 
@@ -142,6 +129,16 @@ def configure_extensions(app):
 
     login_manager.init_app(app)
 
+    app.logger.debug("Loading plugins...")
+    plugin_manager.init_app(app)
+
+    # Register the blueprints before the app is serving requests.
+    plugin_manager.setup_plugins()
+
+
+def configure_hooks(app):
+    app.jinja_env.globals.update(hooks=hooks)
+
 
 def configure_template_filters(app):
     """

+ 1 - 3
flaskbb/extensions.py

@@ -16,8 +16,7 @@ from flask.ext.debugtoolbar import DebugToolbarExtension
 from flask.ext.redis import Redis
 from flask.ext.migrate import Migrate
 from flask.ext.themes2 import Themes
-
-from flaskbb.plugins.manager import PluginManager
+from flask.ext.plugins import PluginManager
 
 
 # Database
@@ -44,6 +43,5 @@ migrate = Migrate()
 # Themes
 themes = Themes()
 
-
 # PluginManager
 plugin_manager = PluginManager()

+ 1 - 1
flaskbb/forum/views.py

@@ -27,7 +27,7 @@ from flaskbb.forum.models import (Category, Forum, Topic, Post, ForumsRead,
 from flaskbb.forum.forms import (QuickreplyForm, ReplyForm, NewTopicForm,
                                  ReportForm, UserSearchForm, SearchPageForm)
 from flaskbb.user.models import User
-from flaskbb.plugins import hooks
+from flaskbb.hooks import hooks
 
 forum = Blueprint("forum", __name__)
 

+ 8 - 0
flaskbb/hooks.py

@@ -0,0 +1,8 @@
+from flask.ext.plugins import HookManager
+
+hooks = HookManager()
+
+hooks.new("beforeIndex")
+hooks.new("afterIndex")
+hooks.new("beforeBreadcrumb")
+hooks.new("afterBreadcrumb")

+ 0 - 195
flaskbb/plugins/__init__.py

@@ -1,195 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    flaskbb.plugins
-    ~~~~~~~~~~~~~~~
-
-    The Plugin class that every plugin should implement
-
-    :copyright: (c) 2014 by the FlaskBB Team.
-    :license: BSD, see LICENSE for more details.
-"""
-
-
-class PluginError(Exception):
-    """Error class for all plugin errors."""
-    pass
-
-
-class Plugin(object):
-    """Every plugin should implement this class. It handles the registration
-    for the plugin hooks, creates or modifies additional relations or
-    registers plugin specific thinks"""
-
-    #: If you want create your tables with one command, put your models
-    #: in here.
-    models = []
-
-    #: The plugin name
-    name = None
-
-    #: The author of the plugin
-    author = None
-
-    #: The license of the plugin
-    license = None
-
-    #: A small description of the plugin.
-    description = None
-
-    #: The version of the plugin"""
-    version = "0.0.0"
-
-    def enable(self):
-        """Enable the plugin."""
-        raise NotImplementedError("{} has not implemented the "
-                                  "enable method".format(self.name))
-
-    def disable(self):
-        """Disable the plugin."""
-        raise NotImplementedError("{} has not implemented the "
-                                  "disable method".format(self.name))
-
-    def install(self):
-        """The plugin should specify here what needs to be installed.
-        For example, create the database and register the hooks."""
-        raise NotImplementedError("{} has not implemented the "
-                                  "install method".format(self.name))
-
-    def uninstall(self):
-        """Uninstalls the plugin and deletes the things that
-        the plugin has installed."""
-        raise NotImplementedError("{} has not implemented the "
-                                  "uninstall method".format(self.name))
-
-    # Some helpers
-    def create_table(self, model, db):
-        """Creates the table for the model
-
-        :param model: The Model which should be created
-        :param db: The database instance.
-        """
-        if not model.__table__.exists(bind=db.engine):
-            model.__table__.create(bind=db.engine)
-
-    def drop_table(self, model, db):
-        """Drops the table for the bounded model.
-
-        :param model: The model on which the table is bound.
-        :param db: The database instance.
-        """
-        model.__table__.drop(bind=db.engine)
-
-    def create_all_tables(self, db):
-        """A interface for creating all models specified in ``models``.
-        If no models are specified in that variable it will abort
-        with a exception.
-
-        :param db: The database instance
-        """
-        if len(self.models) > 0:
-            for model in self.models:
-                self.create_table(model, db)
-        else:
-            raise PluginError("No models found in 'models'.")
-
-    def drop_all_tables(self, db):
-        """A interface for dropping all models specified in the
-        variable ``models``. If no models are specified in that variable,
-        it will abort with an exception.
-
-        :param db: The database instance.
-        """
-        if len(self.models) > 0:
-            for model in self.models:
-                self.drop_table(model, db)
-        else:
-            raise PluginError("No models found in 'models'.")
-
-
-class HookManager(object):
-    """Manages all available hooks.
-
-    A new hook can be created like this::
-
-        hooks.new("testHook")
-
-    To add a callback to the hook you need to do that::
-
-        hooks.add("testHook", test_callback)
-
-    If you want to use the last method, you'd also need to pass a callback over
-    to the ``add`` method.
-    Then you might want to add somewhere in your code the ``caller`` where all
-    registered callbacks for the specified hook are going to be called.
-    For example::
-
-        def hello():
-            do_stuff_here()
-
-            hooks.call("testHook")
-
-            do_more_stuff_here()
-    """
-
-    def __init__(self):
-        self.hooks = {}
-
-    def new(self, name, hook):
-        """Creates a new hook.
-
-        :param name: The name of the hook.
-        """
-        if name not in self.hooks:
-            self.hooks[name] = hook
-
-    def add(self, name, callback):
-        """Adds a callback to the hook.
-
-        :param name: The name of the hook.
-
-        :param callback: The callback which should be added to the hook.
-        """
-        return self.hooks[name].add(callback)
-
-    def remove(self, name, callback):
-        """Removes a callback from the hook.
-
-        :param name: The name of the hook.
-
-        :param callback: The callback which should be removed
-        """
-        self.hooks[name].remove(callback)
-
-    def call(self, name, *args, **kwargs):
-        """Calls all callbacks from a named hook with the given arguments.
-
-        :param name: The name of the hook.
-        """
-        return self.hooks[name].call(*args, **kwargs)
-
-
-class Hook(object):
-    """Represents a hook."""
-
-    def __init__(self):
-        self.callbacks = []
-
-    def add(self, callback):
-        """Adds a callback to a hook"""
-        if callback not in self.callbacks:
-            self.callbacks.append(callback)
-        return callback
-
-    def remove(self, callback):
-        """Removes a callback from a hook"""
-        if callback in self.callbacks:
-            self.callbacks.remove(callback)
-
-    def call(self, *args, **kwargs):
-        """Runs all callbacks for the hook."""
-        for callback in self.callbacks:
-            return callback(*args, **kwargs)
-
-hooks = HookManager()
-hooks.new("beforeIndex", Hook())
-hooks.new("beforeBreadcrumb", Hook())

+ 3 - 1
flaskbb/plugins/example/__init__.py

@@ -1,5 +1,7 @@
 from flask import flash
-from flaskbb.plugins import Plugin, hooks
+from flask.ext.plugins import Plugin
+
+from flaskbb.hooks import hooks
 
 #: The name of your plugin class
 __version__ = "1.0.0"

+ 0 - 144
flaskbb/plugins/manager.py

@@ -1,144 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    flaskbb.plugins.manager
-    ~~~~~~~~~~~~~~~~~~~~~~~
-
-    The Plugin manager.
-
-    :copyright: (c) 2014 by the FlaskBB Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import os
-from werkzeug.utils import import_string
-
-
-class PluginManager(object):
-
-    def __init__(self, app=None, **kwargs):
-        """Initializes the PluginManager. It is also possible to initialize the
-        PluginManager via a factory. For example::
-
-            plugin_manager = PluginManager()
-            plugin_manager.init_app(app)
-
-        :param app: The flask application. It is needed to do plugin
-                    specific things like registering additional views or
-                    doing things where the application context is needed.
-
-        :param plugin_folder: The plugin folder where the plugins resides.
-
-        :param base_plugin_package: The plugins package name. It is usually the
-                                    same like the plugin_folder.
-        """
-        if app is not None:
-            self.init_app(app, **kwargs)
-
-        # All loaded plugins
-        self._plugins = []
-
-        # All found plugins
-        self._found_plugins = []
-
-    def init_app(self, app, plugin_folder="plugins",
-                 base_plugin_package="plugins"):
-        self.app = app
-        self.plugin_folder = os.path.join(self.app.root_path, plugin_folder)
-        self.base_plugin_package = ".".join(
-            [self.app.name, base_plugin_package]
-        )
-
-    @property
-    def plugins(self):
-        """Returns all loaded plugins. You still need to enable them."""
-        if not len(self._plugins):
-            self._plugins = self.load_plugins()
-        return self._plugins
-
-    def __getitem__(self, name):
-        for plugin in self.plugins:
-            if plugin.name == name:
-                return plugin
-        raise KeyError("Plugin %s is not known" % name)
-
-    def load_plugins(self):
-        """Loads all plugins. They are still disabled.
-        Returns a list with all loaded plugins. They should now be accessible
-        via self.plugins.
-        """
-        plugins = []
-        for plugin in self.iter_plugins():
-            plugins.append(plugin)
-
-        return plugins
-
-    def iter_plugins(self):
-        """Iterates over all possible plugins found in ``self.find_plugins()``,
-        imports them and if the import succeeded it will yield the plugin class.
-        """
-        for plugin in self.find_plugins():
-            plugin_class = import_string(plugin)
-
-            if plugin_class is not None:
-                yield plugin_class
-
-    def find_plugins(self):
-        """Find all possible plugins in the plugin folder."""
-        for item in os.listdir(self.plugin_folder):
-            if os.path.isdir(os.path.join(self.plugin_folder, item)) and \
-                    os.path.exists(
-                        os.path.join(self.plugin_folder, item, "__init__.py")):
-
-                plugin = ".".join([self.base_plugin_package, item])
-
-                # Same like from flaskbb.plugins.pluginname import __plugin__
-                tmp = __import__(
-                    plugin, globals(), locals(), ["__plugin__"], -1
-                )
-
-                try:
-                    plugin = "{}.{}".format(plugin, tmp.__plugin__)
-                    self._found_plugins.append(plugin)
-                except AttributeError:
-                    pass
-
-        return self._found_plugins
-
-    def install_plugins(self, plugins=None):
-        """Install all or selected plugins.
-
-        :param plugins: An iterable with plugins. If no plugins are passed
-                        it will try to install all plugins.
-        """
-        for plugin in plugins or self.plugins:
-            with self.app.app_context():
-                plugin().install()
-
-    def uninstall_plugins(self, plugins=None):
-        """Uninstall the plugin.
-
-        :param plugins: An iterable with plugins. If no plugins are passed
-                        it will try to uninstall all plugins.
-        """
-        for plugin in plugins or self.plugins:
-            with self.app.app_context():
-                plugin().uninstall()
-
-    def enable_plugins(self, plugins=None):
-        """Enable all or selected plugins.
-
-        :param plugins: An iterable with plugins. If no plugins are passed
-                        it will try to enable all plugins.
-        """
-        for plugin in plugins or self.plugins:
-            with self.app.app_context():
-                plugin().enable()
-
-    def disable_plugins(self, plugins=None):
-        """Disable all or selected plugins.
-
-        :param plugins: An iterable with plugins. If no plugins are passed
-                        it will try to disable all plugins.
-        """
-        for plugin in plugins or self.plugins:
-            with self.app.app_context():
-                plugin().disable()