Browse Source

Just playing around a bit

sh4nks 11 years ago
parent
commit
480be11acb

+ 13 - 1
flaskbb/app.py

@@ -36,7 +36,8 @@ from flaskbb.utils.helpers import format_date, time_since, crop_title, \
 # permission checks (here they are used for the jinja filters)
 # permission checks (here they are used for the jinja filters)
 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_moderate
+    can_move_topic
+from flaskbb.plugins.manager import PluginManager
 
 
 
 
 def create_app(config=None):
 def create_app(config=None):
@@ -60,6 +61,17 @@ def create_app(config=None):
     configure_errorhandlers(app)
     configure_errorhandlers(app)
     configure_logging(app)
     configure_logging(app)
 
 
+    app.logger.debug("Loading plugins...")
+
+    plugin_manager = PluginManager(app)
+    plugin_manager.load_plugins()
+
+    app.logger.debug(
+        "({}) {} Plugins loaded."
+        .format(len(plugin_manager.plugins),
+                plugin_manager.plugins)
+    )
+
     return app
     return app
 
 
 
 

+ 4 - 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
 
 
 forum = Blueprint("forum", __name__)
 forum = Blueprint("forum", __name__)
 
 
@@ -42,6 +42,9 @@ def index():
     post_count = Post.query.count()
     post_count = Post.query.count()
     newest_user = User.query.order_by(User.id.desc()).first()
     newest_user = User.query.order_by(User.id.desc()).first()
 
 
+    current_app.logger.debug("Runnnig beforeIndex hook...")
+    hooks.runHook(hooks.registered.beforeIndex)
+
     # Check if we use redis or not
     # Check if we use redis or not
     if not current_app.config["REDIS_ENABLED"]:
     if not current_app.config["REDIS_ENABLED"]:
         online_users = User.query.filter(User.lastseen >= time_diff()).count()
         online_users = User.query.filter(User.lastseen >= time_diff()).count()

+ 31 - 12
flaskbb/plugins/__init__.py

@@ -24,30 +24,49 @@ class Plugin(object):
     #: in here.
     #: in here.
     models = []
     models = []
 
 
-    #: The name of the plugin
-    #: E.g. "Example Plugin"
-    name = None
-
-    #: A small description of the plugin
-    description = None
-
-    def install(self, app=None):
+    @property
+    def name(self):
+        return self.__class__.__name__
+
+    @property
+    def description(self):
+        return ""
+
+    @property
+    def version(self):
+        return "0.0.0"
+
+    def enable(self):
+        """Enable the plugin."""
+        #raise NotImplemented()
+        # Just temporary
+        self.install()
+
+    def disable(self):  # pragma: no cover
+        """Disable the plugin."""
+        #pass
+        # Just temporary
+        self.uninstall()
+
+    def install(self):
         """The plugin should specify here what needs to be installed.
         """The plugin should specify here what needs to be installed.
         For example, create the database and register the hooks."""
         For example, create the database and register the hooks."""
-        raise NotImplementedError
+        raise NotImplemented()
 
 
-    def uninstall(self, app=None):
+    def uninstall(self):
         """Uninstalls the plugin and deletes the things that
         """Uninstalls the plugin and deletes the things that
         the plugin has installed."""
         the plugin has installed."""
-        raise NotImplementedError
+        raise NotImplemented()
 
 
+    # Some helpers
     def create_table(self, model, db):
     def create_table(self, model, db):
         """Creates the table for the model
         """Creates the table for the model
 
 
         :param model: The Model which should be created
         :param model: The Model which should be created
         :param db: The database instance.
         :param db: The database instance.
         """
         """
-        model.__table__.create(bind=db.engine)
+        if not model.__table__.exists(bind=db.engine):
+            model.__table__.create(bind=db.engine)
 
 
     def drop_table(self, model, db):
     def drop_table(self, model, db):
         """Drops the table for the bounded model.
         """Drops the table for the bounded model.

+ 27 - 0
flaskbb/plugins/example/__init__.py

@@ -0,0 +1,27 @@
+from flask import flash
+from flaskbb.plugins import Plugin, hooks
+
+
+#: The name of your plugin class
+__plugin__ = "ExamplePlugin"
+
+
+def hello_world():
+    flash("Hello World from {}".format(__plugin__), "success")
+
+
+class ExamplePlugin(Plugin):
+    @property
+    def description(self):
+        return "Example plugin"
+
+    @property
+    def version(self):
+        return "1.0.0"
+
+    def install(self):
+        # register hooks and blueprints/routes here
+        hooks.registered.beforeIndex.append(hello_world)
+
+    def uninstall(self):
+        pass

+ 21 - 0
flaskbb/plugins/hooks.py

@@ -0,0 +1,21 @@
+#import hooks
+# inspired fromhttp://stackoverflow.com/questions/932069/building-a-minimal-plugin-architecture-in-python
+#hooks.registered.beforeIndex.append(hello_world)
+#hooks.runHook(hooks.registered.beforeIndex)
+
+
+class HookError(Exception):
+    pass
+
+
+class registered(object):
+    beforeIndex = []
+    afterIndex = []
+
+
+def runHook(hook):
+    for h in hook:
+        try:
+            h()
+        except Exception as e:
+            raise HookError("An error occured %s", e)

+ 0 - 60
flaskbb/plugins/loader.py

@@ -1,60 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    flaskbb.plugins.loader
-    ~~~~~~~~~~~~~~~~~~~~~~
-
-    The Plugin loader.
-
-    :copyright: (c) 2014 by the FlaskBB Team.
-    :license: BSD, see LICENSE for more details.
-"""
-import os
-
-
-class PluginLoader(object):
-
-    #: Stores all founded plugins in the plugins folder
-    plugins = list()
-
-    def __init__(self, app):
-        self.app = app
-        self.plugin_folder = os.path.join(self.app.root_path, "plugins")
-        self.base_plugin_package = ".".join([self.app.name, "plugins"])
-
-    def load_plugins(self):
-        """Loads all plugins"""
-        #from flaskbb.plugins.pluginname import PluginName
-        #__import__(plugin, globals(), locals(), [tmp.__plugin__], -1)
-        pass
-
-    def check_plugin(self, plugin):
-        """Checks if a plugin is appropriate.
-
-        :param plugin:
-        """
-        pass
-
-    def find_plugins(self):
-        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
-                )
-
-                self.plugins.append(tmp.__plugin__)
-
-"""
-for ipython:
-from flask import current_app
-from flaskbb.plugins.loader import PluginLoader
-loader = PluginLoader(current_app)
-loader.find_plugins()
-loader.plugins
-"""

+ 94 - 0
flaskbb/plugins/manager.py

@@ -0,0 +1,94 @@
+# -*- coding: utf-8 -*-
+"""
+    flaskbb.plugins.manager
+    ~~~~~~~~~~~~~~~~~~~~~~~
+
+    The Plugin loader.
+
+    :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):
+        self.app = app
+        self.plugin_folder = os.path.join(self.app.root_path, "plugins")
+        self.base_plugin_package = ".".join([self.app.name, "plugins"])
+
+        self.found_plugins = []
+        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 register_blueprints(self, blueprint):
+        self.app.register_blueprints(blueprint)
+
+    def load_plugins(self):
+        """Loads and install all found plugins.
+        TODO: Only load/install activated plugins
+        """
+        self.find_plugins()
+
+        for plugin in self.iter_plugins():
+            with self.app.app_context():
+                plugin().install()
+
+        #self.enable_plugins(self.plugins)
+
+    def iter_plugins(self):
+        for plugin in self.found_plugins:
+            plugin_class = import_string(plugin)
+
+            if plugin_class is not None:
+                self.plugins.append(plugin)
+                yield plugin_class
+
+    def find_plugins(self):
+        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
+
+    def enable_plugins(self, plugins=None):
+        """Enable all or selected plugins."""
+
+        for plugin in plugins or self.plugins:
+            plugin.enable()
+
+    def disable_plugins(self, plugins=None):
+        """Disable all or selected plugins."""
+
+        for plugin in plugins or self.plugins:
+            plugin.disable()
+
+
+"""
+for ipython:
+from flask import current_app
+from flaskbb.plugins import Plugin
+from flaskbb.plugins.manager import PluginManager
+manager = PluginLoader(current_app)
+manager.find_plugins()
+manager.plugins
+"""

+ 11 - 4
flaskbb/plugins/portal/__init__.py

@@ -1,7 +1,8 @@
+from flask import current_app
 from flaskbb.extensions import db
 from flaskbb.extensions import db
 from flaskbb.plugins import Plugin
 from flaskbb.plugins import Plugin
 
 
-from .portal import PortalModel
+from .portal import PortalModel, portal
 
 
 
 
 #: The name of your plugin class
 #: The name of your plugin class
@@ -9,14 +10,20 @@ __plugin__ = "PortalPlugin"
 
 
 
 
 class PortalPlugin(Plugin):
 class PortalPlugin(Plugin):
+    # Register the models
     models = [PortalModel]
     models = [PortalModel]
 
 
-    name = "Portal Plugin"
-    description = "A simple Portal"
+    @property
+    def description(self):
+        return "A simple portal plugin"
+
+    @property
+    def version(self):
+        return "0.0.1"
 
 
     def install(self):
     def install(self):
         self.create_all_tables(db)
         self.create_all_tables(db)
-        #
+        current_app.register_blueprint(portal)
         # register hooks and blueprints/routes here
         # register hooks and blueprints/routes here
 
 
     def uninstall(self):
     def uninstall(self):

+ 10 - 0
flaskbb/plugins/portal/portal.py

@@ -9,9 +9,19 @@
     :copyright: (c) 2014 by the FlaskBB Team.
     :copyright: (c) 2014 by the FlaskBB Team.
     :license: BSD, see LICENSE for more details.
     :license: BSD, see LICENSE for more details.
 """
 """
+from flask import Blueprint
 from flaskbb.extensions import db
 from flaskbb.extensions import db
+from flaskbb.utils.helpers import render_template
+
+
+portal = Blueprint("portal", __name__, template_folder="templates")
 
 
 
 
 class PortalModel(db.Model):
 class PortalModel(db.Model):
     id = db.Column(db.Integer, primary_key=True)
     id = db.Column(db.Integer, primary_key=True)
     forum_id = db.Column(db.Integer, db.ForeignKey("forums.id"))
     forum_id = db.Column(db.Integer, db.ForeignKey("forums.id"))
+
+
+@portal.route("/portal")
+def portal_index():
+    return render_template("portal.html")

+ 5 - 0
flaskbb/plugins/portal/templates/portal.html

@@ -0,0 +1,5 @@
+{% extends theme('layout.html') %}
+
+{% block content %}
+Portal Plugin
+{% endblock %}