From 9e6b998c50d70026cc6d4da5ffc9a360d1b0a42e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sybren=20A=2E=20St=C3=BCvel?= Date: Wed, 7 Sep 2016 16:36:25 +0200 Subject: [PATCH] Refactored static file handling so that extensions can provide static files --- pillar/__init__.py | 28 ++++++++++++++++------------ pillar/extension.py | 12 ++++++++++++ pillar/web/static.py | 12 ++++++++++++ 3 files changed, 40 insertions(+), 12 deletions(-) create mode 100644 pillar/web/static.py diff --git a/pillar/__init__.py b/pillar/__init__.py index e0664419..cdc6212d 100644 --- a/pillar/__init__.py +++ b/pillar/__init__.py @@ -231,7 +231,7 @@ class PillarServer(Eve): paths_list = [ jinja2.FileSystemLoader(path) for path in reversed(self.pillar_extensions_template_paths) - ] + ] # ...then load Pillar paths. pillar_dir = os.path.dirname(os.path.realpath(__file__)) @@ -251,23 +251,27 @@ class PillarServer(Eve): pillar.web.jinja.setup_jinja_env(self.jinja_env) def _config_static_dirs(self): - pillar_dir = os.path.dirname(os.path.realpath(__file__)) # Setup static folder for the instanced app self.static_folder = os.path.join(self.app_root, 'static') + # Setup static folder for Pillar - self.pillar_static_folder = os.path.join(pillar_dir, 'web', 'static') + pillar_dir = os.path.dirname(os.path.realpath(__file__)) + pillar_static_folder = os.path.join(pillar_dir, 'web', 'static') + self.register_static_file_endpoint('/static/pillar', 'static_pillar', pillar_static_folder) - from flask.views import MethodView - from flask import send_from_directory - from flask import current_app + # Setup static folders for extensions + for name, ext in self.pillar_extensions.items(): + if not ext.static_path: + continue + self.register_static_file_endpoint('/static/%s' % name, + 'static_%s' % name, + ext.static_path) - class PillarStaticFile(MethodView): - def get(self, filename): - return send_from_directory(current_app.pillar_static_folder, - filename) + def register_static_file_endpoint(self, url_prefix, endpoint_name, static_folder): + from pillar.web.static import PillarStaticFile - self.add_url_rule('/static/pillar/', - view_func=PillarStaticFile.as_view('static_pillar')) + view_func = PillarStaticFile.as_view(endpoint_name, static_folder=static_folder) + self.add_url_rule('%s/' % url_prefix, view_func=view_func) def process_extensions(self): # Re-initialise Eve after we allowed Pillar submodules to be loaded. diff --git a/pillar/extension.py b/pillar/extension.py index dd6f0f67..ff22b3af 100644 --- a/pillar/extension.py +++ b/pillar/extension.py @@ -72,5 +72,17 @@ class PillarExtension(object): """ return None + @property + def static_path(self): + """Returns the path where static files are stored. + + Registers an endpoint named 'static_', to use like: + `url_for('static_attract', filename='js/somefile.js')` + + May return None, in which case the extension will not be able to serve + static files. + """ + return None + def setup_app(self, app): """Called during app startup, after all extensions have loaded.""" diff --git a/pillar/web/static.py b/pillar/web/static.py new file mode 100644 index 00000000..118a0da3 --- /dev/null +++ b/pillar/web/static.py @@ -0,0 +1,12 @@ +"""Static file handling""" + +import flask +import flask.views + + +class PillarStaticFile(flask.views.MethodView): + def __init__(self, static_folder): + self.static_folder = static_folder + + def get(self, filename): + return flask.send_from_directory(self.static_folder, filename)