Media asset management for Python, with glue code for various web frameworks
Comprehensive filter ecosystem for asset transformation including minification, compilation, preprocessing, and optimization. Filters process individual files or bundles through configurable transformation pipelines.
Core filter architecture providing the foundation for all asset transformations.
class Filter:
name = None # Filter name for registration
options = {} # Supported configuration options
max_debug_level = None # Maximum debug level where filter runs
def setup(self):
"""Initialize filter (called before use)."""
def set_context(self, ctx):
"""Set processing context."""
def get_config(self, setting, env=None, require=True, what='dependency', type=None):
"""
Get configuration values.
Parameters:
- setting: Configuration key
- env: Environment instance
- require: Whether setting is required
- what: Description for error messages
- type: Expected value type
Returns:
Configuration value
"""
def input(self, _in, out, **kw):
"""
Process input files.
Parameters:
- _in: Input stream/file
- out: Output stream/file
- **kw: Additional context
"""
def output(self, _in, out, **kw):
"""
Process output files.
Parameters:
- _in: Input stream/file
- out: Output stream/file
- **kw: Additional context
"""
def open(self, out, source_path, **kw):
"""
Direct file processing.
Parameters:
- out: Output stream
- source_path: Source file path
- **kw: Additional context
"""
def concat(self, out, hunks, **kw):
"""
Concatenate multiple sources.
Parameters:
- out: Output stream
- hunks: List of input hunks
- **kw: Additional context
"""
def unique(self):
"""Return unique identifier for filter instance."""
def id(self):
"""Get filter cache key."""
def get_additional_cache_keys(self, **kw):
"""Additional cache dependencies."""
class CallableFilter:
def __init__(self, callable):
"""
Wrapper to create filters from callable functions.
Parameters:
- callable: Function to wrap as filter
"""
class ExternalTool(Filter):
argv = [] # Command line arguments template
method = None # Filter method to implement ('input', 'output', 'open')
def subprocess(self, argv, out, data=None, cwd=None):
"""
Execute external command.
Parameters:
- argv: Command arguments
- out: Output stream
- data: Input data
- cwd: Working directory
"""
def parse_binary(self, string):
"""Parse binary path string."""
class JavaTool(Filter):
"""Base for Java-based filters (JAR files)."""Functions for registering, resolving, and managing filters.
def get_filter(f, *args, **kwargs):
"""
Resolve filter specification to filter instance.
Parameters:
- f: Filter name, class, or instance
- *args: Filter arguments
- **kwargs: Filter options
Returns:
Filter instance
"""
def register_filter(f):
"""
Register filter class with system.
Parameters:
- f: Filter class to register
"""Example usage:
from webassets.filter import get_filter, register_filter
# Get filter by name
jsmin_filter = get_filter('jsmin')
uglify_filter = get_filter('uglifyjs', compress=False)
# Register custom filter
class MyCustomFilter(Filter):
name = 'mycustom'
def input(self, _in, out, **kw):
# Custom processing
pass
register_filter(MyCustomFilter)Minification and optimization filters for JavaScript files.
# Built-in JavaScript filters (import from webassets.filter.*)
class JSMin:
"""JavaScript minification using jsmin library."""
class RJSMin:
"""rJSMin JavaScript minifier with better performance."""
class UglifyJS:
"""UglifyJS minifier with advanced optimization."""
options = {
'binary': 'uglifyjs',
'compress': True,
'mangle': True
}
class ClosureJS:
"""Google Closure Compiler for JavaScript optimization."""
options = {
'binary': 'closure-compiler',
'compilation_level': 'SIMPLE_OPTIMIZATIONS'
}
class YUIJS:
"""YUI JavaScript compressor."""
options = {
'binary': 'yuicompressor',
'jar': None
}
class Slimit:
"""Slimit JavaScript minifier."""
class JSPacker:
"""JavaScript packer for extreme compression."""Minification, optimization, and URL processing filters for CSS files.
# Built-in CSS filters
class CSSMin:
"""CSS minification using cssmin library."""
class RCSSMin:
"""rCSSMin CSS minifier with better performance."""
class CleanCSS:
"""CleanCSS minifier with advanced optimization."""
options = {
'binary': 'cleancss',
'level': 1
}
class YUICSS:
"""YUI CSS compressor."""
options = {
'binary': 'yuicompressor',
'jar': None
}
class CSSSlimmer:
"""CSS Slimmer for CSS optimization."""
class CSSUtils:
"""CSS utilities for parsing and processing."""
class CSSRewrite:
"""CSS URL rewriting for asset path correction."""
options = {
'replace': None,
'base': None
}
class CSSDataUri:
"""Convert CSS references to data URIs."""
options = {
'max_size': 8192,
'include_pattern': None
}
class CSSPrefixer:
"""CSS prefixer for vendor prefixes."""
class AutoPrefixer:
"""Autoprefixer for automatic vendor prefix addition."""
options = {
'binary': 'autoprefixer',
'browsers': None
}Compilation filters for CSS preprocessing languages.
# CSS preprocessor filters
class Sass:
"""Sass/SCSS compilation using Ruby Sass."""
options = {
'binary': 'sass',
'style': 'compressed',
'includes': []
}
class SCSS:
"""SCSS compilation (alias for Sass)."""
class LibSass:
"""LibSass compilation using libsass library."""
options = {
'style': 'compressed',
'include_paths': []
}
class NodeSass:
"""Node-sass compilation."""
options = {
'binary': 'node-sass',
'output_style': 'compressed'
}
class RubySass:
"""Ruby Sass compilation."""
class RubySCSS:
"""Ruby SCSS compilation."""
class Less:
"""Less compilation."""
options = {
'binary': 'lessc',
'compress': True
}
class Stylus:
"""Stylus compilation."""
options = {
'binary': 'stylus',
'compress': True
}
class CleverCSS:
"""CleverCSS compilation."""
class PyScss:
"""pyScss compilation using Python library."""
options = {
'style': 'compressed',
'imports': []
}
class Compass:
"""Compass compilation framework."""
options = {
'binary': 'compass',
'style': 'compressed',
'images_dir': 'images'
}
class PostCSS:
"""PostCSS processing with plugins."""
options = {
'binary': 'postcss',
'plugins': []
}Compilation and templating filters for JavaScript and related languages.
# JavaScript preprocessors
class CoffeeScript:
"""CoffeeScript compilation."""
options = {
'binary': 'coffee',
'bare': False
}
class TypeScript:
"""TypeScript compilation."""
options = {
'binary': 'tsc',
'target': 'es5',
'module': 'commonjs'
}
class Babel:
"""Babel transpilation for modern JavaScript."""
options = {
'binary': 'babel',
'presets': ['env']
}
# Template engines
class Handlebars:
"""Handlebars template compilation."""
options = {
'binary': 'handlebars',
'namespace': 'templates'
}
class Jinja2:
"""Jinja2 template processing."""
class JST:
"""JavaScript templates (Underscore.js style)."""
options = {
'namespace': 'JST',
'bare': False
}
class DustJS:
"""Dust.js template compilation."""
options = {
'binary': 'dustc',
'name': None
}
class Jade:
"""Jade template compilation."""
options = {
'binary': 'jade',
'pretty': False
}Advanced filters for specific optimization and processing tasks.
# Specialized filters
class RequireJS:
"""RequireJS optimizer (r.js)."""
options = {
'binary': 'r.js',
'baseUrl': None,
'optimize': 'uglify2'
}
class Spritemapper:
"""CSS sprite generation."""
options = {
'binary': 'spritemapper',
'output_css': None,
'output_image': None
}
class ClosureTemplateFilter:
"""Closure Templates compilation."""
options = {
'binary': 'SoyToJsSrcCompiler.jar',
'jar': None
}
class ClosureStylesheetsCompiler:
"""Closure Stylesheets compiler."""
options = {
'binary': 'closure-stylesheets.jar',
'jar': None
}
class ClosureStylesheetsMinifier:
"""Closure Stylesheets minifier."""
options = {
'binary': 'closure-stylesheets.jar',
'jar': None
}from webassets.filter import Filter
class CustomSassFilter(Filter):
name = 'custom_sass'
options = {
'style': 'compressed',
'include_paths': []
}
def input(self, _in, out, **kw):
import sass
# Get configuration
style = self.get_config('style', require=False) or 'compressed'
include_paths = self.get_config('include_paths', require=False) or []
# Process input
source = _in.read()
result = sass.compile(
string=source,
output_style=style,
include_paths=include_paths
)
out.write(result)
# Register and use
from webassets.filter import register_filter
register_filter(CustomSassFilter)
# Use in bundle
Bundle('style.scss', filters='custom_sass', output='style.css')# Chain multiple filters
Bundle(
'app.js',
'utils.js',
filters=['babel', 'uglifyjs'], # Babel first, then UglifyJS
output='gen/app.js'
)
# CSS preprocessing and optimization
Bundle(
'style.scss',
filters=['sass', 'autoprefixer', 'cssmin'],
output='gen/style.css'
)
# Complex filter chain
Bundle(
'template.handlebars',
'app.coffee',
filters=['handlebars', 'coffeescript', 'uglifyjs'],
output='gen/compiled.js'
)from webassets import Environment, Bundle
env = Environment('./static', '/static')
# Global filter configuration
env.config['uglifyjs_binary'] = '/usr/local/bin/uglifyjs'
env.config['sass_style'] = 'compressed'
env.config['autoprefixer_browsers'] = ['last 2 versions', 'ie >= 9']
# Bundle-specific filter options
Bundle(
'app.js',
filters={'uglifyjs': {'compress': False, 'mangle': True}},
output='gen/app.js'
)
# Environment-specific settings
if env.debug:
js_filters = None # No minification in debug
else:
js_filters = ['babel', 'uglifyjs']
Bundle('app.js', filters=js_filters, output='gen/app.js')def get_js_filters(debug=False):
if debug:
return ['babel'] # Only transpile, don't minify
else:
return ['babel', 'uglifyjs'] # Transpile and minify
def get_css_filters(debug=False):
base_filters = ['sass', 'autoprefixer']
if not debug:
base_filters.append('cssmin')
return base_filters
# Create bundles with conditional filters
js_bundle = Bundle(
'app.js',
filters=get_js_filters(env.debug),
output='gen/app.js'
)
css_bundle = Bundle(
'style.scss',
filters=get_css_filters(env.debug),
output='gen/style.css'
)Install with Tessl CLI
npx tessl i tessl/pypi-webassets