Browse files

- Request properties and methods added via ``config.set_request_prope…

…rty`` 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.
  • Loading branch information...
1 parent 28dba04 commit 73598739fbd0596ef15b15f827d6a47fb5862a98 @mcdonc mcdonc committed Sep 11, 2012
View
10 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
------------
View
9 pyramid/config/factories.py
@@ -153,8 +153,6 @@ def register():
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 @@ def __init__(self):
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)
View
6 pyramid/router.py
@@ -6,6 +6,7 @@
from pyramid.interfaces import (
IDebugLogger,
IRequest,
+ IRequestExtensions,
IRootFactory,
IRouteRequest,
IRouter,
@@ -48,6 +49,7 @@ def __init__(self, registry):
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 @@ def __call__(self, environ, start_response):
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 @@ def __call__(self, environ, start_response):
finally:
manager.pop()
-
View
5 pyramid/scripting.py
@@ -3,6 +3,7 @@
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,
View
30 pyramid/tests/test_config/test_factories.py
@@ -112,36 +112,6 @@ def foo(self): pass
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)
View
32 pyramid/tests/test_router.py
@@ -312,6 +312,38 @@ def make_response(s):
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()
View
60 pyramid/tests/test_scripting.py
@@ -5,31 +5,37 @@ def _callFUT(self, app, request=None):
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 @@ def _callFUT(self, request=None, registry=None):
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 @@ def test_it_no_valid_apps(self):
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 @@ def test_it_with_request_and_registry(self):
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 @@ def __init__(self, *a, **kw):
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 @@ def pop(self):
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
View
14 pyramid/tests/test_util.py
@@ -132,6 +132,20 @@ def test__set_properties_with_dict(self):
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
View
7 pyramid/util.py
@@ -2,6 +2,7 @@
import weakref
from pyramid.compat import (
+ iteritems_,
integer_types,
string_types,
text_,
@@ -74,6 +75,12 @@ def _set_properties(self, properties):
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.

0 comments on commit 7359873

Please sign in to comment.