diff options
| author | Chris McDonough <chrism@plope.com> | 2012-09-11 01:18:20 -0400 |
|---|---|---|
| committer | Chris McDonough <chrism@plope.com> | 2012-09-11 01:18:20 -0400 |
| commit | 73598739fbd0596ef15b15f827d6a47fb5862a98 (patch) | |
| tree | aca75557019676b83065c7fed5e953f8063b3ca3 | |
| parent | 28dba04ad96aca432b1b55719c960c7e8837191c (diff) | |
| download | pyramid-73598739fbd0596ef15b15f827d6a47fb5862a98.tar.gz pyramid-73598739fbd0596ef15b15f827d6a47fb5862a98.tar.bz2 pyramid-73598739fbd0596ef15b15f827d6a47fb5862a98.zip | |
- Request properties and methods added via ``config.set_request_property`` or
``config.add_request_method`` are now available to tweens.
- Request properties and methods added via ``config.set_request_property`` or
``config.add_request_method`` are now available in the request object
returned from ``pyramid.paster.bootstrap``.
Related partially to issue #520 and issue #538 and issue #596, although it doesn't actually allow us to close any of them, because we still don't issue a newrequest event when bootstrap is used.
| -rw-r--r-- | CHANGES.txt | 10 | ||||
| -rw-r--r-- | pyramid/config/factories.py | 9 | ||||
| -rw-r--r-- | pyramid/router.py | 6 | ||||
| -rw-r--r-- | pyramid/scripting.py | 5 | ||||
| -rw-r--r-- | pyramid/tests/test_config/test_factories.py | 30 | ||||
| -rw-r--r-- | pyramid/tests/test_router.py | 32 | ||||
| -rw-r--r-- | pyramid/tests/test_scripting.py | 60 | ||||
| -rw-r--r-- | pyramid/tests/test_util.py | 14 | ||||
| -rw-r--r-- | pyramid/util.py | 7 |
9 files changed, 114 insertions, 59 deletions
diff --git a/CHANGES.txt b/CHANGES.txt index 693cb4fc6..d510731fd 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -147,6 +147,16 @@ Features - ``pyramid.testing.DummyRequest`` now supports methods supplied by the ``pyramid.util.InstancePropertyMixin`` class such as ``set_property``. +- Request properties and methods added via ``config.set_request_property`` or + ``config.add_request_method`` are now available to tweens. + +- Request properties and methods added via ``config.set_request_property`` or + ``config.add_request_method`` are now available to tweens. + +- Request properties and methods added via ``config.set_request_property`` or + ``config.add_request_method`` are now available in the request object + returned from ``pyramid.paster.bootstrap``. + Deprecations ------------ diff --git a/pyramid/config/factories.py b/pyramid/config/factories.py index 501b1a963..c5d453654 100644 --- a/pyramid/config/factories.py +++ b/pyramid/config/factories.py @@ -153,8 +153,6 @@ class FactoriesConfiguratorMixin(object): if exts is None: exts = _RequestExtensions() self.registry.registerUtility(exts, IRequestExtensions) - self.registry.registerHandler(_set_request_extensions, - (INewRequest,)) plist = exts.descriptors if property else exts.methods plist[name] = callable @@ -201,10 +199,3 @@ class _RequestExtensions(object): self.descriptors = {} self.methods = {} -def _set_request_extensions(event): - request = event.request - exts = request.registry.queryUtility(IRequestExtensions) - for name, fn in iteritems_(exts.methods): - method = fn.__get__(request, request.__class__) - setattr(request, name, method) - request._set_properties(exts.descriptors) diff --git a/pyramid/router.py b/pyramid/router.py index 3491884b8..0cbe00f3a 100644 --- a/pyramid/router.py +++ b/pyramid/router.py @@ -6,6 +6,7 @@ from zope.interface import ( from pyramid.interfaces import ( IDebugLogger, IRequest, + IRequestExtensions, IRootFactory, IRouteRequest, IRouter, @@ -48,6 +49,7 @@ class Router(object): self.root_factory = q(IRootFactory, default=DefaultRootFactory) self.routes_mapper = q(IRoutesMapper) self.request_factory = q(IRequestFactory, default=Request) + self.request_extensions = q(IRequestExtensions) tweens = q(ITweens) if tweens is None: tweens = excview_tween_factory @@ -178,6 +180,9 @@ class Router(object): try: try: + extensions = self.request_extensions + if extensions is not None: + request._set_extensions(extensions) response = self.handle_request(request) has_listeners and notify(NewResponse(request, response)) @@ -192,4 +197,3 @@ class Router(object): finally: manager.pop() - diff --git a/pyramid/scripting.py b/pyramid/scripting.py index f1dc24637..0ab6541ae 100644 --- a/pyramid/scripting.py +++ b/pyramid/scripting.py @@ -3,6 +3,7 @@ from pyramid.exceptions import ConfigurationError from pyramid.request import Request from pyramid.interfaces import ( + IRequestExtensions, IRequestFactory, IRootFactory, ) @@ -70,9 +71,11 @@ def prepare(request=None, registry=None): 'before trying to activate it.') if request is None: request = _make_request('/', registry) - request.registry = registry threadlocals = {'registry':registry, 'request':request} threadlocal_manager.push(threadlocals) + extensions = registry.queryUtility(IRequestExtensions) + if extensions is not None: + request._set_extensions(extensions) def closer(): threadlocal_manager.pop() root_factory = registry.queryUtility(IRootFactory, diff --git a/pyramid/tests/test_config/test_factories.py b/pyramid/tests/test_config/test_factories.py index 213b7af84..cf3a9f8d9 100644 --- a/pyramid/tests/test_config/test_factories.py +++ b/pyramid/tests/test_config/test_factories.py @@ -112,36 +112,6 @@ class TestFactoriesMixin(unittest.TestCase): config.set_request_property(bar, name='bar') self.assertRaises(ConfigurationConflictError, config.commit) - def test_set_request_property_subscriber(self): - from zope.interface import implementer - from pyramid.interfaces import INewRequest - config = self._makeOne() - def foo(r): pass - config.set_request_property(foo, name='foo') - config.set_request_property(foo, name='bar', reify=True) - config.commit() - @implementer(INewRequest) - class Event(object): - request = DummyRequest(config.registry) - event = Event() - config.registry.notify(event) - exts = list(sorted(event.request.extensions)) - self.assertEqual('bar', exts[0]) - self.assertEqual('foo', exts[1]) - - def test_add_request_method_subscriber(self): - from zope.interface import implementer - from pyramid.interfaces import INewRequest - config = self._makeOne(autocommit=True) - def foo(r): return 'bar' - config.add_request_method(foo, name='foo') - @implementer(INewRequest) - class Event(object): - request = DummyRequest(config.registry) - event = Event() - config.registry.notify(event) - self.assertEqual('bar', event.request.foo()) - def test_add_request_method_with_callable(self): from pyramid.interfaces import IRequestExtensions config = self._makeOne(autocommit=True) diff --git a/pyramid/tests/test_router.py b/pyramid/tests/test_router.py index 6c68d548c..778b27473 100644 --- a/pyramid/tests/test_router.py +++ b/pyramid/tests/test_router.py @@ -312,6 +312,38 @@ class TestRouter(unittest.TestCase): self.assertEqual(app_iter, [b'abc']) self.assertEqual(start_response.status, '200 OK') + def test_call_with_request_extensions(self): + from pyramid.interfaces import IViewClassifier + from pyramid.interfaces import IRequestExtensions + from pyramid.interfaces import IRequest + from pyramid.request import Request + context = DummyContext() + self._registerTraverserFactory(context) + class Extensions(object): + def __init__(self): + self.methods = {} + self.descriptors = {} + extensions = Extensions() + L = [] + request = Request.blank('/') + request.request_iface = IRequest + request.registry = self.registry + request._set_extensions = lambda *x: L.extend(x) + def request_factory(environ): + return request + self.registry.registerUtility(extensions, IRequestExtensions) + environ = self._makeEnviron() + response = DummyResponse() + response.app_iter = ['Hello world'] + view = DummyView(response) + self._registerView(self.config.derive_view(view), '', + IViewClassifier, None, None) + router = self._makeOne() + router.request_factory = request_factory + start_response = DummyStartResponse() + router(environ, start_response) + self.assertEqual(L, [extensions]) + def test_call_view_registered_nonspecific_default_path(self): from pyramid.interfaces import IViewClassifier context = DummyContext() diff --git a/pyramid/tests/test_scripting.py b/pyramid/tests/test_scripting.py index a99ae53fe..a27ff812f 100644 --- a/pyramid/tests/test_scripting.py +++ b/pyramid/tests/test_scripting.py @@ -5,31 +5,37 @@ class Test_get_root(unittest.TestCase): from pyramid.scripting import get_root return get_root(app, request) + def _makeRegistry(self): + return DummyRegistry([DummyFactory]) + def test_it_norequest(self): - app = DummyApp(registry=dummy_registry) + registry = self._makeRegistry() + app = DummyApp(registry=registry) root, closer = self._callFUT(app) self.assertEqual(len(app.threadlocal_manager.pushed), 1) pushed = app.threadlocal_manager.pushed[0] - self.assertEqual(pushed['registry'], dummy_registry) + self.assertEqual(pushed['registry'], registry) self.assertEqual(pushed['request'].registry, app.registry) self.assertEqual(len(app.threadlocal_manager.popped), 0) closer() self.assertEqual(len(app.threadlocal_manager.popped), 1) def test_it_withrequest(self): - app = DummyApp(registry=dummy_registry) + registry = self._makeRegistry() + app = DummyApp(registry=registry) request = DummyRequest({}) root, closer = self._callFUT(app, request) self.assertEqual(len(app.threadlocal_manager.pushed), 1) pushed = app.threadlocal_manager.pushed[0] - self.assertEqual(pushed['registry'], dummy_registry) + self.assertEqual(pushed['registry'], registry) self.assertEqual(pushed['request'], request) self.assertEqual(len(app.threadlocal_manager.popped), 0) closer() self.assertEqual(len(app.threadlocal_manager.popped), 1) def test_it_requestfactory_overridden(self): - app = DummyApp(registry=dummy_registry) + registry = self._makeRegistry() + app = DummyApp(registry=registry) root, closer = self._callFUT(app) self.assertEqual(len(app.threadlocal_manager.pushed), 1) pushed = app.threadlocal_manager.pushed[0] @@ -40,8 +46,10 @@ class Test_prepare(unittest.TestCase): from pyramid.scripting import prepare return prepare(request, registry) - def _makeRegistry(self): - return DummyRegistry(DummyFactory) + def _makeRegistry(self, L=None): + if L is None: + L = [None, DummyFactory] + return DummyRegistry(L) def setUp(self): from pyramid.threadlocal import manager @@ -53,7 +61,7 @@ class Test_prepare(unittest.TestCase): self.assertRaises(ConfigurationError, self._callFUT) def test_it_norequest(self): - registry = self._makeRegistry() + registry = self._makeRegistry([DummyFactory, None, DummyFactory]) info = self._callFUT(registry=registry) root, closer = info['root'], info['closer'] pushed = self.manager.get() @@ -89,20 +97,32 @@ class Test_prepare(unittest.TestCase): closer() self.assertEqual(self.default, self.manager.get()) + def test_it_with_extensions(self): + exts = Dummy() + request = DummyRequest({}) + registry = request.registry = self._makeRegistry([exts, DummyFactory]) + info = self._callFUT(request=request, registry=registry) + self.assertEqual(request.extensions, exts) + root, closer = info['root'], info['closer'] + closer() + class Test__make_request(unittest.TestCase): def _callFUT(self, path='/', registry=None): from pyramid.scripting import _make_request return _make_request(path, registry) + def _makeRegistry(self): + return DummyRegistry([DummyFactory]) + def test_it_with_registry(self): - request = self._callFUT('/', dummy_registry) + registry = self._makeRegistry() + request = self._callFUT('/', registry) self.assertEqual(request.environ['path'], '/') - self.assertEqual(request.registry, dummy_registry) + self.assertEqual(request.registry, registry) def test_it_with_no_registry(self): from pyramid.config import global_registries - # keep registry local so that global_registries is cleared after - registry = DummyRegistry(DummyFactory) + registry = self._makeRegistry() global_registries.add(registry) try: request = self._callFUT('/hello') @@ -127,13 +147,13 @@ class DummyFactory(object): self.kw = kw class DummyRegistry(object): - def __init__(self, factory=None): - self.factory = factory + def __init__(self, utilities): + self.utilities = utilities def queryUtility(self, iface, default=None): - return self.factory or default - -dummy_registry = DummyRegistry(DummyFactory) + if self.utilities: + return self.utilities.pop(0) + return default class DummyApp: def __init__(self, registry=None): @@ -156,6 +176,10 @@ class DummyThreadLocalManager: self.popped.append(True) class DummyRequest: + matchdict = None + matched_route = None def __init__(self, environ): self.environ = environ - + + def _set_extensions(self, exts): + self.extensions = exts diff --git a/pyramid/tests/test_util.py b/pyramid/tests/test_util.py index e83ad5922..3d85e18f5 100644 --- a/pyramid/tests/test_util.py +++ b/pyramid/tests/test_util.py @@ -132,6 +132,20 @@ class Test_InstancePropertyMixin(unittest.TestCase): self.assertEqual(1, foo.x) self.assertEqual(2, foo.y) + def test__set_extensions(self): + inst = self._makeOne() + def foo(self, result): + return result + n, bar = inst._make_property(lambda _: 'bar', name='bar') + class Extensions(object): + def __init__(self): + self.methods = {'foo':foo} + self.descriptors = {'bar':bar} + extensions = Extensions() + inst._set_extensions(extensions) + self.assertEqual(inst.bar, 'bar') + self.assertEqual(inst.foo('abc'), 'abc') + class Test_WeakOrderedSet(unittest.TestCase): def _makeOne(self): from pyramid.config import WeakOrderedSet diff --git a/pyramid/util.py b/pyramid/util.py index dabd84695..6190e8156 100644 --- a/pyramid/util.py +++ b/pyramid/util.py @@ -2,6 +2,7 @@ import inspect import weakref from pyramid.compat import ( + iteritems_, integer_types, string_types, text_, @@ -74,6 +75,12 @@ class InstancePropertyMixin(object): cls = type(parent.__name__, (parent, object), attrs) self.__class__ = cls + def _set_extensions(self, extensions): + for name, fn in iteritems_(extensions.methods): + method = fn.__get__(self, self.__class__) + setattr(self, name, method) + self._set_properties(extensions.descriptors) + def set_property(self, callable, name=None, reify=False): """ Add a callable or a property descriptor to the instance. |
