Flask-Assets-0.12/0000755000076500000240000000000012755403770014473 5ustar michaelstaff00000000000000Flask-Assets-0.12/CHANGES0000644000076500000240000000566612755403734015503 0ustar michaelstaff000000000000000.12 (2016-07-13) - Added registration of Flask CLI commands using `flask.commands` entrypoint group. (Jiri Kuncar) - Added an optional support for FlaskAzureStorage when `FLASK_ASSETS_USE_AZURE` is set. (Alejo Arias) - Updated Flask extension imports for compatibility with Flask 0.11. (Andy Driver) (fixes #102) - Fixed generation of absolute urls using //. (fixes #73) - Fixed Flask-Script assets build command. (Frank Tackitt) 0.11 (2015-08-21) - Match webassets 0.11. - Option to use Flask-CDN (James Elkins). 0.10 (2014-07-03) This release is compatible with webassets 0.10. 0.9 (2014-02-20) This release is compatible with webassets 0.9. flask-assets now support Python 3, and drops support for Python 2.5. - Support for Flask-S3 (Erik Taubeneck). - Support latest Flask-Script (Chris Hacken). 0.8 (2012-11-23) This release is compatible with webassets 0.8. - Flask-Script's ``build`` command now has ``--parse-templates`` option. - ``Environment`` class now has ``from_yaml`` and ``from_module`` shortcuts (Sean Lynch). - Jinja2 filter uses the Flask template environment. - Fixed PySscss filter. 0.7 (2012-04-11) This release is compatible with webassets 0.7. - Now officially requires at least Flask 0.8, so it can use the new extension import system, but using the compatibility module, older Flask versions should work fine as well: http://flask.pocoo.org/docs/extensions/ - Support Python 2.5. - Allow customizing the backend of ``ManageAssets`` command. - Due to webassets 0.7, the cssrewrite filter now works with Blueprints. 0.6.2 (2011-10-12) - Fixed Blueprint/Module resolving in output path. 0.6.1 (2011-10-10) - Building in 0.6 was very much broken (thanks Oliver Tonnhofer). - A custom "static_folder" for a Flask app or Blueprint/Module is now supported. 0.6 (2011-10-03) - Support webassets 0.6. - Fixed use of wrong Flask app in some cases. - Fixed init_app() usage (Oliver Tonnhofer) - Python 2.5 compatibility (Ron DuPlain) 0.5.1 (2011-08-12) - New version numbering scheme. The major and minor version numbers will now follow along with the version of webassets the Flask-Assets release was written against, and is guaranteed to be compatible with. - Support for Blueprints (Flask 0.7). - Fixed usage for incorrect request context during URL generation (thank you, julen). 0.2.2 (2011-05-27) - Really fix the ManageAssets command. 0.2.1 (2011-04-28) - Fixed the ManageAssets command to work with the current Flask-Script version. 0.2 (2011-03-30) - Support for init_app() protocol, multiple applications. - Integrate with Flask-Script, provide management command. - Properly support Flask modules, with the ability to reference the module's static files in bundles (Olivier Poitrey). 0.1 (2010-09-24) Initial release. Flask-Assets-0.12/docs/0000755000076500000240000000000012755403770015423 5ustar michaelstaff00000000000000Flask-Assets-0.12/docs/.gitignore0000644000076500000240000000001012301437525017372 0ustar michaelstaff00000000000000/_build/Flask-Assets-0.12/docs/conf.py0000644000076500000240000001552412755403734016731 0ustar michaelstaff00000000000000# -*- coding: utf-8 -*- # # Flask-Assets documentation build configuration file, created by # sphinx-quickstart on Fri Aug 6 14:01:08 2010. # # This file is execfile()d with the current directory set to its containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. import sys, os # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. #sys.path.append(os.path.abspath('.')) sys.path.append(os.path.abspath('_themes')) # make sure we are documenting the local version with autodoc sys.path.insert(0, os.path.abspath('../src')) import flask_assets as flaskassets # -- General configuration ----------------------------------------------------- # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = [ 'sphinx.ext.autodoc', 'sphinx.ext.coverage', 'sphinx.ext.doctest', 'sphinx.ext.intersphinx', 'sphinx.ext.viewcode', ] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. #source_encoding = 'utf-8' # The master toctree document. master_doc = 'index' # General information about the project. project = u'Flask-Assets' copyright = u'2010, Michael Elsdörfer' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. version = ".".join(map(str, flaskassets.__version__)) # The full version, including alpha/beta/rc tags. release = version # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. #language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. #today_fmt = '%B %d, %Y' # List of documents that shouldn't be included in the build. #unused_docs = [] # List of directories, relative to source directory, that shouldn't be searched # for source files. exclude_trees = ['_build'] # The reST default role (used for this markup: `text`) to use for all documents. #default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. #add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). #add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. #show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. #modindex_common_prefix = [] # -- Options for HTML output --------------------------------------------------- # The theme to use for HTML and HTML Help pages. Major themes that come with # Sphinx are currently 'default' and 'sphinxdoc'. html_theme = 'flask_small' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. html_theme_options = {'github_fork': 'miracle2k/flask-assets', 'index_logo': False} # Add any paths that contain custom themes here, relative to this directory. html_theme_path = ['_themes'] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". #html_title = None # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. #html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. #html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. #html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. #html_use_smartypants = True # Custom sidebar templates, maps document names to template names. #html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. #html_additional_pages = {} # If false, no module index is generated. #html_use_modindex = True # If false, no index is generated. #html_use_index = True # If true, the index is split into individual pages for each letter. #html_split_index = False # If true, links to the reST sources are added to the pages. #html_show_sourcelink = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. #html_use_opensearch = '' # If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). #html_file_suffix = '' # Output file base name for HTML help builder. htmlhelp_basename = 'Flask-Assetsdoc' # -- Options for LaTeX output -------------------------------------------------- # The paper size ('letter' or 'a4'). #latex_paper_size = 'letter' # The font size ('10pt', '11pt' or '12pt'). #latex_font_size = '10pt' # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ ('index', 'Flask-Assets.tex', u'Flask-Assets Documentation', u'Michael Elsdörfer', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. #latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. #latex_use_parts = False # Additional stuff for the LaTeX preamble. #latex_preamble = '' # Documents to append as an appendix to all manuals. #latex_appendices = [] # If false, no module index is generated. #latex_use_modindex = True # Example configuration for intersphinx: refer to the Python standard library. intersphinx_mapping = { 'python': ('https://docs.python.org/', None), 'webassets': ('https://webassets.readthedocs.io/en/latest/', None), } Flask-Assets-0.12/docs/index.rst0000644000076500000240000001736212755403734017275 0ustar michaelstaff00000000000000Flask-Assets ============ .. currentmodule:: flask_assets Flask-Assets helps you to integrate `webassets`_ into your `Flask`_ application. .. _webassets: http://github.com/miracle2k/webassets .. _Flask: http://flask.pocoo.org/ Installation ------------ Install the extension with one of the following commands:: $ easy_install Flask-Assets or alternatively if you have pip installed:: $ pip install Flask-Assets Usage ----- You initialize the app by creating an :class:`Environment` instance, and registering your assets with it in the form of so called *bundles*. .. code-block:: python from flask import Flask from flask_assets import Environment, Bundle app = Flask(__name__) assets = Environment(app) js = Bundle('jquery.js', 'base.js', 'widgets.js', filters='jsmin', output='gen/packed.js') assets.register('js_all', js) A bundle consists of any number of source files (it may also contain other nested bundles), an output target, and a list of filters to apply. All paths are relative to your app's **static** directory, or the static directory of a :ref:`Flask blueprint `. If you prefer you can of course just as well define your assets in an external config file, and read them from there. ``webassets`` includes a number of :ref:`helper classes ` for some popular formats like YAML. Like is common for a Flask extension, a Flask-Asssets instance may be used with multiple applications by initializing through ``init_app`` calls, rather than passing a fixed application object: .. code-block:: python app = Flask(__name__) assets = flask_assets.Environment() assets.init_app(app) Using the bundles ~~~~~~~~~~~~~~~~~ Now with your assets properly defined, you want to merge and minify them, and include a link to the compressed result in your web page: .. code-block:: jinja {% assets "js_all" %} {% endassets %} That's it, really. **Flask-Assets** will automatically merge and compress your bundle's source files the first time the template is rendered, and will automatically update the compressed file everytime a source file changes. If you set ``ASSETS_DEBUG`` in your app configuration to ``True``, then each source file will be outputted individually instead. .. _blueprints: Flask blueprints ~~~~~~~~~~~~~~~~ If you are using Flask blueprints, you can refer to a blueprint's static files via a prefix, in the same way as Flask allows you to reference a blueprint's templates: .. code-block:: python js = Bundle('app_level.js', 'blueprint/blueprint_level.js') In the example above, the bundle would reference two files, ``{APP_ROOT}/static/app_level.js``, and ``{BLUEPRINT_ROOT}/static/blueprint_level.js``. If you have used the ``webassets`` library standalone before, you may be familiar with the requirement to set the ``directory`` and ``url`` configuration values. You will note that this is not required here, as Flask's static folder support is used instead. However, note that you *can* set a custom root directory or url if you prefer, for some reason. However, in this case the blueprint support of Flask-Assets is disabled, that is, referencing static files in different blueprints using a prefix, as described above, is no longer possible. All paths will be considered relative to the directory and url you specified. Pre 0.7 modules are also supported; they work exactly the same way. Templates only ~~~~~~~~~~~~~~ If you prefer, you can also do without defining your bundles in code, and simply define everything inside your template: .. code-block:: jinja {% assets filters="jsmin", output="gen/packed.js", "common/jquery.js", "site/base.js", "site/widgets.js" %} {% endassets %} .. _configuration: Configuration ------------- ``webassets`` supports a couple of configuration options. Those can be set both through the :class:`Environment` instance, as well as the Flask configuration. The following two statements are equivalent: .. code-block:: python assets_env.debug = True app.config['ASSETS_DEBUG'] = True For a list of available settings, see the full :ref:`webassets documentation `. Babel Configuration ~~~~~~~~~~~~~~~~~~~ If you use `Babel`_ for internationalization, then you will need to add the extension to your babel configuration file as ``webassets.ext.jinja2.AssetsExtension`` Otherwise, babel will not extract strings from any templates that include an ``assets`` tag. Here is an example ``babel.cfg``: .. code-block:: python [python: **.py] [jinja2: **.html] extensions=jinja2.ext.autoescape,jinja2.ext.with_,webassets.ext.jinja2.AssetsExtension .. _Babel: http://babel.edgewall.org/ Flask-S3 Configuration ~~~~~~~~~~~~~~~~~~~~~~~ `Flask-S3`_ allows you to upload and serve your static files from an Amazon S3 bucket. It accomplishes this by overwriting the Flask ``url_for`` function. In order for Flask-Assets to use this overwritten ``url_for`` function, you need to let it know that you are using Flask-S3. Just set .. code-block:: python app.config['FLASK_ASSETS_USE_S3']=True .. _Flask-S3: https://flask-s3.readthedocs.io/en/latest/ Flask-CDN Configuration ~~~~~~~~~~~~~~~~~~~~~~~ `Flask-CDN`_ allows you to upload and serve your static files from a CDN (like `Amazon Cloudfront`_), without having to modify your templates. It accomplishes this by overwriting the Flask ``url_for`` function. In order for Flask-Assets to use this overwritten ``url_for`` function, you need to let it know that you are using Flask-CDN. Just set .. code-block:: python app.config['FLASK_ASSETS_USE_CDN']=True .. _Flask-CDN: https://flask-cdn.readthedocs.io/en/latest/ .. _Amazon Cloudfront: https://aws.amazon.com/cloudfront/ Command Line Interface ---------------------- *New in version 0.12.* Flask 0.11+ comes with build-in integration of `CLI`_ using `click`_ library. The ``assets`` command is automatically installed through *setuptools* using ``flask.commands`` entry point group in **setup.py**. .. code-block:: python entry_points={ 'flask.commands': [ 'assets = flask_assets:assets', ], }, After installing Flask 0.11+ you should see following line in the output when executing ``flask`` command in your shell: .. code-block:: console $ flask --help ... Commands: assets Web assets commands. ... .. _CLI: https://flask.pocoo.org/docs/0.11/cli/ .. _click: https://click.pocoo.org/docs/latest/ Legacy support ~~~~~~~~~~~~~~ If you have `Flask-Script`_ installed, then a command will be available as ``flask_assets.ManageAssets``: .. code-block:: python from flask_assets import ManageAssets manager = Manager(app) manager.add_command("assets", ManageAssets(assets_env)) You can explicitly pass the ``assets_env`` when adding the command as above. Alternatively, ``ManageAssets`` will import the ``current_app`` from Flask and use the ``jinja_env``. The command allows you to do things like rebuilding bundles from the command line. See the list of :ref:`available subcommands `. .. _Flask-Script: http://pypi.python.org/pypi/Flask-Script API --- .. automodule:: flask_assets :members: Webassets documentation ----------------------- For further information, have a look at the complete :ref:`webassets documentation `, and in particular, the following topics: - :ref:`Configuration ` - :ref:`All about bundles ` - :ref:`Builtin filters ` - :ref:`Custom filters ` - :ref:`CSS compilers ` - :ref:`FAQ ` Flask-Assets-0.12/docs/make.bat0000644000076500000240000000601312301437525017020 0ustar michaelstaff00000000000000@ECHO OFF REM Command file for Sphinx documentation set SPHINXBUILD=sphinx-build set BUILDDIR=_build set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . if NOT "%PAPER%" == "" ( set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% ) if "%1" == "" goto help if "%1" == "help" ( :help echo.Please use `make ^` where ^ is one of echo. html to make standalone HTML files echo. dirhtml to make HTML files named index.html in directories echo. pickle to make pickle files echo. json to make JSON files echo. htmlhelp to make HTML files and a HTML help project echo. qthelp to make HTML files and a qthelp project echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter echo. changes to make an overview over all changed/added/deprecated items echo. linkcheck to check all external links for integrity echo. doctest to run all doctests embedded in the documentation if enabled goto end ) if "%1" == "clean" ( for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i del /q /s %BUILDDIR%\* goto end ) if "%1" == "html" ( %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html echo. echo.Build finished. The HTML pages are in %BUILDDIR%/html. goto end ) if "%1" == "dirhtml" ( %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml echo. echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. goto end ) if "%1" == "pickle" ( %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle echo. echo.Build finished; now you can process the pickle files. goto end ) if "%1" == "json" ( %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json echo. echo.Build finished; now you can process the JSON files. goto end ) if "%1" == "htmlhelp" ( %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp echo. echo.Build finished; now you can run HTML Help Workshop with the ^ .hhp project file in %BUILDDIR%/htmlhelp. goto end ) if "%1" == "qthelp" ( %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp echo. echo.Build finished; now you can run "qcollectiongenerator" with the ^ .qhcp project file in %BUILDDIR%/qthelp, like this: echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Flask-Assets.qhcp echo.To view the help file: echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Flask-Assets.ghc goto end ) if "%1" == "latex" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex echo. echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. goto end ) if "%1" == "changes" ( %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes echo. echo.The overview file is in %BUILDDIR%/changes. goto end ) if "%1" == "linkcheck" ( %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck echo. echo.Link check complete; look for any errors in the above output ^ or in %BUILDDIR%/linkcheck/output.txt. goto end ) if "%1" == "doctest" ( %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest echo. echo.Testing of doctests in the sources finished, look at the ^ results in %BUILDDIR%/doctest/output.txt. goto end ) :end Flask-Assets-0.12/docs/Makefile0000644000076500000240000000610212301437525017052 0ustar michaelstaff00000000000000# Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . .PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " dirhtml to make HTML files named index.html in directories" @echo " pickle to make pickle files" @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " qthelp to make HTML files and a qthelp project" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " changes to make an overview of all changed/added/deprecated items" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" clean: -rm -rf $(BUILDDIR)/* html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILDDIR)/htmlhelp." qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Flask-Assets.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Flask-Assets.qhc" latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ "run these through (pdf)latex." changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILDDIR)/doctest/output.txt." Flask-Assets-0.12/example/0000755000076500000240000000000012755403770016126 5ustar michaelstaff00000000000000Flask-Assets-0.12/example/.gitignore0000644000076500000240000000002212301437525020100 0ustar michaelstaff00000000000000/static/cached.cssFlask-Assets-0.12/example/app.py0000755000076500000240000000073712724075227017270 0ustar michaelstaff00000000000000#!/usr/bin/env python import sys from os import path sys.path.insert(0, path.join(path.dirname(__file__), '../src')) from flask import Flask, render_template, url_for from flask_assets import Environment, Bundle app = Flask(__name__) assets = Environment(app) assets.register('main', 'style1.css', 'style2.css', output='cached.css', filters='cssmin') @app.route('/') def index(): return render_template('index.html') app.run(debug=True) Flask-Assets-0.12/example/static/0000755000076500000240000000000012755403770017415 5ustar michaelstaff00000000000000Flask-Assets-0.12/example/static/style1.css0000644000076500000240000000002612301437525021336 0ustar michaelstaff00000000000000h1 { color: red; }Flask-Assets-0.12/example/static/style2.css0000644000076500000240000000002712301437525021340 0ustar michaelstaff00000000000000h2 { color: blue; }Flask-Assets-0.12/example/templates/0000755000076500000240000000000012755403770020124 5ustar michaelstaff00000000000000Flask-Assets-0.12/example/templates/index.html0000644000076500000240000000030312301437525022105 0ustar michaelstaff00000000000000 {% assets "main" %} {% endassets %}

This should be red.

This should be blue.

Flask-Assets-0.12/fabfile.py0000644000076500000240000000040212301437525016421 0ustar michaelstaff00000000000000from fabric.api import run, put, env env.hosts = ['elsdoerfer.com:2211'] def publish_docs(): target = '/var/www/elsdoerfer/files/docs/flask-assets' run('rm -rf %s' % target) run('mkdir %s' % target) put('build/sphinx/html/*', '%s' % target)Flask-Assets-0.12/LICENSE0000644000076500000240000000251412301437525015472 0ustar michaelstaff00000000000000Copyright (c) 2010, Michael Elsdörfer All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.Flask-Assets-0.12/MANIFEST.in0000644000076500000240000000034112301437525016217 0ustar michaelstaff00000000000000include LICENSE CHANGES README.rst *.py recursive-include docs * prune docs/_build prune docs/_themes/.git recursive-include tests * recursive-exclude tests *.pyc recursive-include example * recursive-exclude example *.pycFlask-Assets-0.12/PKG-INFO0000644000076500000240000000167712755403770015603 0ustar michaelstaff00000000000000Metadata-Version: 1.1 Name: Flask-Assets Version: 0.12 Summary: Asset management for Flask, to compress and merge CSS and Javascript files. Home-page: http://github.com/miracle2k/flask-assets Author: Michael Elsdoerfer Author-email: michael@elsdoerfer.com License: BSD Description: Flask-Assets ------------- Integrates the ``webassets`` library with Flask, adding support for merging, minifying and compiling CSS and Javascript files. Platform: any Classifier: Environment :: Web Environment Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: BSD License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 3 Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content Classifier: Topic :: Software Development :: Libraries :: Python Modules Flask-Assets-0.12/README.rst0000644000076500000240000000035512731460236016157 0ustar michaelstaff00000000000000Integrates the `webassets`_ library with Flask, adding support for merging, minifying and compiling CSS and Javascript files. Documentation: https://flask-assets.readthedocs.io/ .. _webassets: http://github.com/miracle2k/webassets Flask-Assets-0.12/setup.cfg0000644000076500000240000000007312755403770016314 0ustar michaelstaff00000000000000[egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 Flask-Assets-0.12/setup.py0000755000076500000240000000437012731461474016213 0ustar michaelstaff00000000000000#!/usr/bin/env python # coding: utf8 """ Flask-Assets ------------- Integrates the ``webassets`` library with Flask, adding support for merging, minifying and compiling CSS and Javascript files. """ from __future__ import with_statement from setuptools import setup # Figure out the version; this could be done by importing the # module, though that requires dependencies to be already installed, # which may not be the case when processing a pip requirements # file, for example. def parse_version(asignee): import os, re here = os.path.dirname(os.path.abspath(__file__)) version_re = re.compile( r'%s = (\(.*?\))' % asignee) with open(os.path.join(here, 'src', 'flask_assets.py')) as fp: for line in fp: match = version_re.search(line) if match: version = eval(match.group(1)) return ".".join(map(str, version)) else: raise Exception("cannot find version") version = parse_version('__version__') webassets_requirement = parse_version('__webassets_version__') setup( name='Flask-Assets', version=version, url='http://github.com/miracle2k/flask-assets', license='BSD', author='Michael Elsdoerfer', author_email='michael@elsdoerfer.com', description='Asset management for Flask, to compress and merge ' \ 'CSS and Javascript files.', long_description=__doc__, py_modules=['flask_assets'], package_dir={'': 'src'}, zip_safe=False, platforms='any', entry_points={ 'flask.commands': [ 'assets = flask_assets:assets', ], }, install_requires=[ 'Flask>=0.8', 'webassets%s' % webassets_requirement, ], classifiers=[ 'Environment :: Web Environment', 'Intended Audience :: Developers', 'License :: OSI Approved :: BSD License', 'Operating System :: OS Independent', 'Programming Language :: Python', 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 3', 'Topic :: Internet :: WWW/HTTP :: Dynamic Content', 'Topic :: Software Development :: Libraries :: Python Modules' ], test_suite='nose.collector', tests_require=[ 'nose', 'flask-script' ], ) Flask-Assets-0.12/src/0000755000076500000240000000000012755403770015262 5ustar michaelstaff00000000000000Flask-Assets-0.12/src/Flask_Assets.egg-info/0000755000076500000240000000000012755403770021336 5ustar michaelstaff00000000000000Flask-Assets-0.12/src/Flask_Assets.egg-info/dependency_links.txt0000644000076500000240000000000112755403766025411 0ustar michaelstaff00000000000000 Flask-Assets-0.12/src/Flask_Assets.egg-info/entry_points.txt0000644000076500000240000000005712755403766024643 0ustar michaelstaff00000000000000[flask.commands] assets = flask_assets:assets Flask-Assets-0.12/src/Flask_Assets.egg-info/not-zip-safe0000644000076500000240000000000112301465036023552 0ustar michaelstaff00000000000000 Flask-Assets-0.12/src/Flask_Assets.egg-info/PKG-INFO0000644000076500000240000000167712755403766022453 0ustar michaelstaff00000000000000Metadata-Version: 1.1 Name: Flask-Assets Version: 0.12 Summary: Asset management for Flask, to compress and merge CSS and Javascript files. Home-page: http://github.com/miracle2k/flask-assets Author: Michael Elsdoerfer Author-email: michael@elsdoerfer.com License: BSD Description: Flask-Assets ------------- Integrates the ``webassets`` library with Flask, adding support for merging, minifying and compiling CSS and Javascript files. Platform: any Classifier: Environment :: Web Environment Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: BSD License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 3 Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content Classifier: Topic :: Software Development :: Libraries :: Python Modules Flask-Assets-0.12/src/Flask_Assets.egg-info/requires.txt0000644000076500000240000000003512755403766023741 0ustar michaelstaff00000000000000Flask>=0.8 webassets>=0.11.1 Flask-Assets-0.12/src/Flask_Assets.egg-info/SOURCES.txt0000644000076500000240000000155012755403767023231 0ustar michaelstaff00000000000000CHANGES LICENSE MANIFEST.in README.rst fabfile.py setup.py docs/.gitignore docs/Makefile docs/conf.py docs/index.rst docs/make.bat example/.gitignore example/app.py example/static/style1.css example/static/style2.css example/templates/index.html src/flask_assets.py src/Flask_Assets.egg-info/PKG-INFO src/Flask_Assets.egg-info/SOURCES.txt src/Flask_Assets.egg-info/dependency_links.txt src/Flask_Assets.egg-info/entry_points.txt src/Flask_Assets.egg-info/not-zip-safe src/Flask_Assets.egg-info/requires.txt src/Flask_Assets.egg-info/top_level.txt tests/__init__.py tests/helpers.py tests/test_config.py tests/test_env.py tests/test_integration.py tests/test_script.py tests/static/out tests/static/.webassets-cache/60626d2ed874f082bb6a19c376f3c697 tests/static/.webassets-cache/d30b611478d1f50daf7548f28bac732b tests/test_module/__init__.py tests/test_module/static/READMEFlask-Assets-0.12/src/Flask_Assets.egg-info/top_level.txt0000644000076500000240000000001512755403766024071 0ustar michaelstaff00000000000000flask_assets Flask-Assets-0.12/src/flask_assets.py0000644000076500000240000004504112755403734020322 0ustar michaelstaff00000000000000"""Integration of the ``webassets`` library with Flask.""" from __future__ import print_function import logging from os import path from flask import _request_ctx_stack, current_app from flask.templating import render_template_string # We want to expose Bundle via this module. from webassets import Bundle from webassets.env import (BaseEnvironment, ConfigStorage, Resolver, env_options, url_prefix_join) from webassets.filter import Filter, register_filter from webassets.loaders import PythonLoader, YAMLLoader __version__ = (0, 12) # webassets core compatibility used in setup.py __webassets_version__ = ('>=0.11.1', ) __all__ = ( 'Environment', 'Bundle', 'FlaskConfigStorage', 'FlaskResolver', 'Jinja2Filter', ) class Jinja2Filter(Filter): """Will compile all source files as Jinja2 templates using the standard Flask contexts. """ name = 'jinja2' max_debug_level = None def __init__(self, context=None): super(Jinja2Filter, self).__init__() self.context = context or {} def input(self, _in, out, source_path, output_path, **kw): out.write(render_template_string(_in.read(), **self.context)) # Override the built-in ``jinja2`` filter that ships with ``webassets``. This # custom filter uses Flask's ``render_template_string`` function to provide all # the standard Flask template context variables. register_filter(Jinja2Filter) class FlaskConfigStorage(ConfigStorage): """Uses the config object of a Flask app as the backend: either the app instance bound to the extension directly, or the current Flask app on the stack. Also provides per-application defaults for some values. Note that if no app is available, this config object is basically unusable - this is by design; this could also let the user set defaults by writing to a container not related to any app, which would be used as a fallback if a current app does not include a key. However, at least for now, I specifically made the choice to keep things simple and not allow global across-app defaults. """ def __init__(self, *a, **kw): self._defaults = {} ConfigStorage.__init__(self, *a, **kw) def _transform_key(self, key): if key.lower() in env_options: return "ASSETS_%s" % key.upper() else: return key.upper() def setdefault(self, key, value): """We may not always be connected to an app, but we still need to provide a way to the base environment to set it's defaults. """ try: super(FlaskConfigStorage, self).setdefault(key, value) except RuntimeError: self._defaults.__setitem__(key, value) def __contains__(self, key): return self._transform_key(key) in self.env._app.config def __getitem__(self, key): value = self._get_deprecated(key) if value: return value # First try the current app's config public_key = self._transform_key(key) if self.env._app: if public_key in self.env._app.config: return self.env._app.config[public_key] # Try a non-app specific default value if key in self._defaults: return self._defaults.__getitem__(key) # Finally try to use a default based on the current app deffunc = getattr(self, "_app_default_%s" % key, False) if deffunc: return deffunc() # We've run out of options raise KeyError() def __setitem__(self, key, value): if not self._set_deprecated(key, value): self.env._app.config[self._transform_key(key)] = value def __delitem__(self, key): del self.env._app.config[self._transform_key(key)] def get_static_folder(app_or_blueprint): """Return the static folder of the given Flask app instance, or module/blueprint. In newer Flask versions this can be customized, in older ones (<=0.6) the folder is fixed. """ if not hasattr(app_or_blueprint, 'static_folder'): # I believe this is for app objects in very old Flask # versions that did not support custom static folders. return path.join(app_or_blueprint.root_path, 'static') if not app_or_blueprint.has_static_folder: # Use an exception type here that is not hidden by spit_prefix. raise TypeError(('The referenced blueprint %s has no static ' 'folder.') % app_or_blueprint) return app_or_blueprint.static_folder class FlaskResolver(Resolver): """Adds support for Flask blueprints. This resolver is designed to use the Flask staticfile system to locate files, by looking at directory prefixes (``foo/bar.png`` looks in the static folder of the ``foo`` blueprint. ``url_for`` is used to generate urls to these files. This default behaviour changes when you start setting certain standard *webassets* path and url configuration values: If a :attr:`Environment.directory` is set, output files will always be written there, while source files still use the Flask system. If a :attr:`Environment.load_path` is set, it is used to look up source files, replacing the Flask system. Blueprint prefixes are no longer resolved. """ def split_prefix(self, ctx, item): """See if ``item`` has blueprint prefix, return (directory, rel_path). """ app = ctx._app try: if hasattr(app, 'blueprints'): blueprint, name = item.split('/', 1) directory = get_static_folder(app.blueprints[blueprint]) endpoint = '%s.static' % blueprint item = name else: # Module support for Flask < 0.7 module, name = item.split('/', 1) directory = get_static_folder(app.modules[module]) endpoint = '%s.static' % module item = name except (ValueError, KeyError): directory = get_static_folder(app) endpoint = 'static' return directory, item, endpoint def use_webassets_system_for_output(self, ctx): return ctx.config.get('directory') is not None or \ ctx.config.get('url') is not None def use_webassets_system_for_sources(self, ctx): return bool(ctx.load_path) def search_for_source(self, ctx, item): # If a load_path is set, use it instead of the Flask static system. # # Note: With only env.directory set, we don't go to default; # Setting env.directory only makes the output directory fixed. if self.use_webassets_system_for_sources(ctx): return Resolver.search_for_source(self, ctx, item) # Look in correct blueprint's directory directory, item, endpoint = self.split_prefix(ctx, item) try: return self.consider_single_directory(directory, item) except IOError: # XXX: Hack to make the tests pass, which are written to not # expect an IOError upon missing files. They need to be rewritten. return path.normpath(path.join(directory, item)) def resolve_output_to_path(self, ctx, target, bundle): # If a directory/url pair is set, always use it for output files if self.use_webassets_system_for_output(ctx): return Resolver.resolve_output_to_path(self, ctx, target, bundle) # Allow targeting blueprint static folders directory, rel_path, endpoint = self.split_prefix(ctx, target) return path.normpath(path.join(directory, rel_path)) def resolve_source_to_url(self, ctx, filepath, item): # If a load path is set, use it instead of the Flask static system. if self.use_webassets_system_for_sources(ctx): return super(FlaskResolver, self).resolve_source_to_url(ctx, filepath, item) return self.convert_item_to_flask_url(ctx, item, filepath) def resolve_output_to_url(self, ctx, target): # With a directory/url pair set, use it for output files. if self.use_webassets_system_for_output(ctx): return Resolver.resolve_output_to_url(self, ctx, target) # Otherwise, behaves like all other flask URLs. return self.convert_item_to_flask_url(ctx, target) def convert_item_to_flask_url(self, ctx, item, filepath=None): """Given a relative reference like `foo/bar.css`, returns the Flask static url. By doing so it takes into account blueprints, i.e. in the aformentioned example, ``foo`` may reference a blueprint. If an absolute path is given via ``filepath``, it will be used instead. This is needed because ``item`` may be a glob instruction that was resolved to multiple files. If app.config("FLASK_ASSETS_USE_S3") exists and is True then we import the url_for function from flask_s3, otherwise we import url_for from flask directly. If app.config("FLASK_ASSETS_USE_CDN") exists and is True then we import the url_for function from flask. """ if ctx.environment._app.config.get("FLASK_ASSETS_USE_S3"): try: from flask_s3 import url_for except ImportError as e: print("You must have Flask S3 to use FLASK_ASSETS_USE_S3 option") raise e elif ctx.environment._app.config.get("FLASK_ASSETS_USE_CDN"): try: from flask_cdn import url_for except ImportError as e: print("You must have Flask CDN to use FLASK_ASSETS_USE_CDN option") raise e elif ctx.environment._app.config.get("FLASK_ASSETS_USE_AZURE"): try: from flask_azure_storage import url_for except ImportError as e: print("You must have Flask Azure Storage to use FLASK_ASSETS_USE_AZURE option") raise e else: from flask import url_for directory, rel_path, endpoint = self.split_prefix(ctx, item) if filepath is not None: filename = filepath[len(directory)+1:] else: filename = rel_path flask_ctx = None if not _request_ctx_stack.top: flask_ctx = ctx.environment._app.test_request_context() flask_ctx.push() try: url = url_for(endpoint, filename=filename) # In some cases, url will be an absolute url with a scheme and hostname. # (for example, when using werkzeug's host matching). # In general, url_for() will return a http url. During assets build, we # we don't know yet if the assets will be served over http, https or both. # Let's use // instead. url_for takes a _scheme argument, but only together # with external=True, which we do not want to force every time. Further, # this _scheme argument is not able to render // - it always forces a colon. if url and url.startswith('http:'): url = url[5:] return url finally: if flask_ctx: flask_ctx.pop() class Environment(BaseEnvironment): """This object is used to hold a collection of bundles and configuration. If it initialized with an instance of Flask application then webassets Jinja2 extension is automatically registered. """ config_storage_class = FlaskConfigStorage resolver_class = FlaskResolver def __init__(self, app=None): self.app = app super(Environment, self).__init__() if app: self.init_app(app) @property def _app(self): """The application object to work with; this is either the app that we have been bound to, or the current application. """ if self.app is not None: return self.app ctx = _request_ctx_stack.top if ctx is not None: return ctx.app try: from flask import _app_ctx_stack app_ctx = _app_ctx_stack.top if app_ctx is not None: return app_ctx.app except ImportError: pass raise RuntimeError('assets instance not bound to an application, '+ 'and no application in current context') # XXX: This is required because in a couple of places, webassets 0.6 # still access env.directory, at one point even directly. We need to # fix this for 0.6 compatibility, but it might be preferrable to # introduce another API similar to _normalize_source_path() for things # like the cache directory and output files. def set_directory(self, directory): self.config['directory'] = directory def get_directory(self): if self.config.get('directory') is not None: return self.config['directory'] return get_static_folder(self._app) directory = property(get_directory, set_directory, doc= """The base directory to which all paths will be relative to. """) def set_url(self, url): self.config['url'] = url def get_url(self): if self.config.get('url') is not None: return self.config['url'] return self._app.static_url_path url = property(get_url, set_url, doc= """The base url to which all static urls will be relative to.""") def init_app(self, app): app.jinja_env.add_extension('webassets.ext.jinja2.AssetsExtension') app.jinja_env.assets_environment = self def from_yaml(self, path): """Register bundles from a YAML configuration file""" bundles = YAMLLoader(path).load_bundles() for name in bundles: self.register(name, bundles[name]) def from_module(self, path): """Register bundles from a Python module""" bundles = PythonLoader(path).load_bundles() for name in bundles: self.register(name, bundles[name]) try: import flask_script as script except ImportError: pass else: import argparse from webassets.script import GenericArgparseImplementation, CommandError class FlaskArgparseInterface(GenericArgparseImplementation): """Subclass the CLI implementation to add a --parse-templates option.""" def _construct_parser(self, *a, **kw): super(FlaskArgparseInterface, self).\ _construct_parser(*a, **kw) self.parser.add_argument( '--jinja-extension', default='*.html', help='specify the glob pattern for Jinja extensions (default: *.html)') self.parser.add_argument( '--parse-templates', action='store_true', help='search project templates to find bundles') def _setup_assets_env(self, ns, log): env = super(FlaskArgparseInterface, self)._setup_assets_env(ns, log) if env is not None: if ns.parse_templates: log.info('Searching templates...') # Note that we exclude container bundles. By their very nature, # they are guaranteed to have been created by solely referencing # other bundles which are already registered. env.add(*[b for b in self.load_from_templates(env, ns.jinja_extension) if not b.is_container]) if not len(env): raise CommandError( 'No asset bundles were found. ' 'If you are defining assets directly within ' 'your templates, you want to use the ' '--parse-templates option.') return env def load_from_templates(self, env, jinja_extension): from webassets.ext.jinja2 import Jinja2Loader, AssetsExtension from flask import current_app as app # Use the application's Jinja environment to parse jinja2_env = app.jinja_env # Get the template directories of app and blueprints template_dirs = [path.join(app.root_path, app.template_folder)] for blueprint in app.blueprints.values(): if blueprint.template_folder is None: continue template_dirs.append( path.join(blueprint.root_path, blueprint.template_folder)) return Jinja2Loader(env, template_dirs, [jinja2_env], jinja_ext=jinja_extension).\ load_bundles() class ManageAssets(script.Command): """Manage assets.""" capture_all_args = True def __init__(self, assets_env=None, impl=FlaskArgparseInterface, log=None): self.env = assets_env self.implementation = impl self.log = log def run(self, args): """Runs the management script. If ``self.env`` is not defined, it will import it from ``current_app``. """ if not self.env: from flask import current_app self.env = current_app.jinja_env.assets_environment # Determine 'prog' - something like for example # "./manage.py assets", to be shown in the help string. # While we don't know the command name we are registered with # in Flask-Assets, we are lucky to be able to rely on the # name being in argv[1]. import sys, os.path prog = '%s %s' % (os.path.basename(sys.argv[0]), sys.argv[1]) impl = self.implementation(self.env, prog=prog, log=self.log) return impl.main(args) __all__ = __all__ + ('ManageAssets',) try: import click from flask import cli except ImportError: pass else: def _webassets_cmd(cmd): """Helper to run a webassets command.""" from webassets.script import CommandLineEnvironment logger = logging.getLogger('webassets') logger.addHandler(logging.StreamHandler()) logger.setLevel(logging.DEBUG) cmdenv = CommandLineEnvironment( current_app.jinja_env.assets_environment, logger ) getattr(cmdenv, cmd)() @click.group() def assets(): """Web assets commands.""" @assets.command() @cli.with_appcontext def build(): """Build bundles.""" _webassets_cmd('build') @assets.command() @cli.with_appcontext def clean(): """Clean bundles.""" _webassets_cmd('clean') @assets.command() @cli.with_appcontext def watch(): """Watch bundles for file changes.""" _webassets_cmd('watch') __all__ = __all__ + ('assets', 'build', 'clean', 'watch') Flask-Assets-0.12/tests/0000755000076500000240000000000012755403770015635 5ustar michaelstaff00000000000000Flask-Assets-0.12/tests/__init__.py0000644000076500000240000000107012301437525017734 0ustar michaelstaff00000000000000import sys, os # In order to test the Flask-Script command, Flask-Script needs to be # installed. If this is the case, we won't be able to import from our # local src/flaskext directory that nose puts on sys.path, due to the # way Flask extensions employ pkg_resources to have multiple directories # contribute to the same module. We fix it by manually adding the # directory to an already existing virtual flaskext module. try: sys.modules['flaskext'].__path__.append( os.path.join(os.path.dirname(__file__), '../src/flaskext')) except KeyError: passFlask-Assets-0.12/tests/helpers.py0000644000076500000240000000212112724075227017643 0ustar michaelstaff00000000000000from flask.app import Flask from webassets.test import TempEnvironmentHelper as BaseTempEnvironmentHelper from flask_assets import Environment try: from flask import Blueprint Module = None except ImportError: # Blueprints only available starting with 0.7, # fall back to old Modules otherwise. Blueprint = None from flask import Module __all__ = ('TempEnvironmentHelper', 'Module', 'Blueprint') class TempEnvironmentHelper(BaseTempEnvironmentHelper): def _create_environment(self, **kwargs): if not hasattr(self, 'app'): self.app = Flask(__name__, static_folder=self.tempdir, **kwargs) self.env = Environment(self.app) return self.env try: from test.test_support import check_warnings except ImportError: # Python < 2.6 import contextlib @contextlib.contextmanager def check_warnings(*filters, **kwargs): # We cannot reasonably support this, we'd have to copy to much code. # (or write our own). Since this is only testing warnings output, # we might slide by ignoring it. yield Flask-Assets-0.12/tests/static/0000755000076500000240000000000012755403770017124 5ustar michaelstaff00000000000000Flask-Assets-0.12/tests/static/.webassets-cache/0000755000076500000240000000000012755403770022243 5ustar michaelstaff00000000000000Flask-Assets-0.12/tests/static/.webassets-cache/60626d2ed874f082bb6a19c376f3c6970000600000076500000240000000002012565620773026410 0ustar michaelstaff00000000000000S'd41d8cd9' p1 .Flask-Assets-0.12/tests/static/.webassets-cache/d30b611478d1f50daf7548f28bac732b0000600000076500000240000000005012565620773026526 0ustar michaelstaff00000000000000S'780b0bdcdd715bb270409c8f3d49e71a' p1 .Flask-Assets-0.12/tests/static/out0000644000076500000240000000000012565620773017647 0ustar michaelstaff00000000000000Flask-Assets-0.12/tests/test_config.py0000644000076500000240000000727412724075227020523 0ustar michaelstaff00000000000000"""The Environment configuration is hooked up to the Flask config dict. """ from __future__ import absolute_import from tests.helpers import check_warnings from nose.tools import assert_raises from flask import Flask from flask_assets import Environment from webassets.exceptions import ImminentDeprecationWarning try: from webassets.updater import BaseUpdater except ImportError: BaseUpdater = None # older webassets versions (<=0.5) if BaseUpdater: class MooUpdater(BaseUpdater): id = 'MOO' class TestConfigAppBound: """The extension is bound to a specific app. """ def setup(self): self.app = Flask(__name__) self.env = Environment(self.app) def test_set_environment(self): """Setting a config value on the environment works. """ self.env.updater = 'foo' assert self.app.config['ASSETS_UPDATER'] == 'foo' def test_set_config(self): """Setting a value in the Flask config works. """ self.app.config['ASSETS_UPDATER'] = 'MOO' assert self.env.updater == 'MOO' def test_custom_values(self): """Custom config values are relayed to the Flask config as.is. """ self.app.config['LESS_PATH'] = '/usr/bin/less' assert self.env.config['LESS_PATH'] == '/usr/bin/less' def test_no_override(self): """Ensure that the webassets defaults do not override existing Flask config values. """ app = Flask(__name__) app.config['ASSETS_UPDATER'] = 'MOO' env = Environment(app) assert env.updater == 'MOO' assert app.config['ASSETS_UPDATER'] == 'MOO' # Neither do the defaults that flask-assets set. app = Flask(__name__) app.config['ASSETS_URL'] = 'MOO' env = Environment(app) assert env.url == 'MOO' assert app.config['ASSETS_URL'] == 'MOO' class TestConfigNoAppBound: """The application is not bound to a specific app. """ def setup(self): self.env = Environment() def test_no_app_available(self): """Without an application bound, we can't do much.""" assert_raises(RuntimeError, setattr, self.env, 'debug', True) assert_raises(RuntimeError, self.env.config.get, 'debug') def test_global_defaults(self): """We may set defaults even without an application, however.""" self.env.config.setdefault('FOO', 'BAR') with Flask(__name__).test_request_context(): assert self.env.config['FOO'] == 'BAR' def test_multiple_separate_apps(self): """Each app has it's own separate configuration. """ app1 = Flask(__name__) self.env.init_app(app1) # With no app yet available... assert_raises(RuntimeError, getattr, self.env, 'url') # ...set a default self.env.config.setdefault('FOO', 'BAR') # When an app is available, the default is used with app1.test_request_context(): assert self.env.config['FOO'] == 'BAR' # If the default is overridden for this application, it # is still valid for other apps. self.env.config['FOO'] = '42' assert self.env.config['FOO'] == '42' app2 = Flask(__name__) with app2.test_request_context(): assert self.env.config['FOO'] == 'BAR' def test_key_error(self): """KeyError is raised if a config value doesn't exist. """ with Flask(__name__).test_request_context(): assert_raises(KeyError, self.env.config.__getitem__, 'YADDAYADDA') # The get() helper, on the other hand, simply returns None assert self.env.config.get('YADDAYADDA') == None Flask-Assets-0.12/tests/test_env.py0000644000076500000240000000272012724075227020035 0ustar michaelstaff00000000000000import os from nose.tools import assert_raises from flask import Flask from flask_assets import Environment, Bundle class TestEnv: def setup(self): self.app = Flask(__name__) self.env = Environment(self.app) self.env.debug = True self.env.register('test', 'file1', 'file2') def test_tag_available(self): """Jinja tag has been made available. """ t = self.app.jinja_env.from_string('{% assets "test" %}{{ASSET_URL}};{% endassets %}') assert t.render() == '/static/file1;/static/file2;' def test_from_yaml(self): """YAML configuration gets loaded """ f = open('test.yaml', 'w') f.write(""" yamltest: contents: - yamlfile1 - yamlfile2 """) f.close() self.env.from_yaml('test.yaml') t = self.app.jinja_env.from_string('{% assets "yamltest" %}{{ASSET_URL}};{% endassets %}') assert t.render() == '/static/yamlfile1;/static/yamlfile2;' os.remove('test.yaml') def test_from_python_module(self): """Python configuration module gets loaded """ import types module = types.ModuleType('test') module.pytest = Bundle('pyfile1', 'pyfile2') self.env.from_module(module) t = self.app.jinja_env.from_string('{% assets "pytest" %}{{ASSET_URL}};{% endassets %}') assert t.render() == '/static/pyfile1;/static/pyfile2;' Flask-Assets-0.12/tests/test_integration.py0000644000076500000240000002456312724075227021601 0ustar michaelstaff00000000000000from __future__ import absolute_import from nose.tools import assert_raises from flask import Flask from flask_assets import Environment, Bundle from webassets.bundle import get_all_bundle_files from tests.helpers import TempEnvironmentHelper, Module, Blueprint def test_import(): # We want to expose these via the assets extension module. from flask_assets import Bundle from flask_assets import Environment class TestUrlAndDirectory(TempEnvironmentHelper): """By default, the 'url' and 'directory' settings of webassets are not used in Flask-Assets; that is, the values are automatically handled based on the configuration of the Flask app and the modules used. The user can disable the automatic handling by setting these values if he needs to for some reason. Let's test the different scenarios to ensure everything works. """ def setup(self): TempEnvironmentHelper.setup(self) self.app = Flask(__name__, static_path='/app_static') from tests import test_module if not Blueprint: self.module = Module(test_module.__name__, name='module', static_path='/mod_static') self.app.register_module(self.module) else: self.blueprint = Blueprint('module', test_module.__name__, static_url_path='/mod_static', static_folder='static') self.app.register_blueprint(self.blueprint) self.env = Environment(self.app) def test_config_values_not_set_by_default(self): assert not 'directory' in self.env.config assert not 'url' in self.env.config assert_raises(KeyError, self.env.config.__getitem__, 'directory') assert_raises(KeyError, self.env.config.__getitem__, 'url') def test_directory_auto(self): """Test how we resolve file references through the Flask static system by default (if no custom 'env.directory' etc. values have been configured manually). """ assert not 'directory' in self.env.config root = self.app.root_path assert get_all_bundle_files(Bundle('foo'), self.env) == [root + '/static/foo'] # Modules prefixes in paths are handled specifically. assert get_all_bundle_files(Bundle('module/bar'), self.env) == [root + '/test_module/static/bar'] # Prefixes that aren't valid module names are just considered # subfolders of the main app. assert get_all_bundle_files(Bundle('nomodule/bar'), self.env) == [root + '/static/nomodule/bar'] # In case the name of a app-level subfolder conflicts with a # module name, you can always use this hack: assert get_all_bundle_files(Bundle('./module/bar'), self.env) == [root + '/static/module/bar'] # Custom static folder self.app.static_folder = '/' assert get_all_bundle_files(Bundle('foo'), self.env) == ['/foo'] def test_url_auto(self): """Test how urls are generated via the Flask static system by default (if no custom 'env.url' etc. values have been configured manually). """ assert not 'url' in self.env.config assert Bundle('foo', env=self.env).urls() == ['/app_static/foo'] # Urls for files that point to a module use that module's url prefix. assert Bundle('module/bar', env=self.env).urls() == ['/mod_static/bar'] # Try with a prefix that's not actually a valid module assert Bundle('nomodule/bar', env=self.env).urls() == ['/app_static/nomodule/bar'] # [Regression] Ensure that any request context we may have added # to the stack has been removed. from flask import _request_ctx_stack assert _request_ctx_stack.top is None def test_custom_load_path(self): """A custom load_path is configured - this will affect how we deal with source files. """ self.env.append_path(self.tempdir, '/custom/') self.create_files(['foo', 'module/bar']) assert get_all_bundle_files(Bundle('foo'), self.env) == [self.path('foo')] # We do not recognize references to modules. assert get_all_bundle_files(Bundle('module/bar'), self.env) == [self.path('module/bar')] assert Bundle('foo', env=self.env).urls() == ['/custom/foo'] assert Bundle('module/bar', env=self.env).urls() == ['/custom/module/bar'] # [Regression] With a load path configured, generating output # urls still works, and it still uses the flask system. self.env.debug = False self.env.url_expire = False assert Bundle('foo', output='out', env=self.env).urls() == ['/app_static/out'] def test_custom_directory_and_url(self): """Custom directory/url are configured - this will affect how we deal with output files.""" # Create source source file, make it findable (by default, # static_folder) is set to a fixed subfolder of the test dir (why?) self.create_files({'a': ''}) self.app.static_folder = self.tempdir # Setup custom directory/url pair for output self.env.directory = self.tempdir self.env.url = '/custom' self.env.debug = False # Return build urls self.env.url_expire = False # No query strings assert Bundle('a', output='foo', env=self.env).urls() == ['/custom/foo'] # We do not recognize references to modules. assert Bundle('a', output='module/bar', env=self.env).urls() == ['/custom/module/bar'] def test_existing_request_object_used(self): """[Regression] Check for a bug where the url generation code of Flask-Assets always added a dummy test request to the context stack, instead of using the existing one if there is one. We test this by making the context define a custom SCRIPT_NAME prefix, and then we check if it affects the generated urls, as it should. """ with self.app.test_request_context( '/', environ_overrides={'SCRIPT_NAME': '/yourapp'}): assert Bundle('foo', env=self.env).urls() == ['/yourapp/app_static/foo'] def test_glob(self): """Make sure url generation works with globs.""" self.app.static_folder = self.tempdir self.create_files({'a.js': 'foo', 'b.js': 'bar'}) assert list(sorted(self.mkbundle('*.js', env=self.env).urls())) == [ '/app_static/a.js', '/app_static/b.js'] class TestUrlAndDirectoryWithInitApp(object): """[Regression] Make sure the automatic "directory" and "url" values also work if the application is initialized via "init_app()". """ def setup(self): self.app = Flask(__name__, static_path='/initapp_static') self.env = Environment() self.env.init_app(self.app) def test(self): """Make sure the "url" and "directory" config values are read from the Flask app. """ with self.app.test_request_context(): assert not 'url' in self.env.config assert Bundle('foo', env=self.env).urls() == ['/initapp_static/foo'] assert not 'directory' in self.env.config root = self.app.root_path assert get_all_bundle_files(Bundle('foo'), self.env) == [root + '/static/foo'] class TestBuild(TempEnvironmentHelper): """[Regression] Make sure actually building a bundle works also. """ default_files = { 'foo': 'function bla () { /* comment */ var a; } ', } def test_build(self): self.mkbundle('foo', filters='rjsmin', output='out').build() assert self.get('out') == 'function bla(){var a;}' def test_with_cache_default_directory(self): """[Regression] The cache directory is created in the Flask main static folder. """ self.env.cache = True self.mkbundle('foo', filters='rjsmin', output='out').build() assert self.get('out') == 'function bla(){var a;}' class TestBlueprints(TempEnvironmentHelper): default_files = { 'foo': 'function bla () { /* comment */ var a; } ', } def make_blueprint(self, name='module', import_name=None, **kw): if not import_name: from tests import test_module import_name = test_module.__name__ if not Blueprint: self.module = Module(import_name, name=name) self.app.register_module(self.module) else: self.blueprint = Blueprint(name, import_name, **kw) self.app.register_blueprint(self.blueprint) def test_blueprint_output(self): """[Regression] Output can point to a blueprint's static directory. """ module_static_dir = self.create_directories('module-static')[0] self.make_blueprint('module', static_folder=module_static_dir) self.mkbundle('foo', filters='rjsmin', output='module/out').build() assert self.get('module-static/out') == 'function bla(){var a;}' def test_blueprint_urls(self): """Urls to blueprint files are generated correctly.""" self.make_blueprint('module', static_folder='static', static_url_path='/rasputin') # source urls assert self.mkbundle('module/foo').urls() == ['/rasputin/foo'] # output urls - env settings are to not touch filesystem self.env.auto_build = False self.env.url_expire = False assert self.mkbundle(output='module/out', debug=False).urls() == ['/rasputin/out'] def test_blueprint_no_static_folder(self): """Test dealing with a blueprint without a static folder.""" self.make_blueprint('module') assert_raises(TypeError, self.mkbundle('module/foo').urls) def test_cssrewrite(self): """Make sure cssrewrite works with Blueprints. """ module_static_dir = self.create_directories('modfolder')[0] self.make_blueprint('modname', static_folder=module_static_dir, static_url_path='/w/u/f/f') self.create_files( {'modfolder/css': 'h1{background: url("local")}'}) # Source file is in a Blueprint, output file is app-level. self.mkbundle('modname/css', filters='cssrewrite', output='out').build() # The urls are NOT rewritten using the filesystem (/modfolder), but # within the url space. assert self.get('out') == 'h1{background: url("../w/u/f/f/local")}' Flask-Assets-0.12/tests/test_module/0000755000076500000240000000000012755403770020161 5ustar michaelstaff00000000000000Flask-Assets-0.12/tests/test_module/__init__.py0000644000076500000240000000020712301437525022261 0ustar michaelstaff00000000000000"""This is here so that the tests have a Python package available that can serve as the base for Flask modules used during testing. """Flask-Assets-0.12/tests/test_module/static/0000755000076500000240000000000012755403770021450 5ustar michaelstaff00000000000000Flask-Assets-0.12/tests/test_module/static/README0000644000076500000240000000006612301437525022322 0ustar michaelstaff00000000000000static folder needs to exist for Flask to pick it up. Flask-Assets-0.12/tests/test_script.py0000644000076500000240000000563312724075227020557 0ustar michaelstaff00000000000000from __future__ import absolute_import from nose import SkipTest # check for flask-script before importing things that fail if it's not present try: from flask_script import Manager except: raise SkipTest() import sys from flask import Flask from flask_assets import Environment, ManageAssets from webassets.script import GenericArgparseImplementation from tests.helpers import TempEnvironmentHelper # Flask-script seemingly no longer supports 2.6 if sys.version_info[:2] == (2, 6): raise SkipTest() # The CLI likes to log to stderr, which isn't nice to the test output. import logging stdout_log = logging.getLogger(__name__) stdout_log.addHandler(logging.StreamHandler(sys.stdout)) class TestScript(TempEnvironmentHelper): def test_call(self): # Setup the webassets.script with a mock main() function, # so we can check whether our call via Flask-Script actually # goes through. test_inst = self class DummyArgparseImplementation(GenericArgparseImplementation): def run_with_argv(self, argv): test_inst.last_script_call = argv return 0 mgmt = Manager(self.app) mgmt.add_command('assets', ManageAssets(self.env, impl=DummyArgparseImplementation)) try: # -h is a great test as that is something Flask-Script might # want to claim for itself. sys.argv = ['./manage.py', 'assets', '-h'] mgmt.run() except SystemExit: # Always raised, regardless of success or failure of command pass assert self.last_script_call == ['-h'] def test_call_auto_env(self): """Regression test: Passing the environment to the ManageAssets command is optional, it can be auto-detected.""" mgmt = Manager(self.app) mgmt.add_command('assets', ManageAssets()) try: # Used to raise an error due to the env not being properly set. sys.argv = ['./manage.py', 'assets', 'build'] mgmt.run() except SystemExit: # Always raised, regardless of success or failure of command pass def test_parse_templates(self): """Test the --parse-templates option. """ # Create a file in the app's templates directory self.app.template_folder = self.path('templates') self.create_files({ 'templates/template.html': """ {% assets "in", output="output" %} {{ ASSET_URL }} {% endassets %} """, 'in': "foo" }) # Run the build command with --parse-templates, which should pick # up the bundle we defined in above template. mgmt = Manager(self.app) mgmt.add_command('assets', ManageAssets(log=stdout_log)) mgmt.handle('test', ['assets', '--parse-templates', 'build']) assert self.exists('output')