pyramid_assetmutator¶
Overview¶
pyramid_assetmutator
provides simple and flexible asset mutation (also known
as compiling or piping) for your Pyramid applications.
Its goal is to provide Pyramid developers with a basic and straightforward mechanism for utilizing asset compilation (e.g. for CoffeeScript/Sass), minification (e.g. with jsmin), and optimization (e.g. with pngcrush).
As of version 0.3, it also adds experimental support for template language
parsing (e.g. you could use Pyramid helpers like request.route_url()
within
your CoffeeScript files by using application.coffee.pt
as the asset source
filename).
Warning
This package only supports Pyramid 1.3 or later.
Setup¶
Once pyramid_assetmutator
is installed, you must include it in your Pyramid
project’s configuration. This is typically done using Pyramid’s
config.include
mechanism in your
project’s __init__.py
:
config = Configurator(...)
config.include('pyramid_assetmutator')
Next, you must assign one or more mutators via the newly injected
assign_assetmutator()
configuration method, so that
your application can know what kind of assets you’ll be asking it to mutate. The
configuration syntax for your Pyramid project’s __init__.py
is:
config.assign_assetmutator('SOURCE EXTENSION', 'COMMAND', 'OUTPUT EXTENSION')
For example, the following configuration would activate pyramid_assetmutator
in your app, and initialize mutators for CoffeeScript and Less files (allowing
them to be compiled into the appropriate JavaScript and CSS):
config = Configurator(...)
config.include('pyramid_assetmutator')
config.assign_assetmutator('coffee', 'coffee -c -p', 'js')
config.assign_assetmutator('less', 'lessc', 'css')
Usage¶
Once you have included the module and configured your mutators, you will then be able to call one of the following view helper methods in your templates to reference (with Pyramid’s asset specification syntax) and “mutate” (if needed) an asset:
-
class
AssetMutator
(request, rendering_val) -
assetmutator_url
(path, **kw) Returns a Pyramid
static_url()
of the mutated asset (and mutates the asset if needed).Parameters: - path (string - Required) – The Pyramid asset path to process.
- mutator (dict or string - Optional) – Allows you to override/specify a specific mutator to use
(e.g.
coffee
), or assign a brand new mutator dictionary to be used (e.g.{'cmd': 'lessc', 'ext': 'css'}
)
-
assetmutator_path
(path, **kw) Returns a Pyramid
static_path()
of the mutated asset (and mutates the asset if needed).Parameters: - path (string - Required) – The Pyramid asset path to process.
- mutator (dict or string - Optional) – Allows you to override/specify a specific mutator to use
(e.g.
coffee
), or assign a brand new mutator dictionary to be used (e.g.{'cmd': 'lessc', 'ext': 'css'}
)
-
assetmutator_source
(path, **kw) Returns the source data/contents of the mutated asset (and mutates the asset if needed). This is useful when you want to output inline data (e.g. for inline JavaScript blocks).
Parameters: - path (string - Required) – The Pyramid asset path to process.
- mutator (dict or string - Optional) – Allows you to override/specify a specific mutator to use
(e.g.
coffee
), or assign a brand new mutator dictionary to be used (e.g.{'cmd': 'lessc', 'ext': 'css'}
)
Note
Many template packages escape output by default. Consult your template language’s syntax to output an unescaped string.
-
assetmutator_assetpath
(path, **kw) Returns a Pyramid asset specification such as
pkg:static/path/to/file.ext
(and mutates the asset if needed).Parameters: - path (string - Required) – The Pyramid asset path to process.
- mutator (dict or string - Optional) – Allows you to override/specify a specific mutator to use
(e.g.
coffee
), or assign a brand new mutator dictionary to be used (e.g.{'cmd': 'lessc', 'ext': 'css'}
)
This function could be used to nest
pyramid_assetmutator
calls. e.g.assetmutator_path(assetmutator_assetpath('pkg:static/js/script.coffee'))
could compile a CoffeeScript file into JS, and then further minify the JS file if your mutator configuration looked something like:config.assign_assetmutator('coffee', 'coffee -c -p', 'js') config.assign_assetmutator('js', 'uglifyjs', 'js')
-
Template Language Parsing¶
In version 0.3, experimental support for template language parsing was added. As long as the template language is known to Pyramid (e.g. one of these bindings has been configured), you can append the expected template filename extension to your asset filename and it will attempt to parse it before mutation.
For example, if the pyramid_jinja2
package was configured, you could specify
an asset path to an asset named application.coffee.jinja2
and
pyramid_assetmutator
would run it through the Jinja2 renderer before
mutation.
Warning
Current support is experimental, and there are a few caveats:
- You must specify a
mutated_path
in your configuration so that the intermediate-step sources can be stored and parsed from that directory. - Template parsing is currently only supported when using the
each_request
configuration (which is the default configuration). - If Pyramid’s “reload_templates” setting is false, templates will _NOT_ be reprocessed.
- Hopefully obvious, but if the asset you are parsing uses a syntax that conflicts with the template language’s syntax, things probably won’t work out very well for you.
Examples¶
An example using the Chameleon template language (and assuming that a mutator has been assigned for “coffee” files):
<script src="${assetmutator_url('pkg:static/js/test.coffee')}"
type="text/javascript"></script>
And now the same example, but for inline
code output:
<script type="text/javascript">
${structure: assetmutator_source('pkg:static/js/test.coffee')}
</script>
Or, if your default JS mutator configuration uses jsmin
, but you wanted to
use uglifyjs
for a particular asset:
<script src="${assetmutator_url('pkg:static/js/test.js', mutator={'cmd': 'uglifyjs', 'ext': 'js'})}"
type="text/javascript"></script>
As of version 0.3, your asset source could be parsed with Chameleon as well:
<script src="${assetmutator_url('pkg:static/js/test.coffee.pt')}"
type="text/javascript"></script>
Lastly, assetmutator_assetpath()
is a particularly
nifty/dirty method which gives you the ability to chain mutators. For example,
if you wanted to mutate a CoffeeScript file into a JavaScript file and then
minify the JavaScript file, you could do something like:
<script src="${assetmutator_url(assetmutator_assetpath('pkg:static/js/test.coffee'))}"
type="text/javascript"></script>
Mutators¶
You can assign as many mutators as you like using the
config.assign_assetmutator
method, but it is important to keep in mind the
following:
- The mutator
COMMAND
must be installed, must be executable by the Pyramid process, and by default must output the mutated data to stdout. The last point can be tricky depending on the command, so be sure to check its command switches for the appropriate option (or create a wrapper as seen below).- Mutators are executed in order (first in, first out), which means that it is possible to compile a CoffeeScript file into a JavaScript file and then minify the JavaScript file; but for certain configurations this may only work if you have assigned the CoffeeScript compiler before the JavaScript minifier.
Here are a few mutator commands that have been tested and are known to work as of this writing:
# CoffeeScript - http://coffeescript.org/
config.assign_assetmutator('coffee', 'coffee -c -p', 'js')
# Dart - http://www.dartlang.org/
# Requires a wrapper - http://gist.github.com/98aa5e3f3d183d908caa
config.assign_assetmutator('dart', 'dart_wrapper', 'js')
# TypeScript - http://www.typescriptlang.org/
# Requires a wrapper - http://gist.github.com/eaace8a89881c8ca9cda
config.assign_assetmutator('ts', 'tsc_wrapper', 'js')
# Less - http://lesscss.org/
config.assign_assetmutator('less', 'lessc', 'css')
# Sass/SCSS - http://sass-lang.com/
config.assign_assetmutator('sass', 'sass', 'css')
config.assign_assetmutator('scss', 'sass --scss', 'css')
# jsmin - http://www.crockford.com/javascript/jsmin.html
config.assign_assetmutator('js', 'jsmin', 'js')
# UglifyJS - http://github.com/mishoo/UglifyJS
config.assign_assetmutator('js', 'uglifyjs', 'js')
# pngcrush - http://pmt.sourceforge.net/pngcrush/
# Requires a wrapper - http://gist.github.com/3a0c72ef9bb217315347
config.assign_assetmutator('png', 'pngcrush_wrapper', 'png')
Settings¶
While the default settings will probably be fine for most people, custom
settings can be configured via your Pyramid application’s .ini
file (in the
app section representing your Pyramid app) using the assetmutator
key:
assetmutator.remutate_check
Default: stat Options: exists | stat | checksum Defines what type of method to use for checking if an asset source has been updated (and should therefore be remutated). If set to
exists
(fastest, but not always ideal), then it will only check to see if a file matching the mutated version of the asset already exists. If set tostat
, then the size and last modified time will be checked. If set tochecksum
(slowest, but most reliable), then the file contents will also be checked.assetmutator.each_request
Default: true Whether or not assets should be checked/mutated during each request (whenever one of the
assetmutator_*
methods is encountered).assetmutator.each_boot
Default: [] Defines a list of asset specifications that should be checked/mutated when the application boots (uses Pyramid’s
ApplicationCreated
event).Limited “globbing” support is available (via the
glob
module), although checks are not recursive so you must be explicit.e.g.:
assetmutator.each_boot = myapp:static/js/application.coffee myapp:static/css/*.sass myapp:static/css/admin/*.sassassetmutator.mutated_file_prefix
Default: _ A prefix to add to the mutated asset’s output filename.
assetmutator.mutated_path
Default: None By default, mutated output files are stored in the same directory as their source files. If you would like to keep all mutated files in a specific directory, you can define a Pyramid asset specification here (e.g.
pkg:static/cache/
).Note
The specified path must be a valid asset specification that matches a configured static view, and must be writable by the application.
assetmutator.purge_mutated_path
Default: false When
true
, if a validmutated_path
is specified then any files within it will be deleted when the application boots (uses Pyramid’sApplicationCreated
event).assetmutator.always_remutate
Default: [] Defines a list of asset specifications that should always be remutated — even if the mutated version of the asset is already present.
Limited “globbing” support is available (via the
fnmatch
module), so a value of*.sass
would match all Sass sources, while a star value (*
) would specify that all sources should always be remutated.e.g.:
assetmutator.always_remutate = *.sass myapp:static/js/application.coffeeNote
Combining this with the
each_request
setting can be useful in development environments when your source files contain imports and therefore may not always change but should still be remutated so that import changes are processed. However, this can significantly affect performance so it should only be utilized in environments that require it. Alternatively, you may use aremutate_check
value ofstat
(the default) orchecksum
and manually “touch” a source file to trigger a remutate on the next request.
Production Example
As an example, if you wanted to only check/mutate assets on each boot (a good
practice for production environments), processing CoffeeScript and Sass files in
the js
and css
root and admin directories, with each mutated
_filename
stored in a myapp:static/cache/
directory, your .ini
file
would look something like:
[app:main]
...other settings...
assetmutator.each_request = false
assetmutator.each_boot =
myapp:static/js/*.coffee
myapp:static/js/admin/*.coffee
myapp:static/css/*.sass
myapp:static/css/admin/*.sass
assetmutator.mutated_path = myapp:static/cache/
Asset Concatenation (a.k.a Asset Pipeline)¶
A feature that is popular in some web frameworks (e.g. Ruby on Rails) is the
ability to combine all assets that share a common type into a single file for
sourcing within your templates. However, this functionality is currently
beyond the scope of pyramid_assetmutator
as we consider it to have less and
less relevance in an HTTP/2 era.
More Information¶
Development Versions / Reporting Issues¶
Visit http://github.com/seedifferently/pyramid_assetmutator to download development or tagged versions.
Visit http://github.com/seedifferently/pyramid_assetmutator/issues to report issues.