diff options
author | Guido Günther <agx@sigxcpu.org> | 2017-12-21 09:47:05 +0100 |
---|---|---|
committer | Guido Günther <agx@sigxcpu.org> | 2017-12-21 10:07:23 +0100 |
commit | bec30b02537672617c36a23190e7a4813eb49d4f (patch) | |
tree | 97f65a281bf0a5fd60dd3a09022b1b3fceb54fac |
Initial commit
-rw-r--r-- | .travis.yml | 12 | ||||
-rw-r--r-- | README.rst | 33 | ||||
-rw-r--r-- | dev_requirements.txt | 1 | ||||
-rw-r--r-- | flask_xstatic.py | 91 | ||||
-rw-r--r-- | setup.cfg | 3 | ||||
-rwxr-xr-x | setup.py | 42 |
6 files changed, 182 insertions, 0 deletions
diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..b1b767c --- /dev/null +++ b/.travis.yml @@ -0,0 +1,12 @@ +--- +sudo: false +language: python + +python: + - "2.7" + - "3.5" + - "3.6" + +install: "pip install -r dev_requirements.txt" +script: + - flake8 diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..a003141 --- /dev/null +++ b/README.rst @@ -0,0 +1,33 @@ +Flask-XStatic +============= + +A flask extionsion to serve xstatic files. Can be useful if you don't use an +asset pipeline and server e.g. xstatic packaged javascript files directly. + +Setup +----- +Upon initialization tell flask about the xstatic modules you want to +use:: + + app = Flask(__name__) + app.config.from_object(__name__) + app.config.update(dict( + XSTATIC_MODULES="bootstrap_scss,jquery", + )) + xstaticfiles = XStaticFiles(app) + +Serving files +------------- +Install a minimal route handler:: + + @app.route('/xstatic/<module>/<path:filename>') + def xstatic(module, filename): + return xstaticfiles.serve_or_404(module, filename) + +In your templates you can then use xstatic_url_for:: + + <script type=text/javascript src="{{ xstatic_url_for(module='jquery', path='jquery.min.js') }}"></script> + +This has the advantage that you can later serve files from a static +web server by adjusting 'XSTATIC_ROOT' and 'XSTATIC_PROTO' without +having to modify any code. diff --git a/dev_requirements.txt b/dev_requirements.txt new file mode 100644 index 0000000..56a1631 --- /dev/null +++ b/dev_requirements.txt @@ -0,0 +1 @@ +flake8==3.5.0 diff --git a/flask_xstatic.py b/flask_xstatic.py new file mode 100644 index 0000000..df90f64 --- /dev/null +++ b/flask_xstatic.py @@ -0,0 +1,91 @@ +# vim: set fileencoding=utf-8 : +# +# (C) 2017 Guido Guenther <agx@sigxcpu.org> +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +""" +Tiny flask extionsion to serve xstatic files +""" + +import os +from flask import current_app, abort +from flask.helpers import send_file +import xstatic.main + +# Find the stack on which we want to store the sqlalchemy session. +# Starting with Flask 0.9, the _app_ctx_stack is the correct one, +# before that we need to use the _request_ctx_stack. +try: + from flask import _app_ctx_stack as stack +except ImportError: + from flask import _request_ctx_stack as stack + + +class XStaticFiles(object): + + def __init__(self, app=None): + self.app = app + if app is not None: + self.init_app(app) + + def init_app(self, app): + app.config.setdefault('XSTATIC_MODULES', None) + app.config.setdefault('XSTATIC_ROOT', '/xstatic') + app.config.setdefault('XSTATIC_PROTO', 'http') + # Use the newstyle teardown_appcontext if it's available, + # otherwise fall back to the request context + if hasattr(app, 'teardown_appcontext'): + app.teardown_appcontext(self.teardown) + else: + app.teardown_request(self.teardown) + + self.app.jinja_env.globals['xstatic_url_for'] = self.url_for + + def _load(self): + modules = current_app.config['XSTATIC_MODULES'] + if not modules: + return {} + modules = modules.split(',') + pkg = __import__('xstatic.pkg', fromlist=modules) + url = current_app.config['XSTATIC_ROOT'] + proto = current_app.config['XSTATIC_PROTO'] + xss = {} + for name in modules: + mod = getattr(pkg, name) + xs = xstatic.main.XStatic(mod, root_url=url, protocol=proto) + xss[xs.name] = xs + return xss + + def teardown(self, exception): + pass + + @property + def xss(self): + ctx = stack.top + if ctx is not None: + if not hasattr(ctx, 'xss'): + ctx.xss = self._load() + return ctx.xss + + def url_for(self, module, path): + return self.xss[module].url_for(path) + + def serve(self, module, path): + return send_file(os.path.join(self.xss[module].base_dir, path)) + + def serve_or_404(self, module, path): + try: + return self.serve(module, path) + except FileNotFoundError: + abort(404) diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..5d08e9c --- /dev/null +++ b/setup.cfg @@ -0,0 +1,3 @@ +[flake8] +# E501: ignore line length +ignore=E501 diff --git a/setup.py b/setup.py new file mode 100755 index 0000000..d6f699e --- /dev/null +++ b/setup.py @@ -0,0 +1,42 @@ +#!/usr/bin/python3 +# vim: set fileencoding=utf-8 : +""" +Flask-XStatic +------------- + +Make using xstatic files simple +""" +from setuptools import setup + + +def readme(): + with open('README.rst') as file: + return file.read() + + +setup( + name='Flask-XStatic', + version='0.0.1', + url='http://github.com/agx/flask-xstatic', + license='LGPLv3+', + author='Guio Günther', + author_email='agx@sigxcpu.org', + description='Easily use XStatic files in flask', + long_description=readme(), + py_modules=['flask_xstatic'], + zip_safe=False, + include_package_data=True, + platforms='any', + install_requires=[ + 'Flask' + ], + classifiers=[ + 'Environment :: Web Environment', + 'Intended Audience :: Developers', + 'License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+)', + 'Operating System :: OS Independent', + 'Programming Language :: Python', + 'Topic :: Internet :: WWW/HTTP :: Dynamic Content', + 'Topic :: Software Development :: Libraries :: Python Modules' + ] +) |