Chris McDonough
2012-11-21 71cd93bd78015285db9aaadaa63a5ac9042f6843
- Small microspeed enhancement which anticipates that a
``pyramid.response.Response`` object is likely to be returned from a view.
Some code is shortcut if the class of the object returned by a view is this
class. A similar microoptimization was done to
``pyramid.request.Request.is_response``.
5 files modified
119 ■■■■ changed files
CHANGES.txt 9 ●●●●● patch | view | raw | blame | history
pyramid/config/views.py 78 ●●●●● patch | view | raw | blame | history
pyramid/request.py 2 ●●●●● patch | view | raw | blame | history
pyramid/tests/test_config/test_views.py 23 ●●●●● patch | view | raw | blame | history
pyramid/tests/test_request.py 7 ●●●●● patch | view | raw | blame | history
CHANGES.txt
@@ -1,6 +1,15 @@
Next release
============
Features
--------
- Small microspeed enhancement which anticipates that a
  ``pyramid.response.Response`` object is likely to be returned from a view.
  Some code is shortcut if the class of the object returned by a view is this
  class.  A similar microoptimization was done to
  ``pyramid.request.Request.is_response``.
Bug Fixes
---------
pyramid/config/views.py
@@ -59,6 +59,8 @@
    Deferred,
    )
from pyramid.response import Response
from pyramid.security import NO_PERMISSION_REQUIRED
from pyramid.static import static_view
from pyramid.threadlocal import get_current_registry
@@ -341,25 +343,28 @@
        def rendered_view(context, request):
            renderer = view_renderer
            result = view(context, request)
            registry = self.registry
            # this must adapt, it can't do a simple interface check
            # (avoid trying to render webob responses)
            response = registry.queryAdapterOrSelf(result, IResponse)
            if response is None:
                attrs = getattr(request, '__dict__', {})
                if 'override_renderer' in attrs:
                    # renderer overridden by newrequest event or other
                    renderer_name = attrs.pop('override_renderer')
                    renderer = renderers.RendererHelper(
                        name=renderer_name,
                        package=self.kw.get('package'),
                        registry = registry)
                if '__view__' in attrs:
                    view_inst = attrs.pop('__view__')
                else:
                    view_inst = getattr(view, '__original_view__', view)
                response = renderer.render_view(request, result, view_inst,
                                                context)
            if result.__class__ is Response: # potential common case
                response = result
            else:
                registry = self.registry
                # this must adapt, it can't do a simple interface check
                # (avoid trying to render webob responses)
                response = registry.queryAdapterOrSelf(result, IResponse)
                if response is None:
                    attrs = getattr(request, '__dict__', {})
                    if 'override_renderer' in attrs:
                        # renderer overridden by newrequest event or other
                        renderer_name = attrs.pop('override_renderer')
                        renderer = renderers.RendererHelper(
                            name=renderer_name,
                            package=self.kw.get('package'),
                            registry = registry)
                    if '__view__' in attrs:
                        view_inst = attrs.pop('__view__')
                    else:
                        view_inst = getattr(view, '__original_view__', view)
                    response = renderer.render_view(request, result, view_inst,
                                                    context)
            return response
        return rendered_view
@@ -368,21 +373,26 @@
        registry = self.registry
        def viewresult_to_response(context, request):
            result = view(context, request)
            response = registry.queryAdapterOrSelf(result, IResponse)
            if response is None:
                if result is None:
                    append = (' You may have forgotten to return a value from '
                              'the view callable.')
                elif isinstance(result, dict):
                    append = (' You may have forgotten to define a renderer in '
                              'the view configuration.')
                else:
                    append = ''
                msg = ('Could not convert return value of the view callable %s '
                      'into a response object. '
                      'The value returned was %r.' + append)
                raise ValueError(msg % (view_description(view), result))
            if result.__class__ is Response: # common case
                response = result
            else:
                response = registry.queryAdapterOrSelf(result, IResponse)
                if response is None:
                    if result is None:
                        append = (' You may have forgotten to return a value '
                                  'from the view callable.')
                    elif isinstance(result, dict):
                        append = (' You may have forgotten to define a '
                                  'renderer in the view configuration.')
                    else:
                        append = ''
                    msg = ('Could not convert return value of the view '
                           'callable %s into a response object. '
                           'The value returned was %r.' + append)
                    raise ValueError(msg % (view_description(view), result))
            return response
        return viewresult_to_response
pyramid/request.py
@@ -372,6 +372,8 @@
    def is_response(self, ob):
        """ Return ``True`` if the object passed as ``ob`` is a valid
        response object, ``False`` otherwise."""
        if ob.__class__ is Response:
            return True
        registry = self.registry
        adapted = registry.queryAdapterOrSelf(ob, IResponse)
        if adapted is None:
pyramid/tests/test_config/test_views.py
@@ -2483,6 +2483,29 @@
        else: # pragma: no cover
            raise AssertionError
    def test_function_returns_true_Response_no_renderer(self):
        from pyramid.response import Response
        r = Response('Hello')
        def view(request):
            return r
        deriver = self._makeOne()
        result = deriver(view)
        self.assertFalse(result is view)
        response = result(None, None)
        self.assertEqual(response, r)
    def test_function_returns_true_Response_with_renderer(self):
        from pyramid.response import Response
        r = Response('Hello')
        def view(request):
            return r
        renderer = object()
        deriver = self._makeOne(renderer=renderer)
        result = deriver(view)
        self.assertFalse(result is view)
        response = result(None, None)
        self.assertEqual(response, r)
    def test_requestonly_default_method_returns_non_adaptable(self):
        request = DummyRequest()
        class AView(object):
pyramid/tests/test_request.py
@@ -230,6 +230,13 @@
        request.registry = self.config.registry
        self.assertEqual(request.is_response('abc'), False)
    def test_is_response_true_ob_is_pyramid_response(self):
        from pyramid.response import Response
        r = Response('hello')
        request = self._makeOne()
        request.registry = self.config.registry
        self.assertEqual(request.is_response(r), True)
    def test_is_response_false_adapter_is_not_self(self):
        from pyramid.interfaces import IResponse
        request = self._makeOne()