Refactor modules into a plugin-based system
All modules are now plugins. The config.py calls load_plugin for each plugin it needs (some plugins may load others automatically). Also each plugin keeps its own template folder which gets added to the template search path, so i.e. if the photo plugin is unloaded completely, the URL endpoints won't work either (with the old system, since the HTML templates still existed in the default root the endpoints would still serve pages, just without any Python logic behind them).
This commit is contained in:
parent
0146fea8e0
commit
8a2d6a7c04
|
@ -5,6 +5,7 @@
|
|||
import os
|
||||
_basedir = os.path.abspath(os.path.dirname(__file__))
|
||||
import datetime
|
||||
from rophako.plugin import load_plugin
|
||||
|
||||
DEBUG = True
|
||||
|
||||
|
@ -116,3 +117,21 @@ COMMENT_TIME_FORMAT = "%A, %B %d %Y @ %I:%M %p"
|
|||
# We use Gravatar for comments if the user provides an e-mail address. Specify
|
||||
# the URL to a fallback image to use in case they don't have a gravatar.
|
||||
COMMENT_DEFAULT_AVATAR = ""
|
||||
|
||||
################################################################################
|
||||
## Enabled Plugins ##
|
||||
################################################################################
|
||||
|
||||
# Place all the load_plugin calls down here. Some of the plugins need to refer
|
||||
# to config params above so those need to get declared before the plugin begins
|
||||
# to initialize itself.
|
||||
#
|
||||
# Some plugins will automatically load others as dependencies, i.e. the blog
|
||||
# and photo will load comment, and comment will load emoticons. But it doesn't
|
||||
# hurt to list them all out here to be explicit anyway.
|
||||
|
||||
load_plugin("rophako.modules.blog")
|
||||
load_plugin("rophako.modules.photo")
|
||||
load_plugin("rophako.modules.comment")
|
||||
load_plugin("rophako.modules.emoticons")
|
||||
load_plugin("rophako.modules.contact")
|
|
@ -8,7 +8,7 @@ import os
|
|||
import json
|
||||
|
||||
import config
|
||||
from rophako import app
|
||||
from rophako.app import app
|
||||
from rophako.utils import template, login_required
|
||||
import rophako.model.blog as Blog
|
||||
import rophako.jsondb as JsonDB
|
|
@ -1,3 +1,7 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
"""Flask app for Rophako."""
|
||||
|
||||
from flask import Flask, g, request, session, render_template, send_file, abort
|
||||
from flask_sslify import SSLify
|
||||
import jinja2
|
||||
|
@ -5,13 +9,25 @@ import os.path
|
|||
import time
|
||||
import sys
|
||||
|
||||
import config
|
||||
from rophako import __version__
|
||||
import rophako.utils
|
||||
|
||||
# Get the Flask app object ready right away so other modules can import it
|
||||
# without getting a circular import error.
|
||||
app = Flask(__name__,
|
||||
static_url_path="/.static",
|
||||
)
|
||||
|
||||
# We use a custom Jinja loader to support multiple template paths for custom
|
||||
# and default templates. The base list of template paths to check includes
|
||||
# your custom path (from config.SITE_ROOT), the "rophako/www" path for normal
|
||||
# pages, and then the blueprint paths for all imported plugins. This list will
|
||||
# be extended while blueprints are being loaded and passed in below to the
|
||||
# jinja2.ChoiceLoader.
|
||||
BLUEPRINT_PATHS = []
|
||||
|
||||
import config
|
||||
from rophako import __version__
|
||||
from rophako.plugin import load_plugin
|
||||
import rophako.utils
|
||||
|
||||
app.DEBUG = config.DEBUG
|
||||
app.secret_key = config.SECRET_KEY
|
||||
|
||||
|
@ -20,28 +36,32 @@ if config.FORCE_SSL:
|
|||
app.config['SESSION_COOKIE_SECURE'] = True
|
||||
sslify = SSLify(app)
|
||||
|
||||
# Load all the blueprints!
|
||||
from rophako.modules.admin import mod as AdminModule
|
||||
from rophako.modules.account import mod as AccountModule
|
||||
from rophako.modules.blog import mod as BlogModule
|
||||
from rophako.modules.photo import mod as PhotoModule
|
||||
from rophako.modules.comment import mod as CommentModule
|
||||
from rophako.modules.emoticons import mod as EmoticonsModule
|
||||
from rophako.modules.contact import mod as ContactModule
|
||||
app.register_blueprint(AdminModule)
|
||||
app.register_blueprint(AccountModule)
|
||||
app.register_blueprint(BlogModule)
|
||||
app.register_blueprint(PhotoModule)
|
||||
app.register_blueprint(CommentModule)
|
||||
app.register_blueprint(EmoticonsModule)
|
||||
app.register_blueprint(ContactModule)
|
||||
# Load all the built-in essential plugins.
|
||||
load_plugin("rophako.modules.admin")
|
||||
load_plugin("rophako.modules.account")
|
||||
# from rophako.modules.admin import mod as AdminModule
|
||||
# from rophako.modules.account import mod as AccountModule
|
||||
# from rophako.modules.blog import mod as BlogModule
|
||||
# from rophako.modules.photo import mod as PhotoModule
|
||||
# from rophako.modules.comment import mod as CommentModule
|
||||
# from rophako.modules.emoticons import mod as EmoticonsModule
|
||||
# from rophako.modules.contact import mod as ContactModule
|
||||
# app.register_blueprint(AdminModule)
|
||||
# app.register_blueprint(AccountModule)
|
||||
# app.register_blueprint(BlogModule)
|
||||
# app.register_blueprint(PhotoModule)
|
||||
# app.register_blueprint(CommentModule)
|
||||
# app.register_blueprint(EmoticonsModule)
|
||||
# app.register_blueprint(ContactModule)
|
||||
|
||||
# Custom Jinja handler to support custom- and default-template folders for
|
||||
# rendering templates.
|
||||
app.jinja_loader = jinja2.ChoiceLoader([
|
||||
jinja2.FileSystemLoader(config.SITE_ROOT), # Site specific.
|
||||
jinja2.FileSystemLoader("rophako/www"), # Default/fall-back
|
||||
])
|
||||
template_paths = [
|
||||
config.SITE_ROOT, # Site specific.
|
||||
"rophako/www", # Default/fall-back
|
||||
]
|
||||
template_paths.extend(BLUEPRINT_PATHS)
|
||||
app.jinja_loader = jinja2.ChoiceLoader([ jinja2.FileSystemLoader(x) for x in template_paths])
|
||||
|
||||
app.jinja_env.globals["csrf_token"] = rophako.utils.generate_csrf_token
|
||||
app.jinja_env.globals["include_page"] = rophako.utils.include
|
||||
|
@ -152,9 +172,4 @@ def not_found(error):
|
|||
|
||||
@app.errorhandler(403)
|
||||
def forbidden(error):
|
||||
return render_template('errors/403.html', **g.info), 403
|
||||
|
||||
|
||||
# Domain specific endpoints.
|
||||
if config.SITE_NAME == "kirsle.net":
|
||||
import rophako.modules.kirsle_legacy
|
||||
return render_template('errors/403.html', **g.info), 403
|
|
@ -14,10 +14,12 @@ import rophako.model.blog as Blog
|
|||
import rophako.model.comment as Comment
|
||||
import rophako.model.emoticons as Emoticons
|
||||
from rophako.utils import template, render_markdown, pretty_time, login_required
|
||||
from rophako.plugin import load_plugin
|
||||
from rophako.log import logger
|
||||
from config import *
|
||||
|
||||
mod = Blueprint("blog", __name__, url_prefix="/blog")
|
||||
load_plugin("rophako.modules.comment")
|
||||
|
||||
@mod.route("/")
|
||||
def index():
|
|
@ -9,10 +9,12 @@ import time
|
|||
import rophako.model.user as User
|
||||
import rophako.model.comment as Comment
|
||||
from rophako.utils import template, pretty_time, login_required, sanitize_name
|
||||
from rophako.plugin import load_plugin
|
||||
from rophako.log import logger
|
||||
from config import *
|
||||
|
||||
mod = Blueprint("comment", __name__, url_prefix="/comments")
|
||||
load_plugin("rophako.modules.emoticons")
|
||||
|
||||
|
||||
@mod.route("/")
|
|
@ -7,10 +7,12 @@ from flask import Blueprint, g, request, redirect, url_for, session, flash
|
|||
import rophako.model.user as User
|
||||
import rophako.model.photo as Photo
|
||||
from rophako.utils import template, pretty_time, login_required, ajax_response
|
||||
from rophako.plugin import load_plugin
|
||||
from rophako.log import logger
|
||||
from config import *
|
||||
|
||||
mod = Blueprint("photo", __name__, url_prefix="/photos")
|
||||
load_plugin("rophako.modules.comment")
|
||||
|
||||
@mod.route("/")
|
||||
def index():
|
29
rophako/plugin.py
Normal file
29
rophako/plugin.py
Normal file
|
@ -0,0 +1,29 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
"""Dynamic CMS plugin loader."""
|
||||
|
||||
import os
|
||||
from importlib import import_module
|
||||
from rophako.app import app, BLUEPRINT_PATHS
|
||||
|
||||
def load_plugin(name, as_blueprint=True, template_path=None):
|
||||
"""Load a Rophako CMS plugin.
|
||||
|
||||
* `name` is a Python module name, i.e. `rophako.modules.blog`
|
||||
* `as_blueprint` is True if the module exports a blueprint object called
|
||||
`mod` that can be attached to the Flask app. Set this value to False if
|
||||
you simply need to include a Python module that isn't a blueprint.
|
||||
* `template_path` is a filesystem path where the blueprint's templates
|
||||
can be found. If not provided, the path is automatically determined
|
||||
based on the module name, which is suitable for the built-in plugins."""
|
||||
module = import_module(name)
|
||||
if as_blueprint:
|
||||
mod = getattr(module, "mod")
|
||||
app.register_blueprint(mod)
|
||||
|
||||
# Get the template path to add to the BLUEPRINT_PATHS.
|
||||
if template_path is None:
|
||||
module_path = name.replace(".", "/")
|
||||
template_path = os.path.join(module_path, "templates")
|
||||
|
||||
BLUEPRINT_PATHS.append(template_path)
|
Loading…
Reference in New Issue
Block a user