summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris McDonough <chrism@agendaless.com>2009-11-27 07:56:24 +0000
committerChris McDonough <chrism@agendaless.com>2009-11-27 07:56:24 +0000
commitea599997a3f1aeff9620a9247c99d9e5883f00d1 (patch)
tree9d5528a3543fd0cd7143770e2e57c58d6b1b6983
parent813d952d063d9fe5a237bacf1cff35131cc15ba8 (diff)
downloadpyramid-ea599997a3f1aeff9620a9247c99d9e5883f00d1.tar.gz
pyramid-ea599997a3f1aeff9620a9247c99d9e5883f00d1.tar.bz2
pyramid-ea599997a3f1aeff9620a9247c99d9e5883f00d1.zip
configurator API docs.
-rw-r--r--TODO.txt13
-rw-r--r--docs/narr/views.rst77
-rw-r--r--repoze/bfg/configuration.py486
3 files changed, 519 insertions, 57 deletions
diff --git a/TODO.txt b/TODO.txt
index d6b68d920..7a19ca59a 100644
--- a/TODO.txt
+++ b/TODO.txt
@@ -1,18 +1,7 @@
-- Decide about creating a "real" request object during testing.setUp
- vs. creating a dummy request.
-
- Audit the rest of the docs for "view configuration" and "route
configuration" references, etc.
-- Finish Configurator API documentation.
-
-- set_security_policies as API method?
-
-- add set_response_factory or ctor arg and change hooks chapter.
-
-- add set_traverser or ctor arg and change hooks chapter.
-
-- add set_urlgenerator as ctor arg and change hooks chapter?
+- Find ZCML-only docs that deserve imperative-mode analogues.
- Basic WSGI documentation (pipeline / app / server).
diff --git a/docs/narr/views.rst b/docs/narr/views.rst
index 566ef765a..41323e52a 100644
--- a/docs/narr/views.rst
+++ b/docs/narr/views.rst
@@ -349,11 +349,6 @@ view
defaults to a view that returns an empty dictionary (see
:ref:`views_which_use_a_renderer`).
-name
-
- The *view name*. Read and understand :ref:`traversal_chapter` to
- understand the concept of a view name.
-
permission
The name of a *permission* that the user must possess in order to
@@ -432,6 +427,11 @@ wrapper
Predicate Attributes
####################
+name
+
+ The *view name*. Read the :ref:`traversal_chapter` to understand
+ the concept of a view name.
+
for
A Python dotted-path name representing the Python class that the
@@ -447,14 +447,12 @@ route_name
unless you want to perform traversal *after* a route has matched.*
This value must match the ``name`` of a ``<route>`` declaration (see
:ref:`urldispatch_chapter`) that must match before this view will be
- called. The ``<route>`` declaration specified by ``route_name`` must
- exist in ZCML before the view that names the route
- (XML-ordering-wise) . Note that the ``<route>`` declaration
- referred to by ``route_name`` usually has a ``*traverse`` token in
- the value of its ``path`` attribute, representing a part of the path
- that will be used by traversal against the result of the route's
- :term:`root factory`. See :ref:`hybrid_chapter` for more
- information on using this advanced feature.
+ called. Note that the ``route`` configuration referred to by
+ ``route_name`` usually has a ``*traverse`` token in the value of its
+ ``path``, representing a part of the path that will be used by
+ traversal against the result of the route's :term:`root factory`.
+ See :ref:`hybrid_chapter` for more information on using this
+ advanced feature.
request_type
@@ -1612,20 +1610,32 @@ callable to influence automatically constructed response attributes.
Adding and Overriding Renderers
-------------------------------
-Additional ZCML declarations can be made which override an existing
-:term:`renderer` or which add a new renderer. Adding or overriding a
-renderer is accomplished via one or more separate ZCML directives.
+Additional configuration declarations can be made which override an
+existing :term:`renderer` or which add a new renderer. Adding or
+overriding a renderer is accomplished via :term:`ZCML` or via
+imperative configuration.
For example, to add a renderer which renders views which have a
``renderer`` attribute that is a path that ends in ``.jinja``::
- <renderer
- name=".jinja"
- factory="my.package.MyJinja2Renderer"/>
+.. topic:: Via ZCML
+
+ <renderer
+ name=".jinja"
+ factory="my.package.MyJinja2Renderer"/>
+
+ The ``factory`` attribute is a dotted Python name that must point
+ to an implementation of a :term:`renderer`.
+
+ The ``name`` attribute
+
+.. topic:: Via Imperative Configuration
-The ``factory`` attribute is a dotted Python name that must point to
-an implementation of a renderer. A renderer implementation is usually
-a class which has the following interface:
+ from my.package import MyJinja2Renderer
+ config.add_renderer('.jinja', MyJinja2Renderer)
+
+A renderer implementation is usually a class which has the following
+interface:
.. code-block:: python
:linenos:
@@ -1641,31 +1651,24 @@ a class which has the following interface:
system value is a dictionary containing available system
values (e.g. ``view``, ``context``, and ``request``). """
-A renderer's ``name`` is the second element of a ``<renderer>`` tag.
There are essentially two different kinds of ``renderer``
-registrations with respect to the name:
-
-- a ``renderer`` registration which has a ``name`` attribute which
- has a value that starts with a dot (``.``).
-
-- a ``renderer`` registration which has a ``name`` attribute which
- has a value that *does not* start with a dot.
+registrations: registrations that use a dot (``.``) in their ``name``
+argument and ones which do not.
Renderer registrations that have a ``name`` attribute which starts
with a dot are meant to be *wildcard* registrations. When a ``view``
-configuration is encountered which has a ``renderer`` attribute that
+configuration is encountered which has a ``name`` attribute that
contains a dot, at startup time, the path is split on its final dot,
and the second element of the split (the filename extension,
typically) is used to look up a renderer for the configured view. The
-renderer's factory is still passed the entire ``renderer`` attribute
-value (not just the extension).
+renderer's factory is still passed the entire ``name`` attribute value
+(not just the extension).
Renderer registrations that have ``name`` attribute which *does not*
start with a dot are meant to be absolute registrations. When a
-``view`` configuration is encountered which has a ``renderer``
-attribute that does not contain a dot, the full value of the
-``renderer`` attribute is used to look up the renderer for the
-configured view.
+``view`` configuration is encountered which has a ``name`` argument
+that does not contain a dot, the full value of the ``name`` attribute
+is used to look up the renderer for the configured view.
Here's an example of a renderer registration in ZCML:
diff --git a/repoze/bfg/configuration.py b/repoze/bfg/configuration.py
index e4ade41fe..62889e359 100644
--- a/repoze/bfg/configuration.py
+++ b/repoze/bfg/configuration.py
@@ -249,7 +249,7 @@ class Configurator(object):
# API
def add_subscriber(self, subscriber, iface=None):
- """ Add an event subscriber for the event stream implied by
+ """Add an event subscriber for the event stream implied by
the supplied ``iface`` interface. The ``subscriber`` argument
represents a callable object; it will be called with a single
object ``event`` whenever :mod:`repoze.bfg` emits an event
@@ -327,7 +327,212 @@ class Configurator(object):
renderer=None, wrapper=None, xhr=False, accept=None,
header=None, path_info=None, _info=u''):
""" Add a :term:`view configuration` to the current
- configuration state."""
+ configuration state. Arguments to ``add_view`` are broken
+ down below into *predicate* arguments and *non-predicate*
+ arguments. Predicate arguments narrow the circumstances in
+ which a view will be invoked; non-predicate arguments are
+ informational.
+
+ Non-Predicate Arguments
+
+ view
+
+ The Python dotted-path name to the view callable. This
+ argument is required unless a ``renderer`` attribute also
+ exists. If a ``renderer`` argument is passed, this
+ attribute defaults to a view that returns an empty
+ dictionary (see :ref:`views_which_use_a_renderer`).
+
+ permission
+
+ The name of a *permission* that the user must possess in
+ order to call the view. See :ref:`view_security_section`
+ for more information about view security and permissions.
+
+ attr
+
+ The view machinery defaults to using the ``__call__`` method
+ of the view callable (or the function itself, if the view
+ callable is a function) to obtain a response dictionary.
+ The ``attr`` value allows you to vary the method attribute
+ used to obtain the response. For example, if your view was
+ a class, and the class has a method named ``index`` and you
+ wanted to use this method instead of the class' ``__call__``
+ method to return the response, you'd say ``attr="index"`` in the
+ view configuration for the view. This is
+ most useful when the view definition is a class.
+
+ renderer
+
+ This is either a single string term (e.g. ``json``) or a
+ string implying a path or :term:`resource specification`
+ (e.g. ``templates/views.pt``). If the renderer value is a
+ single term (does not contain a dot ``.``), the specified
+ term will be used to look up a renderer implementation, and
+ that renderer implementation will be used to construct a
+ response from the view return value. If the renderer term
+ contains a dot (``.``), the specified term will be treated
+ as a path, and the filename extension of the last element in
+ the path will be used to look up the renderer
+ implementation, which will be passed the full path. The
+ renderer implementation will be used to construct a response
+ from the view return value.
+
+ Note that if the view itself returns a response (see
+ :ref:`the_response`), the specified renderer implementation
+ is never called.
+
+ When the renderer is a path, although a path is usually just
+ a simple relative pathname (e.g. ``templates/foo.pt``,
+ implying that a template named"foo.pt" is in the "templates"
+ directory relative to the directory of *package* of the
+ Configurator), a path can be absolute, starting with a slash
+ on UNIX or a drive letter prefix on Windows. The path can
+ alternately be a :term:`resource specification` in the form
+ ``some.dotted.package_name:relative/path``, making it
+ possible to address template resources which live in a
+ separate package.
+
+ The ``renderer`` attribute is optional. If it is not
+ defined, the "null" renderer is assumed (no rendering is performed
+ and the value is passed back to the upstream BFG machinery
+ unmolested).
+
+ wrapper
+
+ The :term:`view name` of another view declared elsewhere in
+ configuration which will receive the response body of this
+ view as the ``request.wrapped_body`` attribute of its own
+ request, and the response returned by this view as the
+ ``request.wrapped_response`` attribute of its own request.
+ Using a wrapper makes it possible to
+ "chain" views together to form a composite response. The response
+ of the outermost wrapper view will be returned to the user. The
+ wrapper view will be found as any view is found: see
+ :ref:`view_lookup_ordering`. The "best" wrapper view will be found
+ based on the lookup ordering: "under the hood" this wrapper view is
+ looked up via ``repoze.bfg.view.render_view_to_response(context,
+ request, 'wrapper_viewname')``. The context and request of a wrapper
+ view is the same context and request of the inner view. If this
+ attribute is unspecified, no view wrapping is done.
+
+ Predicate Arguments
+
+ name
+
+ The :term:`view name`. Read the :ref:`traversal_chapter` to
+ understand the concept of a view name.
+
+ for
+
+ An object representing Python class that the :term:`context`
+ must be an instance of, *or* the :term:`interface` that the
+ :term:`context` must provide in order for this view to be
+ found and called. This predicate is true when the
+ :term:`context` is an instance of the represented class or
+ if the :term:`context` provides the represented interface;
+ it is otherwise false.
+
+ route_name
+
+ *This argument services an advanced feature that isn't often
+ used unless you want to perform traversal *after* a route
+ has matched.* This value must match the ``name`` of a
+ ``<route>`` declaration (see :ref:`urldispatch_chapter`)
+ that must match before this view will be called. Note that
+ the ``route`` configuration referred to by ``route_name``
+ usually has a ``*traverse`` token in the value of its
+ ``path``, representing a part of the path that will be used
+ by traversal against the result of the route's :term:`root
+ factory`.See :ref:`hybrid_chapter` for more information on
+ using this advanced feature.
+
+ request_type
+
+ This value should be an :term:`interface` that the
+ :term:`request` must provide in order for this view to be
+ found and called. See :ref:`view_request_types_section` for
+ more information about request types.
+
+ request_method
+
+ This value can either be one of the strings 'GET', 'POST',
+ 'PUT', 'DELETE', or 'HEAD' representing an HTTP
+ ``REQUEST_METHOD``. A view declaration with this argument
+ ensures that the view will only be called when the request's
+ ``method`` (aka ``REQUEST_METHOD``) string matches the
+ supplied value.
+
+ request_param
+
+ This value can be any string. A view declaration with this
+ argument ensures that the view will only be called when the
+ request has a key in the ``request.params`` dictionary (an
+ HTTP ``GET`` or ``POST`` variable) that has a name which
+ matches the supplied value. If the value supplied to the
+ attribute has a ``=`` sign in it, e.g. ``request_params="foo=123"``,
+ then the key (``foo``) must both exist in the ``request.params``
+ dictionary, and the value must match the right hand side of the
+ expression (``123``) for the view to "match" the current request.
+
+ containment
+
+ This value should be a reference to a Python class that a
+ graph traversal parent object of the :term:`context` must be
+ an instance of or :term:`interface` that a parent object
+ must provide in order for this view to be found and called.
+ Your models must be"location-aware" to use this feature. See
+ :ref:`location_aware` for more information about location-awareness.
+
+ xhr
+
+ This value should be either ``True`` or ``False``. If this
+ value is specified and is ``True``, the :term:`request` must
+ possess an ``HTTP_X_REQUESTED_WITH`` (aka
+ ``X-Requested-With``) header that has the value
+ ``XMLHttpRequest`` for this view to be found and called.
+ This is useful for detecting AJAX requests issued from
+ jQuery, Prototype and other Javascript libraries.
+
+ accept
+
+ The value of this attribute represents a match query for one
+ or more mimetypes in the ``Accept`` HTTP request header. If
+ this value is specified, it must be in one of the following
+ forms: a mimetype match token in the form ``text/plain``, a
+ wildcard mimetype match token in the form ``text/*`` or a
+ match-all wildcard mimetype match token in the form ``*/*``.
+ If any of the forms matches the ``Accept`` header of the
+ request, this predicate will be true.
+
+ header
+
+ This value represents an HTTP header name or a header
+ name/value pair. If the value contains a ``:`` (colon), it
+ will be considered a name/value pair
+ (e.g. ``User-Agent:Mozilla/.*`` or ``Host:localhost``). The
+ *value* of an attribute that represent a name/value pair
+ should be a regular expression. If the value does not
+ contain a colon, the entire value will be considered to be
+ the header name (e.g. ``If-Modified-Since``). If the value
+ evaluates to a header name only without a value, the header
+ specified by the name must be present in the request for
+ this predicate to be true. If the value evaluates to a
+ header name/value pair, the header specified by the name
+ must be present in the request *and* the regular expression
+ specified as the value must match the header value. Whether
+ or not the value represents a header name or a header
+ name/value pair, the case of the header name is not
+ significant.
+
+ path_info
+
+ This value represents a regular expression pattern that will
+ be tested against the ``PATH_INFO`` WSGI environment
+ variable. If the regex matches, this predicate will be
+ true.
+
+ """
if not view:
if renderer:
@@ -409,7 +614,209 @@ class Configurator(object):
view_accept=None, view_xhr=False,
view_path_info=None, _info=u''):
""" Add a :term:`route configuration` to the current
- configuration state."""
+ configuration state, as well as possibly a :term:`view
+ configuration` to be used to specify a :term:`view callable`
+ that will be invoked when this route matches. The arguments
+ to this method are divided into *predicate*, *non-predicate*,
+ and *view-related* types. Predicate arguments narrow the
+ circumstances in which a route will be match a request;
+ non-predicate arguments are informational. View-related types
+ are used to modify the
+
+
+ Non-Predicate Arguments
+
+ name
+
+ The name of the route, e.g. ``myroute``. This attribute is
+ required. It must be unique among all defined routes in a given
+ configuration.
+
+ factory
+
+ A reference to a Python object (often a function) that will
+ generate a :mod:`repoze.bfg` context object when this route
+ matches. e.g. ``mypackage.models.MyFactoryClass``. If this
+ argument is not specified, a default root factory will be
+ used.
+
+ Predicate Arguments
+
+ path
+
+ The path of the route e.g. ``ideas/:idea``. This argument
+ is required. See :ref:`route_path_pattern_syntax` for
+ information about the syntax of route paths.
+
+ xhr
+
+ This value should be either ``True`` or ``False``. If this
+ value is specified and is ``True``, the :term:`request` must
+ possess an ``HTTP_X_REQUESTED_WITH`` (aka
+ ``X-Requested-With``) header for this route to match. This
+ is useful for detecting AJAX requests issued from jQuery,
+ Prototype and other Javascript libraries. If this predicate
+ returns false, route matching continues.
+
+ request_method
+
+ A string representing an HTTP method name, e.g. ``GET``,
+ ``POST``, ``HEAD``, ``DELETE``, ``PUT``. If this argument
+ is not specified, this route will match if the request has
+ *any* request method. If this predicate returns false,
+ route matching continues.
+
+ path_info
+
+ This value represents a regular expression pattern that will
+ be tested against the ``PATH_INFO`` WSGI environment
+ variable. If the regex matches, this predicate will be
+ true. If this predicate returns false, route matching
+ continues.
+
+ request_param
+
+ This value can be any string. A view declaration with this
+ argument ensures that the associated route will only match
+ when the request has a key in the ``request.params``
+ dictionary (an HTTP ``GET`` or ``POST`` variable) that has a
+ name which matches the supplied value. If the value
+ supplied as the argument has a ``=`` sign in it,
+ e.g. ``request_params="foo=123"``, then the key
+ (``foo``) must both exist in the ``request.params`` dictionary, and
+ the value must match the right hand side of the expression (``123``)
+ for the route to "match" the current request. If this predicate
+ returns false, route matching continues.
+
+ header
+
+ This value represents an HTTP header name or a header
+ name/value pair. If the value contains a ``:`` (colon), it
+ will be considered a name/value pair
+ (e.g. ``User-Agent:Mozilla/.*`` or ``Host:localhost``). The
+ *value* of such a pair should be a regular expression. If
+ the value does not contain a colon, the entire value will be
+ considered to be the header name
+ (e.g. ``If-Modified-Since``). If the value evaluates to a
+ header name only without a value, the header specified by
+ the name must be present in the request for this predicate
+ to be true. If the value evaluates to a header name/value
+ pair, the header specified by the name must be present in
+ the request *and* the regular expression specified as the
+ value must match the header value. Whether or not the value
+ represents a header name or a header name/value pair, the
+ case of the header name is not significant. If this
+ predicate returns false, route matching continues.
+
+ accept
+
+ This value represents a match query for one or more
+ mimetypes in the ``Accept`` HTTP request header. If this
+ value is specified, it must be in one of the following
+ forms: a mimetype match token in the form ``text/plain``, a
+ wildcard mimetype match token in the form ``text/*`` or a
+ match-all wildcard mimetype match token in the form ``*/*``.
+ If any of the forms matches the ``Accept`` header of the
+ request, this predicate will be true. If this predicate
+ returns false, route matching continues.
+
+ View-Related Arguments
+
+ view
+
+ A reference to a Python object that will be used as a view
+ callable when this route
+ matches. e.g. ``mypackage.views.my_view``.
+
+ view_for
+
+ A reference to a class or an :term:`interface` that the
+ :term:`context` of the view should match for the view named
+ by the route to be used. This argument is only useful if
+ the ``view`` attribute is used. If this attribute is not
+ specified, the default (``None``) will be used.
+
+ If the ``view`` argument is not provided, this argument has
+ no effect.
+
+ This attribute can also be spelled as ``for_``.
+
+ view_permission
+
+ The permission name required to invoke the view associated
+ with this route. e.g. ``edit``. (see
+ :ref:`using_security_with_urldispatch` for more information
+ about permissions).
+
+ If the ``view`` attribute is not provided, this argument has
+ no effect.
+
+ This argument can also be spelled as ``permission``.
+
+ view_renderer
+
+ This is either a single string term (e.g. ``json``) or a
+ string implying a path or :term:`resource specification`
+ (e.g. ``templates/views.pt``). If the renderer value is a
+ single term (does not contain a dot ``.``), the specified
+ term will be used to look up a renderer implementation, and
+ that renderer implementation will be used to construct a
+ response from the view return value. If the renderer term
+ contains a dot (``.``), the specified term will be treated
+ as a path, and the filename extension of the last element in
+ the path will be used to look up the renderer
+ implementation, which will be passed the full path. The
+ renderer implementation will be used to construct a response
+ from the view return value. See
+ :ref:`views_which_use_a_renderer` for more information.
+
+ If the ``view`` argument is not provided, this argument has
+ no effect.
+
+ This argument can also be spelled as ``renderer``.
+
+ view_request_type
+
+ A reference to an :term:`interface` representing a
+ :term:`request type`. If this argument is not specified,
+ any request type will be considered a match for the view
+ associated with this route.
+
+ If the ``view`` argument is not provided, this argument has
+ no effect.
+
+ This argument can also be spelled as ``request_type``.
+
+ view_containment
+
+ This a reference to a Python object representing the class
+ that a graph traversal parent object of the :term:`context`
+ must be an instance of (or :term:`interface` that a parent
+ object must provide) in order for this view to be found and
+ called. Your models must be "location-aware" to use this feature.
+ See :ref:`location_aware` for more information about
+ location-awareness.
+
+ If the ``view`` argument is not provided, this argument has no
+ effect.
+
+ view_attr
+
+ The view machinery defaults to using the ``__call__`` method
+ of the view callable (or the function itself, if the view
+ callable is a function) to obtain a response dictionary.
+ The ``attr`` value allows you to vary the method attribute
+ used to obtain the response. For example, if your view was
+ a class, and the class has a method named ``index`` and you
+ wanted to use this method instead of the class' ``__call__``
+ method to return the response, you'd say ``attr="index"`` in
+ the view configuration for the view. This is
+ most useful when the view definition is a class.
+
+ If the ``view`` argument is not provided, this argument has no
+ effect.
+
+ """
# these are route predicates; if they do not match, the next route
# in the routelist will be tried
_, predicates = _make_predicates(xhr=xhr,
@@ -486,14 +893,28 @@ class Configurator(object):
def add_renderer(self, name, renderer, _info=u''):
""" Add a :mod:`repoze.bfg` :term:`renderer` factory to the current
- configuration state."""
+ configuration state.
+
+ The ``name`` argument is the renderer name.
+
+ The ``renderer`` argument is Python reference to an
+ implementation of a :term:`renderer`.
+ """
iface = IRendererFactory
self.registry.registerUtility(renderer, iface, name=name, info=_info)
def override_resource(self, to_override, override_with,
_info=u'', _override=None,):
""" Add a :mod:`repoze.bfg` resource override to the current
- configuration state. See :ref:`resources_chapter` for more
+ configuration state.
+
+ ``to_override`` is a :term:`resource specification` to the
+ resource being overridden.
+
+ ``override_with`` is a :term:`resource specification` to the
+ resource that is performing the override.
+
+ See :ref:`resources_chapter` for more
information about resource overrides."""
if to_override == override_with:
raise ConfigurationError('You cannot override a resource with '
@@ -532,17 +953,66 @@ class Configurator(object):
def set_forbidden_view(self, *arg, **kw):
""" Add a default forbidden view to the current configuration
- state."""
+ state.
+
+ The ``view`` argument should be a :term:`view callable`.
+
+ The ``attr`` argument should be the attribute of the view
+ callable used to retrieve the response (see the ``add_view``
+ method's ``attr`` argument for a description).
+
+ The ``renderer`` argument should be the name of (or path to) a
+ :term:`renderer` used to generate a response for this view
+ (see the ``add_view`` method's ``renderer`` argument for a
+ description).
+
+ The ``wrapper`` argument should be the name of another view
+ which will wrap this view when rendered (see the ``add_view``
+ method's ``wrapper`` argument for a description).
+
+ See :ref:`changing_the_forbidden_view` for more
+ information."""
return self._system_view(IForbiddenView, *arg, **kw)
def set_notfound_view(self, *arg, **kw):
""" Add a default not found view to the current configuration
- state."""
+ state.
+
+ The ``view`` argument should be a :term:`view callable`.
+
+ The ``attr`` argument should be the attribute of the view
+ callable used to retrieve the response (see the ``add_view``
+ method's ``attr`` argument for a description).
+
+ The ``renderer`` argument should be the name of (or path to) a
+ :term:`renderer` used to generate a response for this view
+ (see the ``add_view`` method's ``renderer`` argument for a
+ description).
+
+ The ``wrapper`` argument should be the name of another view
+ which will wrap this view when rendered (see the ``add_view``
+ method's ``wrapper`` argument for a description).
+
+ See :ref:`changing_the_notfound_view` for more
+ information.
+ """
return self._system_view(INotFoundView, *arg, **kw)
def add_static_view(self, name, path, cache_max_age=3600, _info=u''):
- """ Add a static view to the current configuration state."""
+ """ Add a view used to render static resources to the current
+ configuration state.
+
+ The ``name`` argument is a string representing :term:`view
+ name` of the view which is registered.
+
+ The ``path`` argument is the path on disk where the static
+ files reside. This can be an absolute path, a
+ package-relative path, or a :term:`resource specification`.
+
+ See :ref:`static_resources_section` for more information (the
+ ZCML directive just calls this method).
+ """
spec = self._make_spec(path)
view = static(spec, cache_max_age=cache_max_age)
self.add_route(name, "%s*subpath" % name, view=view,