From 11644e705834ff65cb8963333855a1db6272ae1e Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Fri, 30 Oct 2009 18:56:58 +0000 Subject: 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``. --- repoze/bfg/tests/test_urldispatch.py | 78 ++++++++++++++++++++++++++---------- 1 file changed, 56 insertions(+), 22 deletions(-) (limited to 'repoze/bfg/tests/test_urldispatch.py') diff --git a/repoze/bfg/tests/test_urldispatch.py b/repoze/bfg/tests/test_urldispatch.py index c7a6c7ff3..99d5d1a98 100644 --- a/repoze/bfg/tests/test_urldispatch.py +++ b/repoze/bfg/tests/test_urldispatch.py @@ -1,5 +1,5 @@ import unittest -from repoze.bfg.testing import cleanUp +from repoze.bfg import testing class TestRoute(unittest.TestCase): def _getTargetClass(self): @@ -37,16 +37,30 @@ class TestRoute(unittest.TestCase): class RoutesRootFactoryTests(unittest.TestCase): def setUp(self): - cleanUp() + testing.setUp() def tearDown(self): - cleanUp() + testing.tearDown() - def _getEnviron(self, **kw): + def _getRequest(self, **kw): + from zope.component import getSiteManager environ = {'SERVER_NAME':'localhost', 'wsgi.url_scheme':'http'} environ.update(kw) - return environ + request = DummyRequest(environ) + sm = getSiteManager() + request.registry = sm + return request + + def _registerRouteRequest(self, name): + from repoze.bfg.interfaces import IRouteRequest + from zope.interface import Interface + from zope.component import getSiteManager + class IRequest(Interface): + """ """ + sm = getSiteManager() + sm.registerUtility(IRequest, IRouteRequest, name=name) + return IRequest def _getTargetClass(self): from repoze.bfg.urldispatch import RoutesRootFactory @@ -61,61 +75,80 @@ class RoutesRootFactoryTests(unittest.TestCase): self.assertEqual(mapper.default_root_factory, None) def test_no_route_matches(self): - get_root = DummyRootFactory(123) - mapper = self._makeOne(get_root) - environ = self._getEnviron(PATH_INFO='/') - result = mapper(environ) + root_factory = DummyRootFactory(123) + mapper = self._makeOne(root_factory) + request = self._getRequest(PATH_INFO='/') + result = mapper(request) + self.assertEqual(result, 123) + + def test_passed_environ_returns_default(self): + root_factory = DummyRootFactory(123) + mapper = self._makeOne(root_factory) + request = self._getRequest(PATH_INFO='/') + result = mapper(request.environ) self.assertEqual(result, 123) def test_route_matches(self): - get_root = DummyRootFactory(123) - mapper = self._makeOne(get_root) + root_factory = DummyRootFactory(123) + req_iface = self._registerRouteRequest('foo') + mapper = self._makeOne(root_factory) mapper.connect('archives/:action/:article', 'foo') - environ = self._getEnviron(PATH_INFO='/archives/action1/article1') - result = mapper(environ) + request = self._getRequest(PATH_INFO='/archives/action1/article1') + result = mapper(request) self.assertEqual(result, 123) + environ = request.environ routing_args = environ['wsgiorg.routing_args'][1] self.assertEqual(routing_args['action'], 'action1') self.assertEqual(routing_args['article'], 'article1') self.assertEqual(environ['bfg.routes.matchdict'], routing_args) self.assertEqual(environ['bfg.routes.route'].name, 'foo') + self.assertEqual(request.matchdict, routing_args) + self.failUnless(req_iface.providedBy(request)) def test_root_route_matches(self): root_factory = DummyRootFactory(123) + req_iface = self._registerRouteRequest('root') mapper = self._makeOne(root_factory) mapper.connect('', 'root') - environ = self._getEnviron(PATH_INFO='/') - result = mapper(environ) + request = self._getRequest(PATH_INFO='/') + result = mapper(request) + environ = request.environ self.assertEqual(result, 123) self.assertEqual(environ['bfg.routes.route'].name, 'root') self.assertEqual(environ['bfg.routes.matchdict'], {}) self.assertEqual(environ['wsgiorg.routing_args'], ((), {})) + self.assertEqual(request.matchdict, {}) + self.failUnless(req_iface.providedBy(request)) def test_root_route_matches2(self): root_factory = DummyRootFactory(123) + req_iface = self._registerRouteRequest('root') mapper = self._makeOne(root_factory) mapper.connect('/', 'root') - environ = self._getEnviron(PATH_INFO='/') - result = mapper(environ) + request = self._getRequest(PATH_INFO='/') + result = mapper(request) + environ = request.environ self.assertEqual(result, 123) self.assertEqual(environ['bfg.routes.route'].name, 'root') self.assertEqual(environ['bfg.routes.matchdict'], {}) self.assertEqual(environ['wsgiorg.routing_args'], ((), {})) + self.assertEqual(request.matchdict, {}) + self.failUnless(req_iface.providedBy(request)) def test_fallback_to_default_root_factory(self): root_factory = DummyRootFactory(123) mapper = self._makeOne(root_factory) mapper.connect('wont/:be/:found', 'wont') - environ = self._getEnviron(PATH_INFO='/archives/action1/article1') - result = mapper(environ) + request = self._getRequest(PATH_INFO='/archives/action1/article1') + result = mapper(request) self.assertEqual(result, 123) def test_no_path_info(self): root_factory = DummyRootFactory(123) mapper = self._makeOne(root_factory) mapper.connect('/', 'root') - environ = self._getEnviron() - result = mapper(environ) + request = self._getRequest() + result = mapper(request) self.assertEqual(result, 123) def test_has_routes(self): @@ -230,7 +263,8 @@ class DummyContext(object): """ """ class DummyRequest(object): - """ """ + def __init__(self, environ): + self.environ = environ class DummyRoute(object): def __init__(self, generator): -- cgit v1.2.3