Steve Piercy
2018-04-12 cb8637768565ec20b052b6621b12dd5cb8c659eb
commit | author | age
c151ad 1 from zope.deprecation import deprecated
MM 2
0c1c39 3 from zope.interface import (
CM 4     Attribute,
5     Interface,
6     )
eca67a 7
bc37a5 8 from pyramid.compat import PY2
475532 9
4aa22c 10 # public API interfaces
CM 11
8f45be 12 class IContextFound(Interface):
fd5ae9 13     """ An event type that is emitted after :app:`Pyramid` finds a
8f45be 14     :term:`context` object but before it calls any view code.  See the
c81aad 15     documentation attached to :class:`pyramid.events.ContextFound`
8f45be 16     for more information.
CM 17
012b97 18     .. note::
M 19
20        For backwards compatibility with versions of
fd5ae9 21        :app:`Pyramid` before 1.0, this event interface can also be
c81aad 22        imported as :class:`pyramid.interfaces.IAfterTraversal`.
8f45be 23     """
4aa22c 24     request = Attribute('The request object')
8f45be 25
CM 26 IAfterTraversal = IContextFound
4aa22c 27
d4f5a8 28 class IBeforeTraversal(Interface):
499b78 29     """
4112d6 30     An event type that is emitted after :app:`Pyramid` attempted to find a
BJR 31     route but before it calls any traversal or view code. See the documentation
499b78 32     attached to :class:`pyramid.events.Routefound` for more information.
DS 33     """
34     request = Attribute('The request object')
35
4aa22c 36 class INewRequest(Interface):
fd5ae9 37     """ An event type that is emitted whenever :app:`Pyramid`
8f45be 38     begins to process a new request.  See the documentation attached
c81aad 39     to :class:`pyramid.events.NewRequest` for more information."""
4aa22c 40     request = Attribute('The request object')
012b97 41
4aa22c 42 class INewResponse(Interface):
fd5ae9 43     """ An event type that is emitted whenever any :app:`Pyramid`
8f45be 44     view returns a response. See the
c81aad 45     documentation attached to :class:`pyramid.events.NewResponse`
8f45be 46     for more information."""
eb7ea4 47     request = Attribute('The request object')
4aa22c 48     response = Attribute('The response object')
CM 49
8f45be 50 class IApplicationCreated(Interface):
c6895b 51     """ Event issued when the
aff443 52     :meth:`pyramid.config.Configurator.make_wsgi_app` method
8f45be 53     is called.  See the documentation attached to
c81aad 54     :class:`pyramid.events.ApplicationCreated` for more
8f45be 55     information.
CM 56
012b97 57     .. note::
M 58
59        For backwards compatibility with :app:`Pyramid`
c81aad 60        versions before 1.0, this interface can also be imported as
CM 61        :class:`pyramid.interfaces.IWSGIApplicationCreatedEvent`.
8f45be 62     """
e6c2d2 63     app = Attribute("Created application")
239a93 64
CM 65 IWSGIApplicationCreatedEvent = IApplicationCreated # b /c
4aa22c 66
99edc5 67 class IResponse(Interface):
55241c 68     """ Represents a WSGI response using the WebOb response interface.
TL 69     Some attribute and method documentation of this interface references
70     :rfc:`2616`.
51fb07 71
CM 72     This interface is most famously implemented by
73     :class:`pyramid.response.Response` and the HTTP exception classes in
74     :mod:`pyramid.httpexceptions`."""
75
76     RequestClass = Attribute(
77         """ Alias for :class:`pyramid.request.Request` """)
99edc5 78
CM 79     def __call__(environ, start_response):
51fb07 80         """ :term:`WSGI` call interface, should call the start_response
CM 81         callback and should return an iterable"""
82
83     accept_ranges = Attribute(
84         """Gets and sets and deletes the Accept-Ranges header. For more
85         information on Accept-Ranges see RFC 2616, section 14.5""")
86
87     age = Attribute(
88         """Gets and sets and deletes the Age header. Converts using int.
89         For more information on Age see RFC 2616, section 14.6.""")
90
91     allow = Attribute(
92         """Gets and sets and deletes the Allow header. Converts using
93         list. For more information on Allow see RFC 2616, Section 14.7.""")
94
95     app_iter = Attribute(
96         """Returns the app_iter of the response.
97
98         If body was set, this will create an app_iter from that body
99         (a single-item list)""")
100
101     def app_iter_range(start, stop):
102         """ Return a new app_iter built from the response app_iter that
103         serves up only the given start:stop range. """
104
105     body = Attribute(
106         """The body of the response, as a str. This will read in the entire
107         app_iter if necessary.""")
108
109     body_file = Attribute(
110         """A file-like object that can be used to write to the body. If you
111         passed in a list app_iter, that app_iter will be modified by writes.""")
112
113     cache_control = Attribute(
114         """Get/set/modify the Cache-Control header (RFC 2616 section 14.9)""")
115
116     cache_expires = Attribute(
117         """ Get/set the Cache-Control and Expires headers. This sets the
118             response to expire in the number of seconds passed when set. """)
119
120     charset = Attribute(
121         """Get/set the charset (in the Content-Type)""")
122
123     def conditional_response_app(environ, start_response):
124         """ Like the normal __call__ interface, but checks conditional
125         headers:
126
127         - If-Modified-Since (304 Not Modified; only on GET, HEAD)
128
129         - If-None-Match (304 Not Modified; only on GET, HEAD)
130
131         - Range (406 Partial Content; only on GET, HEAD)"""
132
133     content_disposition = Attribute(
134         """Gets and sets and deletes the Content-Disposition header.
135         For more information on Content-Disposition see RFC 2616 section
136         19.5.1.""")
137
138     content_encoding = Attribute(
139         """Gets and sets and deletes the Content-Encoding header.  For more
140         information about Content-Encoding see RFC 2616 section 14.11.""")
141
142     content_language = Attribute(
143         """Gets and sets and deletes the Content-Language header. Converts
144         using list.  For more information about Content-Language see RFC 2616
145         section 14.12.""")
146
147     content_length = Attribute(
148         """Gets and sets and deletes the Content-Length header. For more
149         information on Content-Length see RFC 2616 section 14.17.
150         Converts using int. """)
151
152     content_location = Attribute(
153         """Gets and sets and deletes the Content-Location header. For more
154         information on Content-Location see RFC 2616 section 14.14.""")
155
156     content_md5 = Attribute(
157         """Gets and sets and deletes the Content-MD5 header. For more
158         information on Content-MD5 see RFC 2616 section 14.14.""")
159
25c64c 160     content_range = Attribute(
51fb07 161         """Gets and sets and deletes the Content-Range header. For more
CM 162         information on Content-Range see section 14.16. Converts using
163         ContentRange object.""")
164
165     content_type = Attribute(
166         """Get/set the Content-Type header (or None), without the charset
167         or any parameters. If you include parameters (or ; at all) when
168         setting the content_type, any existing parameters will be deleted;
169         otherwise they will be preserved.""")
170
171     content_type_params = Attribute(
012b97 172         """A dictionary of all the parameters in the content type.  This is
51fb07 173         not a view, set to change, modifications of the dict would not
CM 174         be applied otherwise.""")
175
176     def copy():
177         """ Makes a copy of the response and returns the copy. """
178
179     date = Attribute(
180         """Gets and sets and deletes the Date header. For more information on
181         Date see RFC 2616 section 14.18. Converts using HTTP date.""")
182
80acf2 183     def delete_cookie(name, path='/', domain=None):
51fb07 184         """ Delete a cookie from the client. Note that path and domain must
CM 185         match how the cookie was originally set.  This sets the cookie to the
186         empty string, and max_age=0 so that it should expire immediately. """
187
188     def encode_content(encoding='gzip', lazy=False):
189         """ Encode the content with the given encoding (only gzip and
190         identity are supported)."""
191
192     environ = Attribute(
193         """Get/set the request environ associated with this response,
194         if any.""")
195
196     etag = Attribute(
197         """ Gets and sets and deletes the ETag header. For more information
198         on ETag see RFC 2616 section 14.19. Converts using Entity tag.""")
199
200     expires = Attribute(
201         """ Gets and sets and deletes the Expires header. For more
202         information on Expires see RFC 2616 section 14.21. Converts using
203         HTTP date.""")
204
205     headerlist = Attribute(
206         """ The list of response headers. """)
207
208     headers = Attribute(
209         """ The headers in a dictionary-like object """)
210
211     last_modified = Attribute(
212         """ Gets and sets and deletes the Last-Modified header. For more
213         information on Last-Modified see RFC 2616 section 14.29. Converts
214         using HTTP date.""")
215
216     location = Attribute(
217         """ Gets and sets and deletes the Location header. For more
218         information on Location see RFC 2616 section 14.30.""")
219
220     def md5_etag(body=None, set_content_md5=False):
221         """ Generate an etag for the response object using an MD5 hash of the
222         body (the body parameter, or self.body if not given).  Sets self.etag.
223         If set_content_md5 is True sets self.content_md5 as well """
224
225     def merge_cookies(resp):
226         """ Merge the cookies that were set on this response with the given
227         resp object (which can be any WSGI application).  If the resp is a
228         webob.Response object, then the other object will be modified
229         in-place. """
230
231     pragma = Attribute(
232         """ Gets and sets and deletes the Pragma header. For more information
233         on Pragma see RFC 2616 section 14.32. """)
234
235     request = Attribute(
236         """ Return the request associated with this response if any. """)
237
238     retry_after = Attribute(
239         """ Gets and sets and deletes the Retry-After header. For more
240         information on Retry-After see RFC 2616 section 14.37. Converts
241         using HTTP date or delta seconds.""")
242
243     server = Attribute(
244         """ Gets and sets and deletes the Server header. For more information
245         on Server see RFC216 section 14.38. """)
246
80acf2 247     def set_cookie(name, value='', max_age=None, path='/', domain=None,
51fb07 248                    secure=False, httponly=False, comment=None, expires=None,
CM 249                    overwrite=False):
250         """ Set (add) a cookie for the response """
251
252     status = Attribute(
253         """ The status string. """)
254
255     status_int = Attribute(
256         """ The status as an integer """)
257
258     unicode_body = Attribute(
259         """ Get/set the unicode value of the body (using the charset of
260         the Content-Type)""")
261
80acf2 262     def unset_cookie(name, strict=True):
51fb07 263         """ Unset a cookie with the given name (remove it from the
CM 264         response)."""
265
266     vary = Attribute(
267         """Gets and sets and deletes the Vary header. For more information
268         on Vary see section 14.44. Converts using list.""")
269
270     www_authenticate = Attribute(
271         """ Gets and sets and deletes the WWW-Authenticate header. For more
272         information on WWW-Authenticate see RFC 2616 section 14.47. Converts
273         using 'parse_auth' and 'serialize_auth'. """)
d96ff9 274
CM 275 class IException(Interface): # not an API
276     """ An interface representing a generic exception """
277
278 class IExceptionResponse(IException, IResponse):
a7e625 279     """ An interface representing a WSGI response which is also an exception
CM 280     object.  Register an exception view using this interface as a ``context``
281     to apply the registered view for all exception types raised by
282     :app:`Pyramid` internally (any exception that inherits from
283     :class:`pyramid.response.Response`, including
99edc5 284     :class:`pyramid.httpexceptions.HTTPNotFound` and
CM 285     :class:`pyramid.httpexceptions.HTTPForbidden`)."""
85093d 286     def prepare(environ):
CM 287         """ Prepares the response for being called as a WSGI application """
d96ff9 288
5c52da 289 class IDict(Interface):
CM 290     # Documentation-only interface
291
292     def __contains__(k):
293         """ Return ``True`` if key ``k`` exists in the dictionary."""
294
295     def __setitem__(k, value):
296         """ Set a key/value pair into the dictionary"""
012b97 297
5c52da 298     def __delitem__(k):
CM 299         """ Delete an item from the dictionary which is passed to the
300         renderer as the renderer globals dictionary."""
012b97 301
5c52da 302     def __getitem__(k):
CM 303         """ Return the value for key ``k`` from the dictionary or raise a
304         KeyError if the key doesn't exist"""
305
306     def __iter__():
307         """ Return an iterator over the keys of this dictionary """
012b97 308
5c52da 309     def get(k, default=None):
CM 310         """ Return the value for key ``k`` from the renderer dictionary, or
311         the default if no such value exists."""
312
313     def items():
314         """ Return a list of [(k,v)] pairs from the dictionary """
315
316     def keys():
317         """ Return a list of keys from the dictionary """
318
319     def values():
320         """ Return a list of values from the dictionary """
321
bc37a5 322     if PY2:
475532 323
CM 324         def iterkeys():
325             """ Return an iterator of keys from the dictionary """
326
327         def iteritems():
328             """ Return an iterator of (k,v) pairs from the dictionary """
329
330         def itervalues():
331             """ Return an iterator of values from the dictionary """
332
333         has_key = __contains__
5c52da 334
CM 335     def pop(k, default=None):
336         """ Pop the key k from the dictionary and return its value.  If k
337         doesn't exist, and default is provided, return the default.  If k
338         doesn't exist and default is not provided, raise a KeyError."""
339
340     def popitem():
341         """ Pop the item with key k from the dictionary and return it as a
342         two-tuple (k, v).  If k doesn't exist, raise a KeyError."""
343
344     def setdefault(k, default=None):
345         """ Return the existing value for key ``k`` in the dictionary.  If no
346          value with ``k`` exists in the dictionary, set the ``default``
347          value into the dictionary under the k name passed.  If a value already
348          existed in the dictionary, return it.  If a value did not exist in
349          the dictionary, return the default"""
012b97 350
5c52da 351     def update(d):
CM 352         """ Update the renderer dictionary with another dictionary ``d``."""
353
354     def clear():
355         """ Clear all values from the dictionary """
356
357 class IBeforeRender(IDict):
a76e99 358     """
7709b1 359     Subscribers to this event may introspect and modify the set of
a76e99 360     :term:`renderer globals` before they are passed to a :term:`renderer`.
5c52da 361     The event object itself provides a dictionary-like interface for adding
CM 362     and removing :term:`renderer globals`.  The keys and values of the
363     dictionary are those globals.  For example::
012b97 364
a76e99 365       from repoze.events import subscriber
CM 366       from pyramid.interfaces import IBeforeRender
367
368       @subscriber(IBeforeRender)
369       def add_global(event):
370           event['mykey'] = 'foo'
371
2033ee 372     .. seealso::
SP 373
374         See also :ref:`beforerender_event`.
a76e99 375     """
9a66aa 376     rendering_val = Attribute('The value returned by a view or passed to a '
CM 377                               '``render`` method for this rendering. '
57144e 378                               'This feature is new in Pyramid 1.2.')
9a66aa 379
b04ae5 380 class IRendererInfo(Interface):
MM 381     """ An object implementing this interface is passed to every
382     :term:`renderer factory` constructor as its only argument (conventionally
383     named ``info``)"""
384     name = Attribute('The value passed by the user as the renderer name')
385     package = Attribute('The "current package" when the renderer '
386                         'configuration statement was found')
387     type = Attribute('The renderer type name')
388     registry = Attribute('The "current" application registry when the '
389                          'renderer was created')
390     settings = Attribute('The deployment settings dictionary related '
391                          'to the current application')
392
ec4691 393     def clone():
MM 394         """ Return a shallow copy that does not share any mutable state."""
395
b04ae5 396 class IRendererFactory(Interface):
MM 397     def __call__(info):
398         """ Return an object that implements
399         :class:`pyramid.interfaces.IRenderer`. ``info`` is an
400         object that implements :class:`pyramid.interfaces.IRendererInfo`.
401         """
402
e26903 403 class IRenderer(Interface):
CM 404     def __call__(value, system):
b04ae5 405         """ Call the renderer with the result of the
e26903 406         view (``value``) passed in and return a result (a string or
CM 407         unicode object useful as a response body).  Values computed by
408         the system are passed by the system in the ``system``
409         parameter, which is a dictionary.  Keys in the dictionary
410         include: ``view`` (the view callable that returned the value),
411         ``renderer_name`` (the template name or simple name of the
412         renderer), ``context`` (the context object passed to the
413         view), and ``request`` (the request object passed to the
414         view)."""
415
416 class ITemplateRenderer(IRenderer):
417     def implementation():
418         """ Return the object that the underlying templating system
419         uses to render the template; it is typically a callable that
420         accepts arbitrary keyword arguments and returns a string or
421         unicode object """
b04ae5 422
MM 423 deprecated(
424     'ITemplateRenderer',
425     'As of Pyramid 1.5 the, "pyramid.interfaces.ITemplateRenderer" interface '
426     'is scheduled to be removed. It was used by the Mako and Chameleon '
c151ad 427     'renderers which have been split into their own packages.'
b04ae5 428     )
e26903 429
8739f5 430 class IViewMapper(Interface):
CM 431     def __call__(self, object):
432         """ Provided with an arbitrary object (a function, class, or
433         instance), returns a callable with the call signature ``(context,
434         request)``.  The callable returned should itself return a Response
435         object.  An IViewMapper is returned by
436         :class:`pyramid.interfaces.IViewMapperFactory`."""
437
438 class IViewMapperFactory(Interface):
439     def __call__(self, **kw):
440         """
441         Return an object which implements
442         :class:`pyramid.interfaces.IViewMapper`.  ``kw`` will be a dictionary
443         containing view-specific arguments, such as ``permission``,
444         ``predicates``, ``attr``, ``renderer``, and other items.  An
445         IViewMapperFactory is used by
446         :meth:`pyramid.config.Configurator.add_view` to provide a plugpoint
447         to extension developers who want to modify potential view callable
448         invocation signatures and response values.
449         """
450
a9fb52 451 class IAuthenticationPolicy(Interface):
c81aad 452     """ An object representing a Pyramid authentication policy. """
fe83c6 453
4aa22c 454     def authenticated_userid(request):
fe83c6 455         """ Return the authenticated :term:`userid` or ``None`` if
MM 456         no authenticated userid can be found. This method of the
457         policy should ensure that a record exists in whatever
458         persistent store is used related to the user (the user
459         should not have been deleted); if a record associated with
460         the current id does not exist in a persistent store, it
461         should return ``None``.
462
463         """
2526d8 464
CM 465     def unauthenticated_userid(request):
fe83c6 466         """ Return the *unauthenticated* userid.  This method
MM 467         performs the same duty as ``authenticated_userid`` but is
468         permitted to return the userid based only on data present
469         in the request; it needn't (and shouldn't) check any
470         persistent store to ensure that the user record related to
471         the request userid exists.
472
473         This method is intended primarily a helper to assist the
474         ``authenticated_userid`` method in pulling credentials out
475         of the request data, abstracting away the specific headers,
476         query strings, etc that are used to authenticate the request.
477
478         """
4aa22c 479
CM 480     def effective_principals(request):
481         """ Return a sequence representing the effective principals
fe83c6 482         typically including the :term:`userid` and any groups belonged
MM 483         to by the current user, always including 'system' groups such
484         as ``pyramid.security.Everyone`` and
485         ``pyramid.security.Authenticated``.
486
487         """
4aa22c 488
c7afe4 489     def remember(request, userid, **kw):
4aa22c 490         """ Return a set of headers suitable for 'remembering' the
fe83c6 491         :term:`userid` named ``userid`` when set in a response.  An
MM 492         individual authentication policy and its consumers can
c62f7d 493         decide on the composition and meaning of ``**kw``.
fe83c6 494
MM 495         """
012b97 496
4aa22c 497     def forget(request):
CM 498         """ Return a set of headers suitable for 'forgetting' the
fe83c6 499         current user on subsequent requests.
MM 500
501         """
4aa22c 502
CM 503 class IAuthorizationPolicy(Interface):
c81aad 504     """ An object representing a Pyramid authorization policy. """
4aa22c 505     def permits(context, principals, permission):
57cc86 506         """ Return ``True`` if any of the ``principals`` is allowed the
CM 507         ``permission`` in the current ``context``, else return ``False``
508         """
012b97 509
4aa22c 510     def principals_allowed_by_permission(context, permission):
57cc86 511         """ Return a set of principal identifiers allowed by the
CM 512         ``permission`` in ``context``.  This behavior is optional; if you
513         choose to not implement it you should define this method as
514         something which raises a ``NotImplementedError``.  This method
515         will only be called when the
516         ``pyramid.security.principals_allowed_by_permission`` API is
517         used."""
4aa22c 518
5c52da 519 class IMultiDict(IDict): # docs-only interface
2a1c3f 520     """
CM 521     An ordered dictionary that can have multiple values for each key. A
b9a6b3 522     multidict adds the methods ``getall``, ``getone``, ``mixed``, ``extend``,
2a1c3f 523     ``add``, and ``dict_of_lists`` to the normal dictionary interface.  A
CM 524     multidict data structure is used as ``request.POST``, ``request.GET``,
525     and ``request.params`` within an :app:`Pyramid` application.
526     """
527
528     def add(key, value):
529         """ Add the key and value, not overwriting any previous value. """
530
531     def dict_of_lists():
532         """
533         Returns a dictionary where each key is associated with a list of
534         values.
535         """
536
537     def extend(other=None, **kwargs):
538         """ Add a set of keys and values, not overwriting any previous
539         values.  The ``other`` structure may be a list of two-tuples or a
540         dictionary.  If ``**kwargs`` is passed, its value *will* overwrite
541         existing values."""
542
543     def getall(key):
544         """ Return a list of all values matching the key (may be an empty
545         list) """
546
547     def getone(key):
548         """ Get one value matching the key, raising a KeyError if multiple
549         values were found. """
550
551     def mixed():
552         """ Returns a dictionary where the values are either single values,
553         or a list of values when a key/value appears more than once in this
554         dictionary. This is similar to the kind of dictionary often used to
555         represent the variables in a web request. """
d2973d 556
CM 557 # internal interfaces
558
559 class IRequest(Interface):
560     """ Request type interface attached to all request objects """
561
b4843b 562 class ITweens(Interface):
af2323 563     """ Marker interface for utility registration representing the ordered
b4843b 564     set of a configuration's tween factories"""
af2323 565
CM 566 class IRequestHandler(Interface):
567     """ """
568     def __call__(self, request):
0d4963 569         """ Must return a tuple of IReqest, IResponse or raise an exception.
CM 570         The ``request`` argument will be an instance of an object that
571         provides IRequest."""
af2323 572
012b97 573 IRequest.combined = IRequest # for exception view lookups
d2973d 574
d7f34b 575 class IRequestExtensions(Interface):
MM 576     """ Marker interface for storing request extensions (properties and
577     methods) which will be added to the request object."""
578     descriptors = Attribute(
579         """A list of descriptors that will be added to each request.""")
580     methods = Attribute(
581         """A list of methods to be added to each request.""")
74d503 582
d2973d 583 class IRouteRequest(Interface):
CM 584     """ *internal only* interface used as in a utility lookup to find
585     route-specific interfaces.  Not an API."""
586
b29429 587 class IStaticURLInfo(Interface):
3e2f12 588     """ A policy for generating URLs to static assets """
cda7f6 589     def add(config, name, spec, **extra):
b29429 590         """ Add a new static info registration """
CM 591
592     def generate(path, request, **kw):
593         """ Generate a URL for the given path """
a0b40c 594
6e29b4 595     def add_cache_buster(config, spec, cache_buster):
MM 596         """ Add a new cache buster to a particular set of assets """
597
c8cf22 598 class IResponseFactory(Interface):
da5f5f 599     """ A utility which generates a response """
MM 600     def __call__(request):
601         """ Return a response object implementing IResponse,
602         e.g. :class:`pyramid.response.Response`). It should handle the
603         case when ``request`` is ``None``."""
7de404 604
81a833 605 class IRequestFactory(Interface):
CM 606     """ A utility which generates a request """
607     def __call__(environ):
04cc91 608         """ Return an instance of ``pyramid.request.Request``"""
81a833 609
CM 610     def blank(path):
611         """ Return an empty request object (see
8c6a4c 612         :meth:`pyramid.request.Request.blank`)"""
81a833 613
ff1213 614 class IViewClassifier(Interface):
CM 615     """ *Internal only* marker interface for views."""
616
617 class IExceptionViewClassifier(Interface):
618     """ *Internal only* marker interface for exception views."""
619
7de404 620 class IView(Interface):
CM 621     def __call__(context, request):
99edc5 622         """ Must return an object that implements IResponse. """
d66bfb 623
CM 624 class ISecuredView(IView):
573184 625     """ *Internal only* interface.  Not an API. """
d66bfb 626     def __call_permissive__(context, request):
CM 627         """ Guaranteed-permissive version of __call__ """
628
629     def __permitted__(context, request):
630         """ Return True if view execution will be permitted using the
631         context and request, False otherwise"""
632
633 class IMultiView(ISecuredView):
634     """ *internal only*.  A multiview is a secured view that is a
635     collection of other views.  Each of the views is associated with
636     zero or more predicates.  Not an API."""
ff1213 637     def add(view, predicates, order, accept=None, phash=None):
d66bfb 638         """ Add a view to the multiview. """
5ed24b 639
358dc2 640 class IRootFactory(Interface):
8b1f6e 641     def __call__(request):
CM 642         """ Return a root object based on the request """
dfc2b6 643
CM 644 class IDefaultRootFactory(Interface):
8b1f6e 645     def __call__(request):
dfc2b6 646         """ Return the *default* root object for an application """
612d74 647
4df575 648 class ITraverser(Interface):
8b1f6e 649     def __call__(request):
80a25e 650         """ Return a dictionary with (at least) the keys ``root``,
CM 651         ``context``, ``view_name``, ``subpath``, ``traversed``,
652         ``virtual_root``, and ``virtual_root_path``.  These values are
f426e5 653         typically the result of an object graph traversal.  ``root`` is the
CM 654         physical root object, ``context`` will be a model object,
655         ``view_name`` will be the view name used (a Unicode name),
656         ``subpath`` will be a sequence of Unicode names that followed the
657         view name but were not traversed, ``traversed`` will be a sequence of
658         Unicode names that were traversed (including the virtual root path,
659         if any) ``virtual_root`` will be a model object representing the
660         virtual root (or the physical root if traversal was not performed),
661         and ``virtual_root_path`` will be a sequence representing the virtual
662         root path (a sequence of Unicode names) or ``None`` if traversal was
663         not performed.
80a25e 664
f426e5 665         Extra keys for special purpose functionality can be returned as
80a25e 666         necessary.
CM 667
668         All values returned in the dictionary will be made available
f426e5 669         as attributes of the ``request`` object by the :term:`router`.
80a25e 670         """
93a4f5 671
517d03 672 ITraverserFactory = ITraverser # b / c for 1.0 code
8f8869 673
2466f6 674 class IViewPermission(Interface):
d7e43b 675     def __call__(context, request):
b04ae5 676         """ Return True if the permission allows, return False if it denies.
MM 677         """
2466f6 678
eba6f8 679 class IRouter(Interface):
b04ae5 680     """ WSGI application which routes requests to 'view' code based on
eba6f8 681     a view registry."""
9dd823 682     registry = Attribute(
eba6f8 683         """Component architecture registry local to this application.""")
012b97 684
0e21c2 685 class ISettings(Interface):
c81aad 686     """ Runtime settings utility for pyramid; represents the
8b1f6e 687     deployment settings for the application.  Implements a mapping
CM 688     interface."""
012b97 689
c81aad 690 # this interface, even if it becomes unused within Pyramid, is
cba2e1 691 # imported by other packages (such as traversalwrapper)
cbdc36 692 class ILocation(Interface):
CM 693     """Objects that have a structural location"""
694     __parent__ = Attribute("The parent in the location hierarchy")
695     __name__ = Attribute("The name within the parent")
696
bd39b1 697 class IDebugLogger(Interface):
47b4d3 698     """ Interface representing a PEP 282 logger """
62267e 699
bd39b1 700 ILogger = IDebugLogger # b/c
CM 701
70f1cd 702 class IRoutePregenerator(Interface):
CM 703     def __call__(request, elements, kw):
fb90f0 704
CM 705         """ A pregenerator is a function associated by a developer with a
706         :term:`route`. The pregenerator for a route is called by
707         :meth:`pyramid.request.Request.route_url` in order to adjust the set
708         of arguments passed to it by the user for special purposes, such as
709         Pylons 'subdomain' support.  It will influence the URL returned by
710         ``route_url``.
70f1cd 711
CM 712         A pregenerator should return a two-tuple of ``(elements, kw)``
713         after examining the originals passed to this function, which
714         are the arguments ``(request, elements, kw)``.  The simplest
715         pregenerator is::
716
717             def pregenerator(request, elements, kw):
718                 return elements, kw
719
720         You can employ a pregenerator by passing a ``pregenerator``
721         argument to the
aff443 722         :meth:`pyramid.config.Configurator.add_route`
70f1cd 723         function.
CM 724
725         """
726
74409d 727 class IRoute(Interface):
CM 728     """ Interface representing the type of object returned from
729     ``IRoutesMapper.get_route``"""
730     name = Attribute('The route name')
731     pattern = Attribute('The route pattern')
732     factory = Attribute(
fd5ae9 733         'The :term:`root factory` used by the :app:`Pyramid` router '
74409d 734         'when this route matches (or ``None``)')
CM 735     predicates = Attribute(
736         'A sequence of :term:`route predicate` objects used to '
c337a8 737         'determine if a request matches this route or not after '
74409d 738         'basic pattern matching has been completed.')
70f1cd 739     pregenerator = Attribute('This attribute should either be ``None`` or '
CM 740                              'a callable object implementing the '
741                              '``IRoutePregenerator`` interface')
0445bf 742
74409d 743     def match(path):
CM 744         """
745         If the ``path`` passed to this function can be matched by the
746         ``pattern`` of this route, return a dictionary (the
747         'matchdict'), which will contain keys representing the dynamic
748         segment markers in the pattern mapped to values extracted from
749         the provided ``path``.
750
751         If the ``path`` passed to this function cannot be matched by
752         the ``pattern`` of this route, return ``None``.
753         """
754     def generate(kw):
755         """
756         Generate a URL based on filling in the dynamic segment markers
757         in the pattern using the ``kw`` dictionary provided.
758         """
759
62267e 760 class IRoutesMapper(Interface):
CM 761     """ Interface representing a Routes ``Mapper`` object """
8b1f6e 762     def get_routes():
e725cf 763         """ Return a sequence of Route objects registered in the mapper.
CM 764         Static routes will not be returned in this sequence."""
8b1f6e 765
74409d 766     def has_routes():
CM 767         """ Returns ``True`` if any route has been registered. """
768
769     def get_route(name):
770         """ Returns an ``IRoute`` object if a route with the name ``name``
771         was registered, otherwise return ``None``."""
772
90ed75 773     def connect(name, pattern, factory=None, predicates=(), pregenerator=None,
CM 774                 static=True):
8b1f6e 775         """ Add a new route. """
CM 776
777     def generate(name, kw):
778         """ Generate a URL using the route named ``name`` with the
779         keywords implied by kw"""
780
781     def __call__(request):
74409d 782         """ Return a dictionary containing matching information for
CM 783         the request; the ``route`` key of this dictionary will either
784         be a Route object or ``None`` if no route matched; the
51b2f9 785         ``match`` key will be the matchdict or ``None`` if no route
90ed75 786         matched.  Static routes will not be considered for matching.  """
8b1f6e 787
c51896 788 class IResourceURL(Interface):
db0185 789     virtual_path = Attribute(
CM 790         'The virtual url path of the resource as a string.'
791         )
792     physical_path = Attribute(
793         'The physical url path of the resource as a string.'
794         )
795     virtual_path_tuple = Attribute(
796         'The virtual url path of the resource as a tuple.  (New in 1.5)'
797         )
e744e9 798     physical_path_tuple = Attribute(
db0185 799         'The physical url path of the resource as a tuple. (New in 1.5)'
CM 800         )
c51896 801
bea48e 802 class IPEP302Loader(Interface):
TS 803     """ See http://www.python.org/dev/peps/pep-0302/#id30.
804     """
805     def get_data(path):
806         """ Retrieve data for and arbitrary "files" from storage backend.
807
808         Raise IOError for not found.
809
810         Data is returned as bytes.
811         """
812
813     def is_package(fullname):
814         """ Return True if the module specified by 'fullname' is a package.
815         """
816
817     def get_code(fullname):
818         """ Return the code object for the module identified by 'fullname'.
0445bf 819
bea48e 820         Return 'None' if it's a built-in or extension module.
0445bf 821
bea48e 822         If the loader doesn't have the code object but it does have the source
TS 823         code, return the compiled source code.
824
825         Raise ImportError if the module can't be found by the importer at all.
826         """
827
828     def get_source(fullname):
829         """ Return the source code for the module identified by 'fullname'.
0445bf 830
bea48e 831         Return a string, using newline characters for line endings, or None
TS 832         if the source is not available.
0445bf 833
bea48e 834         Raise ImportError if the module can't be found by the importer at all.
TS 835         """
836
837     def get_filename(fullname):
838         """ Return the value of '__file__' if the named module was loaded.
0445bf 839
bea48e 840         If the module is not found, raise ImportError.
TS 841         """
842
843
844 class IPackageOverrides(IPEP302Loader):
2869fc 845     """ Utility for pkg_resources overrides """
CM 846
a7a6d7 847 # VH_ROOT_KEY is an interface; its imported from other packages (e.g.
CM 848 # traversalwrapper)
ff1213 849 VH_ROOT_KEY = 'HTTP_X_VHM_ROOT'
7534ba 850
CM 851 class ILocalizer(Interface):
852     """ Localizer for a specific language """
012b97 853
7534ba 854 class ILocaleNegotiator(Interface):
CM 855     def __call__(request):
856         """ Return a locale name """
857
858 class ITranslationDirectories(Interface):
859     """ A list object representing all known translation directories
860     for an application"""
d96ff9 861
e25a70 862 class IDefaultPermission(Interface):
CM 863     """ A string object representing the default permission to be used
864     for all view configurations which do not explicitly declare their
865     own."""
968209 866
de3d0c 867 class IDefaultCSRFOptions(Interface):
MM 868     """ An object representing the default CSRF settings to be used for
869     all view configurations which do not explicitly declare their own."""
870     require_csrf = Attribute(
871         'Boolean attribute. If ``True``, then CSRF checks will be enabled by '
872         'default for the view unless overridden.')
873     token = Attribute('The key to be matched in the body of the request.')
874     header = Attribute('The header to be matched with the CSRF token.')
875     safe_methods = Attribute('A set of safe methods that skip CSRF checks.')
17fa5e 876     callback = Attribute('A callback to disable CSRF checks per-request.')
de3d0c 877
968209 878 class ISessionFactory(Interface):
CM 879     """ An interface representing a factory which accepts a request object and
880     returns an ISession object """
881     def __call__(request):
882         """ Return an ISession object """
883
866949 884 class ISession(IDict):
968209 885     """ An interface representing a session (a web session object,
CM 886     usually accessed via ``request.session``.
887
888     Keys and values of a session must be pickleable.
889     """
890
891     # attributes
892
893     created = Attribute('Integer representing Epoch time when created.')
894     new = Attribute('Boolean attribute.  If ``True``, the session is new.')
895
896     # special methods
897
898     def invalidate():
899         """ Invalidate the session.  The action caused by
900         ``invalidate`` is implementation-dependent, but it should have
901         the effect of completely dissociating any data stored in the
902         session with the current request.  It might set response
dd4f73 903         values (such as one which clears a cookie), or it might not.
MM 904
905         An invalidated session may be used after the call to ``invalidate``
906         with the effect that a new session is created to store the data. This
907         enables workflows requiring an entirely new session, such as in the
908         case of changing privilege levels or preventing fixation attacks.
909         """
968209 910
CM 911     def changed():
912         """ Mark the session as changed. A user of a session should
913         call this method after he or she mutates a mutable object that
914         is *a value of the session* (it should not be required after
915         mutating the session itself).  For example, if the user has
916         stored a dictionary in the session under the key ``foo``, and
917         he or she does ``session['foo'] = {}``, ``changed()`` needn't
918         be called.  However, if subsequently he or she does
919         ``session['foo']['a'] = 1``, ``changed()`` must be called for
920         the sessioning machinery to notice the mutation of the
921         internal dictionary."""
922
6f6d36 923     def flash(msg, queue='', allow_duplicate=True):
CM 924         """ Push a flash message onto the end of the flash queue represented
925         by ``queue``.  An alternate flash message queue can used by passing
926         an optional ``queue``, which must be a string.  If
927         ``allow_duplicate`` is false, if the ``msg`` already exists in the
bfb395 928         queue, it will not be re-added."""
4df636 929
6f6d36 930     def pop_flash(queue=''):
CM 931         """ Pop a queue from the flash storage.  The queue is removed from
932         flash storage after this message is called.  The queue is returned;
933         it is a list of flash messages added by
be03f7 934         :meth:`pyramid.interfaces.ISession.flash`"""
6f6d36 935
CM 936     def peek_flash(queue=''):
937         """ Peek at a queue in the flash storage.  The queue remains in
938         flash storage after this message is called.  The queue is returned;
939         it is a list of flash messages added by
be03f7 940         :meth:`pyramid.interfaces.ISession.flash`
319793 941         """
CM 942
ac718c 943     def new_csrf_token():
319793 944         """ Create and set into the session a new, random cross-site request
CM 945         forgery protection token.  Return the token.  It will be a string."""
946
ac718c 947     def get_csrf_token():
14f863 948         """ Return a random cross-site request forgery protection token.  It
CM 949         will be a string.  If a token was previously added to the session via
950         ``new_csrf_token``, that token will be returned.  If no CSRF token
951         was previously set into the session, ``new_csrf_token`` will be
952         called, which will create and set a token, and this token will be
953         returned.
319793 954         """
eb2fee 955
3b5ccb 956 class IIntrospector(Interface):
CM 957     def get(category_name, discriminator, default=None):
958         """ Get the IIntrospectable related to the category_name and the
959         discriminator (or discriminator hash) ``discriminator``.  If it does
8a32e3 960         not exist in the introspector, return the value of ``default`` """
3b5ccb 961
79f34b 962     def get_category(category_name, default=None, sort_key=None):
412b4a 963         """ Get a sequence of dictionaries in the form
CM 964         ``[{'introspectable':IIntrospectable, 'related':[sequence of related
965         IIntrospectables]}, ...]`` where each introspectable is part of the
79f34b 966         category associated with ``category_name`` .
CM 967
968         If the category named ``category_name`` does not exist in the
969         introspector the value passed as ``default`` will be returned.
970
971         If ``sort_key`` is ``None``, the sequence will be returned in the
972         order the introspectables were added to the introspector.  Otherwise,
973         sort_key should be a function that accepts an IIntrospectable and
974         returns a value from it (ala the ``key`` function of Python's
975         ``sorted`` callable)."""
412b4a 976
5e92f3 977     def categories():
CM 978         """ Return a sorted sequence of category names known by
979          this introspector """
980
57a0d7 981     def categorized(sort_key=None):
412b4a 982         """ Get a sequence of tuples in the form ``[(category_name,
CM 983         [{'introspectable':IIntrospectable, 'related':[sequence of related
984         IIntrospectables]}, ...])]`` representing all known
57a0d7 985         introspectables.  If ``sort_key`` is ``None``, each introspectables
412b4a 986         sequence will be returned in the order the introspectables were added
57a0d7 987         to the introspector.  Otherwise, sort_key should be a function that
3b5ccb 988         accepts an IIntrospectable and returns a value from it (ala the
CM 989         ``key`` function of Python's ``sorted`` callable)."""
990
991     def remove(category_name, discriminator):
992         """ Remove the IIntrospectable related to ``category_name`` and
5e92f3 993         ``discriminator`` from the introspector, and fix up any relations
CM 994         that the introspectable participates in. This method will not raise
995         an error if an introspectable related to the category name and
996         discriminator does not exist."""
997
57a9d6 998     def related(intr):
5e92f3 999         """ Return a sequence of IIntrospectables related to the
57a9d6 1000         IIntrospectable ``intr``. Return the empty sequence if no relations
CM 1001         for exist."""
5e92f3 1002
CM 1003     def add(intr):
1004         """ Add the IIntrospectable ``intr`` (use instead of
1005         :meth:`pyramid.interfaces.IIntrospector.add` when you have a custom
1006         IIntrospectable). Replaces any existing introspectable registered
1007         using the same category/discriminator.
1008
1009         This method is not typically called directly, instead it's called
1010         indirectly by :meth:`pyramid.interfaces.IIntrospector.register`"""
3b5ccb 1011
CM 1012     def relate(*pairs):
043ccd 1013         """ Given any number of ``(category_name, discriminator)`` pairs
3b5ccb 1014         passed as positional arguments, relate the associated introspectables
CM 1015         to each other. The introspectable related to each pair must have
1016         already been added via ``.add`` or ``.add_intr``; a :exc:`KeyError`
1017         will result if this is not true.  An error will not be raised if any
5e92f3 1018         pair has already been associated with another.
CM 1019
1020         This method is not typically called directly, instead it's called
1021         indirectly by :meth:`pyramid.interfaces.IIntrospector.register`
1022         """
3b5ccb 1023
CM 1024     def unrelate(*pairs):
043ccd 1025         """ Given any number of ``(category_name, discriminator)`` pairs
3b5ccb 1026         passed as positional arguments, unrelate the associated introspectables
CM 1027         from each other. The introspectable related to each pair must have
1028         already been added via ``.add`` or ``.add_intr``; a :exc:`KeyError`
1029         will result if this is not true.  An error will not be raised if any
5e92f3 1030         pair is not already related to another.
3b5ccb 1031
5e92f3 1032         This method is not typically called directly, instead it's called
CM 1033         indirectly by :meth:`pyramid.interfaces.IIntrospector.register`
1034         """
3b5ccb 1035
CM 1036
1037 class IIntrospectable(Interface):
1038     """ An introspectable object used for configuration introspection.  In
1039     addition to the methods below, objects which implement this interface
1040     must also implement all the methods of Python's
57a0d7 1041     ``collections.MutableMapping`` (the "dictionary interface"), and must be
CM 1042     hashable."""
3b5ccb 1043
5e92f3 1044     title = Attribute('Text title describing this introspectable')
CM 1045     type_name = Attribute('Text type name describing this introspectable')
1046     order = Attribute('integer order in which registered with introspector '
522405 1047                       '(managed by introspector, usually)')
3b5ccb 1048     category_name = Attribute('introspection category name')
CM 1049     discriminator = Attribute('introspectable discriminator (within category) '
1050                               '(must be hashable)')
1051     discriminator_hash = Attribute('an integer hash of the discriminator')
522405 1052     action_info = Attribute('An IActionInfo object representing the caller '
CM 1053                             'that invoked the creation of this introspectable '
1054                             '(usually a sentinel until updated during '
1055                             'self.register)')
3b5ccb 1056
CM 1057     def relate(category_name, discriminator):
5e92f3 1058         """ Indicate an intent to relate this IIntrospectable with another
CM 1059         IIntrospectable (the one associated with the ``category_name`` and
1060         ``discriminator``) during action execution.
3b5ccb 1061         """
CM 1062
8f6b24 1063     def unrelate(category_name, discriminator):
5e92f3 1064         """ Indicate an intent to break the relationship between this
CM 1065         IIntrospectable with another IIntrospectable (the one associated with
1066         the ``category_name`` and ``discriminator``) during action execution.
1067         """
3b5ccb 1068
57a9d6 1069     def register(introspector, action_info):
35ad08 1070         """ Register this IIntrospectable with an introspector.  This method
CM 1071         is invoked during action execution.  Adds the introspectable and its
57a9d6 1072         relations to the introspector.  ``introspector`` should be an object
CM 1073         implementing IIntrospector.  ``action_info`` should be a object
1074         implementing the interface :class:`pyramid.interfaces.IActionInfo`
1075         representing the call that registered this introspectable.
1076         Pseudocode for an implementation of this method:
35ad08 1077
CM 1078         .. code-block:: python
1079
1080             def register(self, introspector, action_info):
1081                 self.action_info = action_info
1082                 introspector.add(self)
1083                 for methodname, category_name, discriminator in self._relations:
1084                     method = getattr(introspector, methodname)
1085                     method((i.category_name, i.discriminator),
1086                            (category_name, discriminator))
1087         """
1088
57a0d7 1089     def __hash__():
CM 1090
1091         """ Introspectables must be hashable.  The typical implementation of
1092         an introsepectable's __hash__ is::
1093
1094           return hash((self.category_name,) + (self.discriminator,))
1095         """
1096
57a9d6 1097 class IActionInfo(Interface):
549cf7 1098     """ Class which provides code introspection capability associated with an
CM 1099     action.  The ParserInfo class used by ZCML implements the same interface."""
1100     file = Attribute(
d2ed7e 1101         'Filename of action-invoking code as a string')
549cf7 1102     line = Attribute(
d2ed7e 1103         'Starting line number in file (as an integer) of action-invoking code.'
CM 1104         'This will be ``None`` if the value could not be determined.')
549cf7 1105
CM 1106     def __str__():
1107         """ Return a representation of the action information (including
1108         source code from file, if possible) """
57a9d6 1109
56df90 1110 class IAssetDescriptor(Interface):
CM 1111     """
1112     Describes an :term:`asset`.
1113     """
1114
1115     def absspec():
1116         """
1117         Returns the absolute asset specification for this asset
1118         (e.g. ``mypackage:templates/foo.pt``).
1119         """
1120
1121     def abspath():
1122         """
1123         Returns an absolute path in the filesystem to the asset.
1124         """
1125
1126     def stream():
1127         """
1128         Returns an input stream for reading asset contents.  Raises an
1129         exception if the asset is a directory or does not exist.
1130         """
1131
1132     def isdir():
1133         """
1134         Returns True if the asset is a directory, otherwise returns False.
1135         """
1136
1137     def listdir():
1138         """
1139         Returns iterable of filenames of directory contents.  Raises an
1140         exception if asset is not a directory.
1141         """
1142
1143     def exists():
1144         """
1145         Returns True if asset exists, otherwise returns False.
1146         """
1147
677216 1148 class IJSONAdapter(Interface):
MM 1149     """
1150     Marker interface for objects that can convert an arbitrary object
1151     into a JSON-serializable primitive.
1152     """
1153
a00621 1154 class IPredicateList(Interface):
CM 1155     """ Interface representing a predicate list """
1156
e4b931 1157 class IViewDeriver(Interface):
0b0f7e 1158     options = Attribute('A list of supported options to be passed to '
e4b931 1159                         ':meth:`pyramid.config.Configurator.add_view`. '
MM 1160                         'This attribute is optional.')
1161
1162     def __call__(view, info):
1163         """
1164         Derive a new view from the supplied view.
1165
1166         View options, package information and registry are available on
1167         ``info``, an instance of :class:`pyramid.interfaces.IViewDeriverInfo`.
1168
1169         The ``view`` is a callable accepting ``(context, request)``.
1170
1171         """
007600 1172
MM 1173 class IViewDeriverInfo(Interface):
1174     """ An object implementing this interface is passed to every
1175     :term:`view deriver` during configuration."""
2160ce 1176     registry = Attribute('The "current" application registry where the '
007600 1177                          'view was created')
2160ce 1178     package = Attribute('The "current package" where the view '
007600 1179                         'configuration statement was found')
MM 1180     settings = Attribute('The deployment settings dictionary related '
1181                          'to the current application')
1182     options = Attribute('The view options passed to the view, including any '
1183                         'default values that were not overriden')
1184     predicates = Attribute('The list of predicates active on the view')
a610d0 1185     original_view = Attribute('The original view object being wrapped')
e8c66a 1186     exception_only = Attribute('The view will only be invoked for exceptions')
007600 1187
e4b931 1188 class IViewDerivers(Interface):
MM 1189     """ Interface for view derivers list """
1190
2a1ca8 1191 class ICacheBuster(Interface):
CR 1192     """
6e29b4 1193     A cache buster modifies the URL generation machinery for
MM 1194     :meth:`~pyramid.request.Request.static_url`. See :ref:`cache_busting`.
6b88bd 1195
CM 1196     .. versionadded:: 1.6
2a1ca8 1197     """
4d19b8 1198     def __call__(request, subpath, kw):
0445bf 1199         """
40c6bf 1200         Modifies a subpath and/or keyword arguments from which a static asset
4d19b8 1201         URL will be computed during URL generation.
0445bf 1202
6e29b4 1203         The ``subpath`` argument is a path of ``/``-delimited segments that
MM 1204         represent the portion of the asset URL which is used to find the asset.
1205         The ``kw`` argument is a dict of keywords that are to be passed
1206         eventually to :meth:`~pyramid.request.Request.static_url` for URL
1207         generation.  The return value should be a two-tuple of
b2fc4a 1208         ``(subpath, kw)`` where ``subpath`` is the relative URL from where the
MM 1209         file is served and ``kw`` is the same input argument. The return value
1210         should be modified to include the cache bust token in the generated
1211         URL.
9d521e 1212
4d19b8 1213         The ``kw`` dictionary contains extra arguments passed to
MM 1214         :meth:`~pyramid.request.Request.static_url` as well as some extra
1215         items that may be usful including:
2a1ca8 1216
4d19b8 1217           - ``pathspec`` is the path specification for the resource
MM 1218             to be cache busted.
1219
1220           - ``rawspec`` is the original location of the file, ignoring
1221             any calls to :meth:`pyramid.config.Configurator.override_asset`.
1222
1223         The ``pathspec`` and ``rawspec`` values are only different in cases
1224         where an asset has been mounted into a virtual location using
1225         :meth:`pyramid.config.Configurator.override_asset`. For example, with
1226         a call to ``request.static_url('myapp:static/foo.png'), the
1227         ``pathspec`` is ``myapp:static/foo.png`` whereas the ``rawspec`` may
1228         be ``themepkg:bar.png``, assuming a call to
b2fc4a 1229         ``config.override_asset('myapp:static/foo.png', 'themepkg:bar.png')``.
0445bf 1230         """
CR 1231
eb2fee 1232 # configuration phases: a lower phase number means the actions associated
CM 1233 # with this phase will be executed earlier than those with later phase
3171fb 1234 # numbers.  The default phase number is 0, FTR.
eb2fee 1235
568a02 1236 PHASE0_CONFIG = -30
eb2fee 1237 PHASE1_CONFIG = -20
CM 1238 PHASE2_CONFIG = -10
568a02 1239 PHASE3_CONFIG = 0