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,
 from flask import (Blueprint, current_app, request, redirect, url_for, flash,
                    __version__ as flask_version)
                    __version__ as flask_version)
 from flask.ext.login import current_user
 from flask.ext.login import current_user
+from flask.ext.plugins import get_plugins_list
 
 
 from flaskbb import __version__ as flaskbb_version
 from flaskbb import __version__ as flaskbb_version
 from flaskbb.forum.forms import UserSearchForm
 from flaskbb.forum.forms import UserSearchForm
 from flaskbb.utils.helpers import render_template
 from flaskbb.utils.helpers import render_template
 from flaskbb.utils.decorators import admin_required
 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.user.models import User, Group
 from flaskbb.forum.models import Post, Topic, Forum, Category, Report
 from flaskbb.forum.models import Post, Topic, Forum, Category, Report
 from flaskbb.admin.forms import (AddUserForm, EditUserForm, AddGroupForm,
 from flaskbb.admin.forms import (AddUserForm, EditUserForm, AddGroupForm,
@@ -97,7 +98,7 @@ def reports():
 @admin.route("/plugins")
 @admin.route("/plugins")
 @admin_required
 @admin_required
 def plugins():
 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")
 @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, \
 from flaskbb.utils.permissions import can_post_reply, can_post_topic, \
     can_delete_topic, can_delete_post, can_edit_post, can_lock_topic, \
     can_delete_topic, can_delete_post, can_edit_post, can_lock_topic, \
     can_move_topic
     can_move_topic
-from flaskbb.plugins import hooks
+from flaskbb.hooks import hooks
 
 
 
 
 def create_app(config=None):
 def create_app(config=None):
@@ -54,6 +54,7 @@ def create_app(config=None):
     # try to update the config via the environment variable
     # try to update the config via the environment variable
     app.config.from_envvar("FLASKBB_SETTINGS", silent=True)
     app.config.from_envvar("FLASKBB_SETTINGS", silent=True)
 
 
+    configure_hooks(app)
     configure_blueprints(app)
     configure_blueprints(app)
     configure_extensions(app)
     configure_extensions(app)
     configure_template_filters(app)
     configure_template_filters(app)
@@ -61,20 +62,6 @@ def create_app(config=None):
     configure_errorhandlers(app)
     configure_errorhandlers(app)
     configure_logging(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
     return app
 
 
 
 
@@ -142,6 +129,16 @@ def configure_extensions(app):
 
 
     login_manager.init_app(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):
 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.redis import Redis
 from flask.ext.migrate import Migrate
 from flask.ext.migrate import Migrate
 from flask.ext.themes2 import Themes
 from flask.ext.themes2 import Themes
-
-from flaskbb.plugins.manager import PluginManager
+from flask.ext.plugins import PluginManager
 
 
 
 
 # Database
 # Database
@@ -44,6 +43,5 @@ migrate = Migrate()
 # Themes
 # Themes
 themes = Themes()
 themes = Themes()
 
 
-
 # PluginManager
 # PluginManager
 plugin_manager = 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,
 from flaskbb.forum.forms import (QuickreplyForm, ReplyForm, NewTopicForm,
                                  ReportForm, UserSearchForm, SearchPageForm)
                                  ReportForm, UserSearchForm, SearchPageForm)
 from flaskbb.user.models import User
 from flaskbb.user.models import User
-from flaskbb.plugins import hooks
+from flaskbb.hooks import hooks
 
 
 forum = Blueprint("forum", __name__)
 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 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
 #: The name of your plugin class
 __version__ = "1.0.0"
 __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()