Custom resolvers¶
The resolver is a pluggable object that webassets uses to find the
contents of a Bundle on the filesystem, as well as to
generate the correct urls to these files.
For example, the default resolver searches the
Environment.load_path, or looks within
Environment.directory. The webassets Django integration
will use Django’s staticfile finders to look for files.
For normal usage, you will not need to write your own resolver, or
indeed need to know how they work. However, if you want to integrate
webassets with another framework, or if your application is
complex enough that it requires custom file referencing, read on.
The API as webassets sees it¶
webassets expects to find the resolver via the
Environment.resolver property, and expects this object to
provide the following methods:
- Resolver.resolve_source(ctx, item)¶
Given
itemfrom a Bundle’s contents, this has to return the final value to use, usually an absolute filesystem path.Note
It is also allowed to return urls and bundle instances (or generally anything else the calling
Bundleinstance may be able to handle). Indeed this is the reason why the name of this method does not imply a return type.The incoming item is usually a relative path, but may also be an absolute path, or a url. These you will commonly want to return unmodified.
This method is also allowed to resolve
itemto multiple values, in which case a list should be returned. This is commonly used ifitemincludes glob instructions (wildcards).Note
Instead of this, subclasses should consider implementing
search_for_source()instead.
- Resolver.resolve_output_to_path(ctx, target, bundle)¶
Given
target, this has to return the absolute filesystem path to which the output file ofbundleshould be written.targetmay be a relative or absolute path, and is usually taking from theBundle.outputproperty.If a version-placeholder is used (
%(version)s, it is still unresolved at this point.
- Resolver.resolve_source_to_url(ctx, filepath, item)¶
Given the absolute filesystem path in
filepath, as well as the original value fromBundle.contentswhich resolved to this path, this must return the absolute url through which the file is to be referenced.Depending on the use case, either the
filepathor theitemargument will be more helpful in generating the url.This method should raise a
ValueErrorif the url cannot be determined.
- Resolver.resolve_output_to_url(ctx, target)¶
Given
target, this has to return the url through which the output file can be referenced.targetmay be a relative or absolute path, and is usually taking from theBundle.outputproperty.This is different from
resolve_source_to_url()in that you do not passed along the result ofresolve_output_to_path(). This is because in many use cases, the filesystem is not available at the point where the output url is needed (the media server may on a different machine).
Methods to overwrite¶
However, in practice, you will usually want to override the builtin
Resolver, and customize it’s behaviour where necessary. The
default resolver already splits what is is doing into multiple
methods; so that you can either override them, or
refer to them in your own implementation, as makes sense.
Instead of the official entrypoints above, you may instead prefer to override the following methods of the default resolver class:
- Resolver.search_for_source(ctx, item)¶
Called by
resolve_source()after determining thatitemis a relative filesystem path.You should always overwrite this method, and let
resolve_source()deal with absolute paths, urls and other types of items that a bundle may contain.
- Resolver.search_load_path(ctx, item)¶
This is called by
search_for_source()when aEnvironment.load_pathis set.If you want to change how the load path is processed, overwrite this method.
Helpers to use¶
The following methods of the default resolver class you may find useful as helpers while implementing your subclass:
- Resolver.consider_single_directory(directory, item)¶
Searches for
itemwithindirectory. Is able to resolve glob instructions.Subclasses can call this when they have narrowed done the location of a bundle item to a single directory.
- Resolver.glob(basedir, expr)¶
Evaluates a glob expression. Yields a sorted list of absolute filenames.
- Resolver.query_url_mapping(ctx, filepath)¶
Searches the environment-wide url mapping (based on the urls assigned to each directory in the load path). Returns the correct url for
filepath.Subclasses should be sure that they really want to call this method, instead of simply falling back to
super().
Example: A prefix resolver¶
The following is a simple resolver implementation that searches for files in a different directory depending on the first directory part.
from webassets.env import Resolver
class PrefixResolver(Resolver):
def __init__(self, prefixmap):
self.map = prefixmap
def search_for_source(self, ctx, item):
parts = item.split('/', 1)
if len(parts) < 2:
raise ValueError(
'"%s" not valid; a static path requires a prefix.' % item)
prefix, name = parts
if not prefix in self.map:
raise ValueError(('Prefix "%s" of static path "%s" is not '
'registered') % (prefix, item))
# For the rest, defer to base class method, which provides
# support for things like globbing.
return self.consider_single_directory(self.map[prefix], name)
Using it:
env = webassets.Environment(path, url)
env.resolver = PrefixResolver({
'app1': '/var/www/app1/static',
'app2': '/srv/deploy/media/app2',
})
bundle = Bundle(
'app2/scripts/jquery.js',
'app1/*.js',
)
Other implementations¶
django-assets Resolver (search for
class DjangoResolver).Flask-Assets Resolver (search for
class FlaskResolver).pyramid_webassets Resolver (search for
class PyramidResolver).