summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES.txt107
-rw-r--r--docs/api/request.rst2
-rw-r--r--pyramid/config.py2
-rw-r--r--pyramid/request.py64
-rw-r--r--pyramid/router.py7
-rw-r--r--pyramid/tests/test_request.py30
-rw-r--r--pyramid/tests/test_router.py91
7 files changed, 32 insertions, 271 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index b1979347a..c9c95fd7f 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -8,71 +8,28 @@ Features
``rendering_val``. This can be used to introspect the value returned by a
view in a BeforeRender subscriber.
-- New method: ``pyramid.request.Request.add_view_wrapper``. A view wrapper
- is used to wrap the found view callable before it is called by Pyramid's
- router. This is a feature usually only used by framework extensions, to
- provide, for example, view timing support.
-
- A view wrapper factory must be a callable which accepts three arguments:
- ``view_callable``, ``request``, and ``exc``. It must return a view
- callable. The view callable returned by the factory must implement the
- ``context, request`` view callable calling convention. For example::
-
- import time
-
- def wrapper_factory(view_callable, request, exc):
- def wrapper(context, request):
- start = time.time()
- result = view_callable(context, request)
- end = time.time()
- request.view_timing = end - start
- return result
- return wrapper
-
- The ``view_callable`` argument to the factory will be the view callable
- found by Pyramid via view lookup. The ``request`` argument to the factory
- will be the current request. The ``exc`` argument to the factory will be
- an Exception object if the found view is an exception view; it will be
- ``None`` otherwise.
-
- View wrappers only last for the duration of a single request. You can add
- such a factory for every request by using the
- ``pyramid.events.NewRequest`` subscriber::
-
- from pyramid.events import subscriber, NewRequest
-
- @subscriber(NewRequest)
- def newrequest(event):
- event.request.add_view_wrapper(wrapper_factory)
-
- If more than one view wrapper is registered during a single request,
- a 'later' view wrapper factory will be called with the result of its
- directly former view wrapper factory as its ``view_callable``
- argument; this chain will be returned to Pyramid as a single view
- callable.
-
- New configurator directive:
- ``pyramid.config.Configurator.add_request_handler``. This directive adds
- a request handler factory.
+ ``pyramid.config.Configurator.add_request_handler``. This directive adds
+ a request handler factory.
- A request handler factory is used to wrap the Pyramid router's primary
- request handling function. This is a feature usually only used by
- framework extensions, to provide, for example, view timing support and as
- a convenient place to hang bookkeeping code that examines exceptions
- before they are returned to the server.
+ A request handler factory is used to wrap the Pyramid router's primary
+ request handling function. This is a feature may be used by framework
+ extensions, to provide, for example, view timing support and as a
+ convenient place to hang bookkeeping code that examines exceptions before
+ they are returned to the server.
- A request handler factory (passed as ``handler_factory``) must be a
- callable which accepts two arguments: ``handler`` and ``registry``.
- ``handler`` will be the request handler being wrapped. ``registry`` will
- be the Pyramid application registry represented by this Configurator. A
- request handler factory must return a request handler when it is called.
+ A request handler factory (passed as ``handler_factory``) must be a
+ callable which accepts two arguments: ``handler`` and ``registry``.
+ ``handler`` will be the request handler being wrapped. ``registry`` will
+ be the Pyramid application registry represented by this Configurator. A
+ request handler factory must return a request handler when it is called.
- A request handler accepts a request object and returns a response object.
+ A request handler accepts a request object and returns a response object.
- Here's an example of creating both a handler factory and a handler, and
- registering the handler factory:
+ Here's an example of creating both a handler factory and a handler, and
+ registering the handler factory:
- .. code-block:: python
+ .. code-block:: python
import time
@@ -93,23 +50,21 @@ Features
config.add_request_handler(timing_handler_factory, 'timing')
- The ``request`` argument to the handler will be the request created by
- Pyramid's router when it receives a WSGI request.
-
- If more than one request handler factory is registered into a single
- configuration, the request handlers will be chained together. The first
- request handler factory added (in code execution order) will be called
- with the default Pyramid request handler, the second handler factory added
- will be called with the result of the first handler factory, ad
- infinitum. The Pyramid router will use the outermost wrapper in this chain
- (which is a bit like a WSGI middleware "pipeline") as its handler
- function.
-
- The ``name`` argument to this function is required. The name is used as a
- key for conflict detection. No two request handler factories may share
- the same name in the same configuration (unless
- automatic_conflict_resolution is able to resolve the conflict or
- this is an autocommitting configurator).
+ The ``request`` argument to the handler will be the request created by
+ Pyramid's router when it receives a WSGI request.
+
+ If more than one request handler factory is registered into a single
+ configuration, the request handlers will be chained together. The first
+ request handler factory added (in code execution order) will be called with
+ the default Pyramid request handler, the second handler factory added will
+ be called with the result of the first handler factory, ad infinitum. The
+ Pyramid router will use the outermost wrapper in this chain (which is a bit
+ like a WSGI middleware "pipeline") as its handler function.
+
+ The ``name`` argument to this function is required. The name is used as a
+ key for conflict detection. No two request handler factories may share the
+ same name in the same configuration (unless automatic_conflict_resolution
+ is able to resolve the conflict or this is an autocommitting configurator).
1.1 (2011-07-22)
================
diff --git a/docs/api/request.rst b/docs/api/request.rst
index 58532bbd1..404825d1b 100644
--- a/docs/api/request.rst
+++ b/docs/api/request.rst
@@ -154,8 +154,6 @@
.. automethod:: add_finished_callback
- .. automethod:: add_view_wrapper
-
.. automethod:: route_url
.. automethod:: route_path
diff --git a/pyramid/config.py b/pyramid/config.py
index 6c47e7871..d6a87c7ad 100644
--- a/pyramid/config.py
+++ b/pyramid/config.py
@@ -892,7 +892,7 @@ class Configurator(object):
"""
Add a request handler factory. A request handler factory is used to
wrap the Pyramid router's primary request handling function. This is
- a feature usually only used by framework extensions, to provide, for
+ a feature that may be used by framework extensions, to provide, for
example, view timing support and as a convenient place to hang
bookkeeping code that examines exceptions before they are returned to
the server.
diff --git a/pyramid/request.py b/pyramid/request.py
index 927319479..8df204681 100644
--- a/pyramid/request.py
+++ b/pyramid/request.py
@@ -203,7 +203,6 @@ class Request(BaseRequest, DeprecatedRequestMethods):
implements(IRequest)
response_callbacks = ()
finished_callbacks = ()
- view_wrappers = ()
exception = None
matchdict = None
matched_route = None
@@ -213,69 +212,6 @@ class Request(BaseRequest, DeprecatedRequestMethods):
""" Template context (for Pylons apps) """
return TemplateContext()
- def add_view_wrapper(self, wrapper):
- """
- Add a view wrapper factory. A view wrapper is used to wrap the found
- view callable before it is called by Pyramid's router. This is a
- feature usually only used by framework extensions, to provide, for
- example, view timing support.
-
- A view wrapper factory must be a callable which accepts three
- arguments: ``view_callable``, ``request``, and ``exc``. It must
- return a view callable. The view callable returned by the factory
- must implement the ``context, request`` view callable calling
- convention. For example:
-
- .. code-block:: python
-
- import time
-
- def wrapper_factory(view_callable, request, exc):
- def wrapper(context, request):
- start = time.time()
- result = view_callable(context, request)
- end = time.time()
- request.view_timing = end - start
- return result
- return wrapper
-
- The ``view_callable`` argument to the factory will be the view
- callable found by Pyramid via :term:`view lookup`. The ``request``
- argument to the factory will be the current request. The ``exc``
- argument to the factory will be an Exception object if the found view
- is a :term:`exception view`; it will be ``None`` otherwise.
-
- View wrappers only last for the duration of a single request. You
- can add such a factory for every request by using the
- :class:`pyramid.events.NewRequest` subscriber:
-
- .. code-block:: python
-
- from pyramid.events import subscriber, NewRequest
-
- @subscriber(NewRequest)
- def newrequest(event):
- event.request.add_view_wrapper(wrapper_factory)
-
- If more than one view wrapper is registered during a single request,
- a 'later' view wrapper factory will be called with the result of its
- directly former view wrapper factory as its ``view_callable``
- argument; this chain will be returned to Pyramid as a single view
- callable.
-
- .. note:: This feature is new as of Pyramid 1.1.1.
- """
- wrappers = self.view_wrappers
- if not wrappers:
- wrappers = []
- wrappers.append(wrapper)
- self.view_wrappers = wrappers
-
- def _wrap_view(self, view, exc=None):
- for wrapper in self.view_wrappers:
- view = wrapper(view, self, exc)
- return view
-
def add_response_callback(self, callback):
"""
Add a callback to the set of callbacks to be called by the
diff --git a/pyramid/router.py b/pyramid/router.py
index dcf257beb..e8c19fca0 100644
--- a/pyramid/router.py
+++ b/pyramid/router.py
@@ -160,9 +160,6 @@ class Router(object):
else:
# if there were any view wrappers for the current
# request, use them to wrap the view
- if request.view_wrappers:
- view_callable = request._wrap_view(
- view_callable)
response = view_callable(context, request)
@@ -185,10 +182,6 @@ class Router(object):
if view_callable is None:
raise
- if request.view_wrappers:
- view_callable = request._wrap_view(view_callable,
- exc=why)
-
response = view_callable(why, request)
has_listeners and notify(NewResponse(request, response))
diff --git a/pyramid/tests/test_request.py b/pyramid/tests/test_request.py
index 3c24c8f58..066aa9207 100644
--- a/pyramid/tests/test_request.py
+++ b/pyramid/tests/test_request.py
@@ -145,36 +145,6 @@ class TestRequest(unittest.TestCase):
self.assertEqual(inst.called2, True)
self.assertEqual(inst.finished_callbacks, [])
- def test_add_view_wrapper(self):
- inst = self._makeOne({})
- wrapper = object()
- inst.add_view_wrapper(wrapper)
- self.assertEqual(inst.view_wrappers, [wrapper])
-
- def test_add_view_wrapper_wrappers_exist(self):
- inst = self._makeOne({})
- inst.view_wrappers = [123]
- wrapper = object()
- inst.add_view_wrapper(wrapper)
- self.assertEqual(inst.view_wrappers, [123, wrapper])
-
- def test__wrap_view_no_wrappers(self):
- inst = self._makeOne({})
- wrapped = inst._wrap_view(lambda *arg: 'OK')
- self.assertEqual(wrapped(), 'OK')
-
- def test__wrap_view_with_wrappers_no_exc(self):
- inst = self._makeOne({})
- def view(*arg): return 'OK'
- def view_wrapper(_view, request, exc):
- self.assertEqual(_view, view)
- self.assertEqual(request, inst)
- self.assertEqual(exc, '123')
- return _view
- inst.view_wrappers = [view_wrapper]
- wrapped = inst._wrap_view(view, exc='123')
- self.assertEqual(wrapped(), 'OK')
-
def test_resource_url(self):
self._registerContextURL()
inst = self._makeOne({})
diff --git a/pyramid/tests/test_router.py b/pyramid/tests/test_router.py
index a1e7252e9..4d44de5c0 100644
--- a/pyramid/tests/test_router.py
+++ b/pyramid/tests/test_router.py
@@ -546,97 +546,6 @@ class TestRouter(unittest.TestCase):
exc_raised(NotImplementedError, router, environ, start_response)
self.assertEqual(environ['called_back'], True)
- def test_call_request_has_view_wrappers(self):
- from zope.interface import Interface
- from zope.interface import directlyProvides
- class IContext(Interface):
- pass
- from pyramid.interfaces import IRequest
- from pyramid.interfaces import IViewClassifier
- from pyramid.interfaces import INewRequest
- wrappers = []
- class ViewWrapper(object):
- def __call__(self, view, request, exc):
- self.view = view
- self.exc = exc
- wrappers.append(self)
- return self.wrap
- def wrap(self, context, request):
- return self.view(context, request)
- wrapper1 = ViewWrapper()
- wrapper2 = ViewWrapper()
- def newrequest(event):
- event.request.view_wrappers = [wrapper1, wrapper2]
- self.registry.registerHandler(newrequest, (INewRequest,))
- context = DummyContext()
- directlyProvides(context, IContext)
- self._registerTraverserFactory(context, subpath=[''])
- response = DummyResponse('200 OK')
- response.app_iter = ['OK']
- def view(context, request):
- return response
- environ = self._makeEnviron()
- self._registerView(view, '', IViewClassifier, IRequest, IContext)
- router = self._makeOne()
- start_response = DummyStartResponse()
- itera = router(environ, start_response)
- wrapper1, wrapper2 = wrappers
- self.assertEqual(wrapper1.view, view)
- self.assertEqual(wrapper2.view, wrapper1.wrap)
- self.assertEqual(wrapper1.exc, None)
- self.assertEqual(wrapper2.exc, None)
- self.assertEqual(itera, ['OK'])
-
- def test_call_request_has_view_wrappers_in_exception(self):
- from zope.interface import Interface
- from zope.interface import directlyProvides
- class IContext(Interface):
- pass
- from pyramid.interfaces import IRequest
- from pyramid.interfaces import IViewClassifier
- from pyramid.interfaces import INewRequest
- from pyramid.interfaces import IExceptionViewClassifier
- wrappers = []
- class ViewWrapper(object):
- def __init__(self):
- self.views = []
- self.exc = []
- def __call__(self, view, request, exc):
- self.views.append(view)
- self.exc.append(exc)
- wrappers.append(self)
- return self.wrap
- def wrap(self, context, request):
- return self.views[-1](context, request)
- wrapper1 = ViewWrapper()
- wrapper2 = ViewWrapper()
- def newrequest(event):
- event.request.view_wrappers = [wrapper1, wrapper2]
- self.registry.registerHandler(newrequest, (INewRequest,))
- context = DummyContext()
- directlyProvides(context, IContext)
- self._registerTraverserFactory(context, subpath=[''])
- error = NotImplementedError()
- def view(context, request):
- raise error
- environ = self._makeEnviron()
- self._registerView(view, '', IViewClassifier, IRequest, IContext)
- exception_response = DummyResponse('404 Not Found')
- exception_response.app_iter = ['Not Found']
- exception_view = DummyView(exception_response)
- environ = self._makeEnviron()
- self._registerView(exception_view, '', IExceptionViewClassifier,
- IRequest, NotImplementedError)
- router = self._makeOne()
- start_response = DummyStartResponse()
- itera = router(environ, start_response)
- wrapper1, wrapper2, wrapper3, wrapper4 = wrappers
- self.assertEqual(wrapper1.views, [view, exception_view])
- self.assertEqual(wrapper2.views, [wrapper1.wrap, wrapper1.wrap])
- self.assertEqual(wrapper1.exc, [None, error])
- self.assertEqual(wrapper2.exc, [None, error])
- self.assertEqual(itera, ['Not Found'])
-
def test_call_request_factory_raises(self):
# making sure finally doesnt barf when a request cannot be created
environ = self._makeEnviron()