summaryrefslogtreecommitdiff
path: root/repoze/bfg/urldispatch.py
diff options
context:
space:
mode:
authorChris McDonough <chrism@agendaless.com>2009-10-30 18:56:58 +0000
committerChris McDonough <chrism@agendaless.com>2009-10-30 18:56:58 +0000
commit11644e705834ff65cb8963333855a1db6272ae1e (patch)
tree6730225c3c81d52263f37ceac0876b11a57865ae /repoze/bfg/urldispatch.py
parent1b2d8e7326cd1eaa95b3522d985e97642764c7c8 (diff)
downloadpyramid-11644e705834ff65cb8963333855a1db6272ae1e.tar.gz
pyramid-11644e705834ff65cb8963333855a1db6272ae1e.tar.bz2
pyramid-11644e705834ff65cb8963333855a1db6272ae1e.zip
Features
-------- - In previous versions of BFG, the "root factory" (the ``get_root`` callable passed to ``make_app`` or a function pointed to by the ``factory`` attribute of a route) was called with a "bare" WSGI environment. In this version, and going forward, it will be called with a ``request`` object. The request object passed to the factory implements dictionary-like methods in such a way that existing root factory code which expects to be passed an environ will continue to work. Internal -------- - The request implements dictionary-like methods that mutate and query the WSGI environ. This is only for the purpose of backwards compatibility with root factories which expect an ``environ`` rather than a request. - The ``repoze.bfg.request.create_route_request_factory`` function, which returned a request factory was removed in favor of a ``repoze.bfg.request.route_request_interface`` function, which returns an interface. - The ``repoze.bfg.request.Request`` class, which is a subclass of ``webob.Request`` now defines its own ``__setattr__``, ``__getattr__`` and ``__delattr__`` methods, which override the default WebOb behavior. The default WebOb behavior stores attributes of the request in ``self.environ['webob.adhoc_attrs']``, and retrieves them from that dictionary during a ``__getattr__``. This behavior was undesirable for speed and "expectation" reasons. Now attributes of the ``request`` are stored in ``request.__dict__`` (as you otherwise might expect from an object that did not override these methods). - Reverse the order in which the router calls the request factory and the root factory. The request factory is now called first; the resulting request is passed to the root factory. - The ``repoze.bfg.request.request_factory`` function has been removed. Its functionality is no longer required. - The "routes root factory" that wraps the default root factory when there are routes mentioned in the configuration now attaches an interface to the request via ``zope.interface.directlyProvides``. This replaces logic in the (now-gone) ``repoze.bfg.request.request_factory`` function. - The ``route`` and ``view`` ZCML directives now register an interface as a named utility (retrieved from ``repoze.bfg.request.route_request_interface``) rather than a request factory (the previous return value of the now-missing ``repoze.bfg.request.create_route_request_factory``.
Diffstat (limited to 'repoze/bfg/urldispatch.py')
-rw-r--r--repoze/bfg/urldispatch.py32
1 files changed, 31 insertions, 1 deletions
diff --git a/repoze/bfg/urldispatch.py b/repoze/bfg/urldispatch.py
index 14a81062c..4088cef12 100644
--- a/repoze/bfg/urldispatch.py
+++ b/repoze/bfg/urldispatch.py
@@ -1,6 +1,10 @@
import re
from urllib import unquote
+from zope.interface import directlyProvides
+
+from repoze.bfg.interfaces import IRouteRequest
+
from repoze.bfg.traversal import traversal_path
from repoze.bfg.traversal import quote_path_segment
from repoze.bfg.encode import url_quote
@@ -35,7 +39,29 @@ class RoutesRootFactory(object):
def generate(self, name, kw):
return self.routes[name].generate(kw)
- def __call__(self, environ):
+ def __call__(self, request):
+ try:
+ # As of BFG 1.1a9, a root factory is now typically called
+ # with a request object (instead of a WSGI environ, as in
+ # previous versions) by the router. Simultaneously, as of
+ # 1.1a9, the RoutesRootFactory *requires* that the object
+ # passed to it be a request, instead of an environ, as it
+ # uses both the ``registry`` attribute of the request, and
+ # if a route is found, it decorates the object with an
+ # interface using directlyProvides. However, existing app
+ # code "in the wild" calls the root factory explicitly
+ # with a dictionary argument (e.g. a subscriber to
+ # WSGIApplicationCreatedEvent does
+ # ``app.root_factory({})``). It makes no sense for such
+ # code to depend on the side effects of a
+ # RoutesRootFactory, for bw compat purposes we catch the
+ # exception that will be raised when passed a dictionary
+ # and just return the result of the default root factory.
+ environ = request.environ
+ registry = request.registry
+ except AttributeError:
+ return self.default_root_factory(request)
+
try:
path = environ['PATH_INFO']
except KeyError:
@@ -46,6 +72,10 @@ class RoutesRootFactory(object):
environ['wsgiorg.routing_args'] = ((), match)
environ['bfg.routes.route'] = route
environ['bfg.routes.matchdict'] = match
+ request.matchdict = match
+ iface = registry.queryUtility(IRouteRequest, name=route.name)
+ if iface is not None:
+ directlyProvides(request, iface)
factory = route.factory or self.default_root_factory
return factory(environ)