diff options
| -rw-r--r-- | CHANGES.txt | 26 | ||||
| -rw-r--r-- | RELEASING.txt | 25 | ||||
| -rw-r--r-- | docs/api/request.rst | 10 | ||||
| -rw-r--r-- | docs/designdefense.rst | 9 | ||||
| -rw-r--r-- | docs/glossary.rst | 3 | ||||
| -rw-r--r-- | docs/narr/sessions.rst | 2 | ||||
| -rw-r--r-- | docs/narr/webob.rst | 54 | ||||
| -rw-r--r-- | docs/whatsnew-1.1.rst | 12 | ||||
| -rw-r--r-- | pyramid/config.py | 149 | ||||
| -rw-r--r-- | pyramid/request.py | 5 | ||||
| -rw-r--r-- | pyramid/router.py | 11 | ||||
| -rw-r--r-- | pyramid/tests/restbugapp/views.py | 2 | ||||
| -rw-r--r-- | pyramid/tests/test_config.py | 236 | ||||
| -rw-r--r-- | pyramid/tests/test_integration.py | 2 | ||||
| -rw-r--r-- | pyramid/tests/test_request.py | 25 | ||||
| -rw-r--r-- | pyramid/tests/test_router.py | 21 | ||||
| -rw-r--r-- | pyramid/tests/test_view.py | 13 | ||||
| -rw-r--r-- | pyramid/tests/venusianapp/__init__.py | 14 | ||||
| -rw-r--r-- | pyramid/view.py | 6 |
19 files changed, 404 insertions, 221 deletions
diff --git a/CHANGES.txt b/CHANGES.txt index 0eb02baad..ff4036036 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -4,10 +4,14 @@ Next release Features -------- -- New request attribute: ``json``. If the request's ``content_type`` is - ``application/json``, this attribute will contain the JSON-decoded - variant of the request body. If the request's ``content_type`` is not - ``application/json``, this attribute will be ``None``. +- The ``config.scan`` method has grown a ``**kw`` argument. ``kw`` argument + represents a set of keyword arguments to pass to the Venusian ``Scanner`` + object created by Pyramid. (See the Venusian documentation for more + information about ``Scanner``). + +- New request property: ``json_body``. This property will return the + JSON-decoded variant of the request body. If the request body is not + well-formed JSON, this property will raise an exception. - A new value ``http_cache`` can be used as a view configuration parameter. @@ -60,6 +64,20 @@ Features to only influence ``Cache-Control`` headers, pass a tuple as ``http_cache`` with the first element of ``None``, e.g.: ``(None, {'public':True})``. +Bug Fixes +--------- + +- Framework wrappers of the original view (such as http_cached and so on) + relied on being able to trust that the response they were receiving was an + IResponse. It wasn't always, because the response was resolved by the + router instead of early in the view wrapping process. This has been fixed. + +Documentation +------------- + +- Added a section in the "Webob" chapter named "Dealing With A JSON-Encoded + Request Body" (usage of ``request.json_body``). + 1.1a4 (2011-07-01) ================== diff --git a/RELEASING.txt b/RELEASING.txt index 645083acf..bb2dab87f 100644 --- a/RELEASING.txt +++ b/RELEASING.txt @@ -48,4 +48,29 @@ Releasing Pyramid - Announce to Twitter. +Announcement template +---------------------- +Pyramid 1.1.X has been released. + +Here are the changes: + +<<changes>> + +A "What's New In Pyramid 1.1" document exists at +http://docs.pylonsproject.org/projects/pyramid/1.1/whatsnew-1.1.html . + +You will be able to see the 1.1 release documentation (across all +alphas and betas, as well as when it eventually gets to final release) +at http://docs.pylonsproject.org/projects/pyramid/1.1/ . + +You can install it via PyPI: + + easy_install Pyramid==1.1a4 + +Enjoy, and please report any issues you find to the issue tracker at +https://github.com/Pylons/pyramid/issues + +Thanks! + +- C diff --git a/docs/api/request.rst b/docs/api/request.rst index 5dfb2ae9a..404825d1b 100644 --- a/docs/api/request.rst +++ b/docs/api/request.rst @@ -180,12 +180,12 @@ object (exposed to view code as ``request.response``) to influence rendered response behavior. - .. attribute:: json + .. attribute:: json_body - If the request's ``content_type`` is ``application/json``, this - attribute will contain the JSON-decoded variant of the request body. - If the request's ``content_type`` is not ``application/json``, this - attribute will be ``None``. + This property will return the JSON-decoded variant of the request + body. If the request body is not well-formed JSON, or there is no + body associated with this request, this property will raise an + exception. See also :ref:`request_json_body`. .. note:: diff --git a/docs/designdefense.rst b/docs/designdefense.rst index ce3c507c5..b285524c6 100644 --- a/docs/designdefense.rst +++ b/docs/designdefense.rst @@ -1125,10 +1125,11 @@ Self-described "microframeworks" exist: `Bottle <http://bottle.paws.de>`_ and <http://bobo.digicool.com/>`_ doesn't describe itself as a microframework, but its intended userbase is much the same. Many others exist. We've actually even (only as a teaching tool, not as any sort of official project) -`created one using BFG <http://bfg.repoze.org/videos#groundhog1>`_ (the -precursor to Pyramid). Microframeworks are small frameworks with one common -feature: each allows its users to create a fully functional application that -lives in a single Python file. +`created one using Pyramid <http://bfg.repoze.org/videos#groundhog1>`_ (the +videos use BFG, a precursor to Pyramid, but the resulting code is `available +for Pyramid too <http://github.com/Pylons/groundhog>`_). Microframeworks are +small frameworks with one common feature: each allows its users to create a +fully functional application that lives in a single Python file. Some developers and microframework authors point out that Pyramid's "hello world" single-file program is longer (by about five lines) than the diff --git a/docs/glossary.rst b/docs/glossary.rst index e45317dae..c8943acae 100644 --- a/docs/glossary.rst +++ b/docs/glossary.rst @@ -506,6 +506,9 @@ Glossary `JavaScript Object Notation <http://www.json.org/>`_ is a data serialization format. + jQuery + A popular `Javascript library <http://jquery.org>`_. + renderer A serializer that can be referred to via :term:`view configuration` which converts a non-:term:`Response` return diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst index 97e3ebc55..365ee395b 100644 --- a/docs/narr/sessions.rst +++ b/docs/narr/sessions.rst @@ -288,7 +288,7 @@ Preventing Cross-Site Request Forgery Attacks `Cross-site request forgery <http://en.wikipedia.org/wiki/Cross-site_request_forgery>`_ attacks are a phenomenon whereby a user with an identity on your website might click on a -URL or button on another website which unwittingly redirects the user to your +URL or button on another website which secretly redirects the user to your application to perform some command that requires elevated privileges. You can avoid most of these attacks by making sure that the correct *CSRF diff --git a/docs/narr/webob.rst b/docs/narr/webob.rst index 0ff8e1de7..beb319084 100644 --- a/docs/narr/webob.rst +++ b/docs/narr/webob.rst @@ -78,6 +78,10 @@ object: ``PUT``. You can also get ``req.body_file`` for a file-like object. +``req.json_body`` + The JSON-decoded contents of the body of the request. See + :ref:`request_json_body`. + ``req.cookies``: A simple dictionary of all the cookies. @@ -239,6 +243,56 @@ tuples; all the keys are ordered, and all the values are ordered. API documentation for a multidict exists as :class:`pyramid.interfaces.IMultiDict`. +.. _request_json_body: + +Dealing With A JSON-Encoded Request Body +++++++++++++++++++++++++++++++++++++++++ + +.. note:: this feature is new as of Pyramid 1.1. + +:attr:`pyramid.request.Request.json_body` is a property that returns a +:term:`JSON` -decoded representation of the request body. If the request +does not have a body, or the body is not a properly JSON-encoded value, an +exception will be raised when this attribute is accessed. + +This attribute is useful when you invoke a Pyramid view callable via +e.g. jQuery's ``$.ajax`` function, which has the potential to send a request +with a JSON-encoded body. + +Using ``request.json_body`` is equivalent to: + +.. code-block:: python + + from json import loads + loads(request.body, encoding=request.charset) + +Here's how to construct an AJAX request in Javascript using :term:`jQuery` +that allows you to use the ``request.json_body`` attribute when the request +is sent to a Pyramid application: + +.. code-block:: javascript + + jQuery.ajax({type:'POST', + url: 'http://localhost:6543/', // the pyramid server + data: JSON.stringify({'a':1}), + contentType: 'application/json; charset=utf-8'}); + +When such a request reaches a view in your application, the +``request.json_body`` attribute will be available in the view callable body. + +.. code-block:: javascript + + @view_config(renderer='string') + def aview(request): + print request.json_body + return 'OK' + +For the above view, printed to the console will be: + +.. code-block:: python + + {u'a': 1} + More Details ++++++++++++ diff --git a/docs/whatsnew-1.1.rst b/docs/whatsnew-1.1.rst index fdf3b1c74..a9df38a45 100644 --- a/docs/whatsnew-1.1.rst +++ b/docs/whatsnew-1.1.rst @@ -94,10 +94,14 @@ Default HTTP Exception View Minor Feature Additions ----------------------- -- New request attribute: ``json``. If the request's ``content_type`` is - ``application/json``, this attribute will contain the JSON-decoded - variant of the request body. If the request's ``content_type`` is not - ``application/json``, this attribute will be ``None``. +- The :meth:`pyramid.config.Configurator.scan` method has grown a ``**kw`` + argument. ``kw`` argument represents a set of keyword arguments to pass to + the Venusian ``Scanner`` object created by Pyramid. (See the + :term:`Venusian` documentation for more information about ``Scanner``). + +- New request property: ``json_body``. This property will return the + JSON-decoded variant of the request body. If the request body is not + well-formed JSON, this property will raise an exception. - A new value ``http_cache`` can be used as a :term:`view configuration` parameter. diff --git a/pyramid/config.py b/pyramid/config.py index 3ad872e27..2e018f66f 100644 --- a/pyramid/config.py +++ b/pyramid/config.py @@ -1140,6 +1140,12 @@ class Configurator(object): tuple as ``http_cache`` with the first element of ``None``, e.g.: ``(None, {'public':True})``. + If you wish to prevent a view that uses ``http_cache`` in its + configuration from having its caching response headers changed by + this machinery, set ``response.cache_control.prevent_auto = True`` + before returning the response from the view. This effectively + disables any HTTP caching done by ``http_cache`` for that response. + wrapper The :term:`view name` of a different :term:`view @@ -1950,7 +1956,7 @@ class Configurator(object): return mapper # this is *not* an action method (uses caller_package) - def scan(self, package=None, categories=None): + def scan(self, package=None, categories=None, **kw): """Scan a Python package and any of its subpackages for objects marked with :term:`configuration decoration` such as :class:`pyramid.view.view_config`. Any decorated object found will @@ -1970,12 +1976,28 @@ class Configurator(object): :class:`pyramid.view.view_config`. See the :term:`Venusian` documentation for more information about limiting a scan by using an explicit set of categories. + + To perform a ``scan``, Pyramid creates a Venusian ``Scanner`` object. + The ``kw`` argument represents a set of keyword arguments to pass to + the Venusian ``Scanner`` object's constructor. See the + :term:`venusian` documentation (its ``Scanner`` class) for more + information about the constructor. By default, the only keyword + arguments passed to the Scanner constructor are ``{'config':self}`` + where ``self`` is this configurator object. This services the + requirement of all built-in Pyramid decorators, but extension systems + may require additional arguments. Providing this argument is not + often necessary; it's an advanced usage. + + .. note:: the ``**kw`` argument is new in Pyramid 1.1 """ package = self.maybe_dotted(package) if package is None: # pragma: no cover package = caller_package() - scanner = self.venusian.Scanner(config=self) + scankw = {'config':self} + scankw.update(kw) + + scanner = self.venusian.Scanner(**scankw) scanner.scan(package, categories=categories) @action_method @@ -2866,54 +2888,42 @@ class MultiView(object): continue raise PredicateMismatch(self.name) -def wraps_view(wrapped): +def wraps_view(wrapper): def inner(self, view): - wrapped_view = wrapped(self, view) - return preserve_view_attrs(view, wrapped_view) + wrapper_view = wrapper(self, view) + return preserve_view_attrs(view, wrapper_view) return inner -def preserve_view_attrs(view, wrapped_view): - if wrapped_view is view: +def preserve_view_attrs(view, wrapper): + if wrapper is view: return view + original_view = getattr(view, '__original_view__', None) + if original_view is None: original_view = view - wrapped_view.__original_view__ = original_view - wrapped_view.__module__ = view.__module__ - wrapped_view.__doc__ = view.__doc__ - try: - wrapped_view.__name__ = view.__name__ - except AttributeError: - wrapped_view.__name__ = repr(view) - try: - wrapped_view.__permitted__ = view.__permitted__ - except AttributeError: - pass - try: - wrapped_view.__call_permissive__ = view.__call_permissive__ - except AttributeError: - pass - try: - wrapped_view.__permission__ = view.__permission__ - except AttributeError: - pass - try: - wrapped_view.__predicated__ = view.__predicated__ - except AttributeError: - pass - try: - wrapped_view.__predicates__ = view.__predicates__ - except AttributeError: - pass - try: - wrapped_view.__accept__ = view.__accept__ - except AttributeError: - pass + + wrapper.__wraps__ = view + wrapper.__original_view__ = original_view + wrapper.__module__ = view.__module__ + wrapper.__doc__ = view.__doc__ + try: - wrapped_view.__order__ = view.__order__ + wrapper.__name__ = view.__name__ except AttributeError: - pass - return wrapped_view + wrapper.__name__ = repr(view) + + # attrs that may not exist on "view", but, if so, must be attached to + # "wrapped view" + for attr in ('__permitted__', '__call_permissive__', '__permission__', + '__predicated__', '__predicates__', '__accept__', + '__order__'): + try: + setattr(wrapper, attr, getattr(view, attr)) + except AttributeError: + pass + + return wrapper class ViewDeriver(object): def __init__(self, **kw): @@ -2929,8 +2939,8 @@ class ViewDeriver(object): self.authdebug_view( self.secured_view( self.owrapped_view( - self.decorated_view( - self.http_cached_view( + self.http_cached_view( + self.decorated_view( self.rendered_view( self.mapped_view(view))))))))) @@ -2970,11 +2980,12 @@ class ViewDeriver(object): @wraps_view def http_cached_view(self, view): seconds = self.kw.get('http_cache') - options = {} if seconds is None: return view + options = {} + if isinstance(seconds, (tuple, list)): try: seconds, options = seconds @@ -2985,9 +2996,9 @@ class ViewDeriver(object): def wrapper(context, request): response = view(context, request) - cache_expires = getattr(response, 'cache_expires', None) - if cache_expires is not None: - cache_expires(seconds, **options) + cache_control = response.cache_control + if not hasattr(cache_control, 'prevent_auto'): + response.cache_expires(seconds, **options) return response return wrapper @@ -3097,19 +3108,23 @@ class ViewDeriver(object): @wraps_view def rendered_view(self, view): - wrapped_view = view - static_renderer = self.kw.get('renderer') - if static_renderer is None: + # one way or another this wrapper must produce a Response + renderer = self.kw.get('renderer') + if renderer is None: # register a default renderer if you want super-dynamic # rendering. registering a default renderer will also allow # override_renderer to work if a renderer is left unspecified for # a view registration. - return view - - def _rendered_view(context, request): - renderer = static_renderer - result = wrapped_view(context, request) - registry = self.kw['registry'] + return self._response_resolved_view(view) + return self._rendered_view(view, renderer) + + def _rendered_view(self, view, view_renderer): + 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__', {}) @@ -3122,13 +3137,29 @@ class ViewDeriver(object): if '__view__' in attrs: view_inst = attrs.pop('__view__') else: - view_inst = getattr(wrapped_view, '__original_view__', - wrapped_view) + view_inst = getattr(view, '__original_view__', view) response = renderer.render_view(request, result, view_inst, context) return response - return _rendered_view + return rendered_view + + def _response_resolved_view(self, view): + registry = self.registry + if hasattr(registry, '_dont_resolve_responses'): + # for Pyramid unit tests only + return view + + def viewresult_to_response(context, request): + result = view(context, request) + response = registry.queryAdapterOrSelf(result, IResponse) + if response is None: + raise ValueError( + 'Could not convert view return value "%s" into a ' + 'response object' % (result,)) + return response + + return viewresult_to_response @wraps_view def decorated_view(self, view): diff --git a/pyramid/request.py b/pyramid/request.py index a3848461f..1bf044b69 100644 --- a/pyramid/request.py +++ b/pyramid/request.py @@ -491,9 +491,8 @@ class Request(BaseRequest, DeprecatedRequestMethods): return adapted is ob @property - def json(self): - if self.content_type == 'application/json': - return json.loads(self.body, encoding=self.charset) + def json_body(self): + return json.loads(self.body, encoding=self.charset) def route_request_iface(name, bases=()): diff --git a/pyramid/router.py b/pyramid/router.py index 458237a8c..d011b1245 100644 --- a/pyramid/router.py +++ b/pyramid/router.py @@ -159,7 +159,7 @@ class Router(object): msg = request.path_info raise HTTPNotFound(msg) else: - result = view_callable(context, request) + response = view_callable(context, request) # handle exceptions raised during root finding and view-exec except Exception, why: @@ -173,14 +173,7 @@ class Router(object): if view_callable is None: raise - result = view_callable(why, request) - - # process the response - response = registry.queryAdapterOrSelf(result, IResponse) - if response is None: - raise ValueError( - 'Could not convert view return value "%s" into a ' - 'response object' % (result,)) + response = view_callable(why, request) has_listeners and notify(NewResponse(request, response)) diff --git a/pyramid/tests/restbugapp/views.py b/pyramid/tests/restbugapp/views.py index b94851099..2ace59fa9 100644 --- a/pyramid/tests/restbugapp/views.py +++ b/pyramid/tests/restbugapp/views.py @@ -1,4 +1,4 @@ -from webob import Response +from pyramid.response import Response class BaseRESTView(object): def __init__(self, context, request): diff --git a/pyramid/tests/test_config.py b/pyramid/tests/test_config.py index fa1ad2b88..d7e62da0a 100644 --- a/pyramid/tests/test_config.py +++ b/pyramid/tests/test_config.py @@ -10,7 +10,9 @@ except: class ConfiguratorTests(unittest.TestCase): def _makeOne(self, *arg, **kw): from pyramid.config import Configurator - return Configurator(*arg, **kw) + config = Configurator(*arg, **kw) + config.registry._dont_resolve_responses = True + return config def _registerRenderer(self, config, name='.txt'): from pyramid.interfaces import IRendererFactory @@ -211,7 +213,7 @@ class ConfiguratorTests(unittest.TestCase): view = self._getViewCallable(config, ctx_iface=IExceptionResponse, request_iface=IRequest) - self.assertTrue(view is default_exceptionresponse_view) + self.assertTrue(view.__wraps__ is default_exceptionresponse_view) def test_ctor_exceptionresponse_view_None(self): from pyramid.interfaces import IExceptionResponse @@ -230,7 +232,7 @@ class ConfiguratorTests(unittest.TestCase): view = self._getViewCallable(config, ctx_iface=IExceptionResponse, request_iface=IRequest) - self.assertTrue(view is exceptionresponse_view) + self.assertTrue(view.__wraps__ is exceptionresponse_view) def test_with_package_module(self): from pyramid.tests import test_configuration @@ -2848,6 +2850,11 @@ class ConfiguratorTests(unittest.TestCase): result = render_view_to_response(ctx, req, '') self.assertEqual(result, 'grokked') + def test_scan_integration_with_extra_kw(self): + config = self._makeOne(autocommit=True) + config.scan('pyramid.tests.venusianapp', a=1) + self.assertEqual(config.a, 1) + def test_testing_securitypolicy(self): from pyramid.testing import DummySecurityPolicy config = self._makeOne(autocommit=True) @@ -3190,8 +3197,10 @@ class TestConfiguratorDeprecatedFeatures(unittest.TestCase): def _makeOne(self, *arg, **kw): from pyramid.config import Configurator - return Configurator(*arg, **kw) - + config = Configurator(*arg, **kw) + config.registry._dont_resolve_responses = True + return config + def _getRouteRequestIface(self, config, name): from pyramid.interfaces import IRouteRequest iface = config.registry.getUtility(IRouteRequest, name) @@ -3498,29 +3507,31 @@ class TestViewDeriver(unittest.TestCase): self.config.registry.registerUtility(policy, IAuthorizationPolicy) def test_requestonly_function(self): + response = DummyResponse() def view(request): - return 'OK' + return response deriver = self._makeOne() result = deriver(view) self.assertFalse(result is view) - self.assertEqual(result(None, None), 'OK') + self.assertEqual(result(None, None), response) def test_requestonly_function_with_renderer(self): + response = DummyResponse() class moo(object): def render_view(inself, req, resp, view_inst, ctx): self.assertEqual(req, request) self.assertEqual(resp, 'OK') self.assertEqual(view_inst, view) self.assertEqual(ctx, context) - return 'moo' + return response def view(request): return 'OK' deriver = self._makeOne(renderer=moo()) result = deriver(view) - self.assertFalse(result is view) + self.assertFalse(result.__wraps__ is view) request = self._makeRequest() context = testing.DummyResource() - self.assertEqual(result(context, request), 'moo') + self.assertEqual(result(context, request), response) def test_requestonly_function_with_renderer_request_override(self): def moo(info): @@ -3542,46 +3553,50 @@ class TestViewDeriver(unittest.TestCase): self.assertEqual(result(context, request).body, 'moo') def test_requestonly_function_with_renderer_request_has_view(self): + response = DummyResponse() class moo(object): def render_view(inself, req, resp, view_inst, ctx): self.assertEqual(req, request) self.assertEqual(resp, 'OK') self.assertEqual(view_inst, 'view') self.assertEqual(ctx, context) - return 'moo' + return response def view(request): return 'OK' deriver = self._makeOne(renderer=moo()) result = deriver(view) - self.assertFalse(result is view) + self.assertFalse(result.__wraps__ is view) request = self._makeRequest() request.__view__ = 'view' context = testing.DummyResource() - self.assertEqual(result(context, request), 'moo') + r = result(context, request) + self.assertEqual(r, response) self.assertFalse(hasattr(request, '__view__')) def test_class_without_attr(self): + response = DummyResponse() class View(object): def __init__(self, request): pass def __call__(self): - return 'OK' + return response deriver = self._makeOne() result = deriver(View) request = self._makeRequest() - self.assertEqual(result(None, request), 'OK') + self.assertEqual(result(None, request), response) self.assertEqual(request.__view__.__class__, View) def test_class_with_attr(self): + response = DummyResponse() class View(object): def __init__(self, request): pass def another(self): - return 'OK' + return response deriver = self._makeOne(attr='another') result = deriver(View) request = self._makeRequest() - self.assertEqual(result(None, request), 'OK') + self.assertEqual(result(None, request), response) self.assertEqual(request.__view__.__class__, View) def test_as_function_context_and_request(self): @@ -3589,13 +3604,14 @@ class TestViewDeriver(unittest.TestCase): return 'OK' deriver = self._makeOne() result = deriver(view) - self.assertTrue(result is view) + self.assertTrue(result.__wraps__ is view) self.assertFalse(hasattr(result, '__call_permissive__')) self.assertEqual(view(None, None), 'OK') def test_as_function_requestonly(self): + response = DummyResponse() def view(request): - return 'OK' + return response deriver = self._makeOne() result = deriver(view) self.assertFalse(result is view) @@ -3603,14 +3619,15 @@ class TestViewDeriver(unittest.TestCase): self.assertEqual(view.__doc__, result.__doc__) self.assertEqual(view.__name__, result.__name__) self.assertFalse(hasattr(result, '__call_permissive__')) - self.assertEqual(result(None, None), 'OK') + self.assertEqual(result(None, None), response) def test_as_newstyle_class_context_and_request(self): + response = DummyResponse() class view(object): def __init__(self, context, request): pass def __call__(self): - return 'OK' + return response deriver = self._makeOne() result = deriver(view) self.assertFalse(result is view) @@ -3619,15 +3636,16 @@ class TestViewDeriver(unittest.TestCase): self.assertEqual(view.__name__, result.__name__) self.assertFalse(hasattr(result, '__call_permissive__')) request = self._makeRequest() - self.assertEqual(result(None, request), 'OK') + self.assertEqual(result(None, request), response) self.assertEqual(request.__view__.__class__, view) def test_as_newstyle_class_requestonly(self): + response = DummyResponse() class view(object): def __init__(self, context, request): pass def __call__(self): - return 'OK' + return response deriver = self._makeOne() result = deriver(view) self.assertFalse(result is view) @@ -3636,15 +3654,16 @@ class TestViewDeriver(unittest.TestCase): self.assertEqual(view.__name__, result.__name__) self.assertFalse(hasattr(result, '__call_permissive__')) request = self._makeRequest() - self.assertEqual(result(None, request), 'OK') + self.assertEqual(result(None, request), response) self.assertEqual(request.__view__.__class__, view) def test_as_oldstyle_class_context_and_request(self): + response = DummyResponse() class view: def __init__(self, context, request): pass def __call__(self): - return 'OK' + return response deriver = self._makeOne() result = deriver(view) self.assertFalse(result is view) @@ -3653,15 +3672,16 @@ class TestViewDeriver(unittest.TestCase): self.assertEqual(view.__name__, result.__name__) self.assertFalse(hasattr(result, '__call_permissive__')) request = self._makeRequest() - self.assertEqual(result(None, request), 'OK') + self.assertEqual(result(None, request), response) self.assertEqual(request.__view__.__class__, view) def test_as_oldstyle_class_requestonly(self): + response = DummyResponse() class view: def __init__(self, context, request): pass def __call__(self): - return 'OK' + return response deriver = self._makeOne() result = deriver(view) self.assertFalse(result is view) @@ -3670,24 +3690,26 @@ class TestViewDeriver(unittest.TestCase): self.assertEqual(view.__name__, result.__name__) self.assertFalse(hasattr(result, '__call_permissive__')) request = self._makeRequest() - self.assertEqual(result(None, request), 'OK') + self.assertEqual(result(None, request), response) self.assertEqual(request.__view__.__class__, view) def test_as_instance_context_and_request(self): + response = DummyResponse() class View: def __call__(self, context, request): - return 'OK' + return response view = View() deriver = self._makeOne() result = deriver(view) - self.assertTrue(result is view) + self.assertTrue(result.__wraps__ is view) self.assertFalse(hasattr(result, '__call_permissive__')) - self.assertEqual(result(None, None), 'OK') + self.assertEqual(result(None, None), response) def test_as_instance_requestonly(self): + response = DummyResponse() class View: def __call__(self, request): - return 'OK' + return response view = View() deriver = self._makeOne() result = deriver(view) @@ -3696,10 +3718,11 @@ class TestViewDeriver(unittest.TestCase): self.assertEqual(view.__doc__, result.__doc__) self.assertTrue('instance' in result.__name__) self.assertFalse(hasattr(result, '__call_permissive__')) - self.assertEqual(result(None, None), 'OK') + self.assertEqual(result(None, None), response) def test_with_debug_authorization_no_authpol(self): - view = lambda *arg: 'OK' + response = DummyResponse() + view = lambda *arg: response self.config.registry.settings = dict( debug_authorization=True, reload_templates=True) logger = self._registerLogger() @@ -3712,7 +3735,7 @@ class TestViewDeriver(unittest.TestCase): request = self._makeRequest() request.view_name = 'view_name' request.url = 'url' - self.assertEqual(result(None, request), 'OK') + self.assertEqual(result(None, request), response) self.assertEqual(len(logger.messages), 1) self.assertEqual(logger.messages[0], "debug_authorization of url url (view name " @@ -3720,7 +3743,8 @@ class TestViewDeriver(unittest.TestCase): "(no authorization policy in use)") def test_with_debug_authorization_authn_policy_no_authz_policy(self): - view = lambda *arg: 'OK' + response = DummyResponse() + view = lambda *arg: response self.config.registry.settings = dict(debug_authorization=True) from pyramid.interfaces import IAuthenticationPolicy policy = DummySecurityPolicy(False) @@ -3735,7 +3759,7 @@ class TestViewDeriver(unittest.TestCase): request = self._makeRequest() request.view_name = 'view_name' request.url = 'url' - self.assertEqual(result(None, request), 'OK') + self.assertEqual(result(None, request), response) self.assertEqual(len(logger.messages), 1) self.assertEqual(logger.messages[0], "debug_authorization of url url (view name " @@ -3743,7 +3767,8 @@ class TestViewDeriver(unittest.TestCase): "(no authorization policy in use)") def test_with_debug_authorization_authz_policy_no_authn_policy(self): - view = lambda *arg: 'OK' + response = DummyResponse() + view = lambda *arg: response self.config.registry.settings = dict(debug_authorization=True) from pyramid.interfaces import IAuthorizationPolicy policy = DummySecurityPolicy(False) @@ -3758,7 +3783,7 @@ class TestViewDeriver(unittest.TestCase): request = self._makeRequest() request.view_name = 'view_name' request.url = 'url' - self.assertEqual(result(None, request), 'OK') + self.assertEqual(result(None, request), response) self.assertEqual(len(logger.messages), 1) self.assertEqual(logger.messages[0], "debug_authorization of url url (view name " @@ -3766,7 +3791,8 @@ class TestViewDeriver(unittest.TestCase): "(no authorization policy in use)") def test_with_debug_authorization_no_permission(self): - view = lambda *arg: 'OK' + response = DummyResponse() + view = lambda *arg: response self.config.registry.settings = dict( debug_authorization=True, reload_templates=True) self._registerSecurityPolicy(True) @@ -3780,7 +3806,7 @@ class TestViewDeriver(unittest.TestCase): request = self._makeRequest() request.view_name = 'view_name' request.url = 'url' - self.assertEqual(result(None, request), 'OK') + self.assertEqual(result(None, request), response) self.assertEqual(len(logger.messages), 1) self.assertEqual(logger.messages[0], "debug_authorization of url url (view name " @@ -3788,7 +3814,8 @@ class TestViewDeriver(unittest.TestCase): "no permission registered)") def test_debug_auth_permission_authpol_permitted(self): - view = lambda *arg: 'OK' + response = DummyResponse() + view = lambda *arg: response self.config.registry.settings = dict( debug_authorization=True, reload_templates=True) logger = self._registerLogger() @@ -3798,18 +3825,19 @@ class TestViewDeriver(unittest.TestCase): self.assertEqual(view.__module__, result.__module__) self.assertEqual(view.__doc__, result.__doc__) self.assertEqual(view.__name__, result.__name__) - self.assertEqual(result.__call_permissive__, view) + self.assertEqual(result.__call_permissive__.__wraps__, view) request = self._makeRequest() request.view_name = 'view_name' request.url = 'url' - self.assertEqual(result(None, request), 'OK') + self.assertEqual(result(None, request), response) self.assertEqual(len(logger.messages), 1) self.assertEqual(logger.messages[0], "debug_authorization of url url (view name " "'view_name' against context None): True") def test_debug_auth_permission_authpol_permitted_no_request(self): - view = lambda *arg: 'OK' + response = DummyResponse() + view = lambda *arg: response self.config.registry.settings = dict( debug_authorization=True, reload_templates=True) logger = self._registerLogger() @@ -3819,8 +3847,8 @@ class TestViewDeriver(unittest.TestCase): self.assertEqual(view.__module__, result.__module__) self.assertEqual(view.__doc__, result.__doc__) self.assertEqual(view.__name__, result.__name__) - self.assertEqual(result.__call_permissive__, view) - self.assertEqual(result(None, None), 'OK') + self.assertEqual(result.__call_permissive__.__wraps__, view) + self.assertEqual(result(None, None), response) self.assertEqual(len(logger.messages), 1) self.assertEqual(logger.messages[0], "debug_authorization of url None (view name " @@ -3828,7 +3856,8 @@ class TestViewDeriver(unittest.TestCase): def test_debug_auth_permission_authpol_denied(self): from pyramid.httpexceptions import HTTPForbidden - view = lambda *arg: 'OK' + response = DummyResponse() + view = lambda *arg: response self.config.registry.settings = dict( debug_authorization=True, reload_templates=True) logger = self._registerLogger() @@ -3838,7 +3867,7 @@ class TestViewDeriver(unittest.TestCase): self.assertEqual(view.__module__, result.__module__) self.assertEqual(view.__doc__, result.__doc__) self.assertEqual(view.__name__, result.__name__) - self.assertEqual(result.__call_permissive__, view) + self.assertEqual(result.__call_permissive__.__wraps__, view) request = self._makeRequest() request.view_name = 'view_name' request.url = 'url' @@ -3866,7 +3895,8 @@ class TestViewDeriver(unittest.TestCase): self.assertEqual(permitted, False) def test_debug_auth_permission_authpol_overridden(self): - view = lambda *arg: 'OK' + response = DummyResponse() + view = lambda *arg: response self.config.registry.settings = dict( debug_authorization=True, reload_templates=True) logger = self._registerLogger() @@ -3880,14 +3910,15 @@ class TestViewDeriver(unittest.TestCase): request = self._makeRequest() request.view_name = 'view_name' request.url = 'url' - self.assertEqual(result(None, request), 'OK') + self.assertEqual(result(None, request), response) self.assertEqual(len(logger.messages), 1) self.assertEqual(logger.messages[0], "debug_authorization of url url (view name " "'view_name' against context None): False") def test_secured_view_authn_policy_no_authz_policy(self): - view = lambda *arg: 'OK' + response = DummyResponse() + view = lambda *arg: response self.config.registry.settings = {} from pyramid.interfaces import IAuthenticationPolicy policy = DummySecurityPolicy(False) @@ -3901,10 +3932,11 @@ class TestViewDeriver(unittest.TestCase): request = self._makeRequest() request.view_name = 'view_name' request.url = 'url' - self.assertEqual(result(None, request), 'OK') + self.assertEqual(result(None, request), response) def test_secured_view_authz_policy_no_authn_policy(self): - view = lambda *arg: 'OK' + response = DummyResponse() + view = lambda *arg: response self.config.registry.settings = {} from pyramid.interfaces import IAuthorizationPolicy policy = DummySecurityPolicy(False) @@ -3918,10 +3950,11 @@ class TestViewDeriver(unittest.TestCase): request = self._makeRequest() request.view_name = 'view_name' request.url = 'url' - self.assertEqual(result(None, request), 'OK') + self.assertEqual(result(None, request), response) def test_with_predicates_all(self): - view = lambda *arg: 'OK' + response = DummyResponse() + view = lambda *arg: response predicates = [] def predicate1(context, request): predicates.append(True) @@ -3934,7 +3967,7 @@ class TestViewDeriver(unittest.TestCase): request = self._makeRequest() request.method = 'POST' next = result(None, None) - self.assertEqual(next, 'OK') + self.assertEqual(next, response) self.assertEqual(predicates, [True, True]) def test_with_predicates_checker(self): @@ -3972,7 +4005,7 @@ class TestViewDeriver(unittest.TestCase): self.assertEqual(predicates, [True, True]) def test_with_wrapper_viewname(self): - from webob import Response + from pyramid.response import Response from pyramid.interfaces import IView from pyramid.interfaces import IViewClassifier inner_response = Response('OK') @@ -3981,7 +4014,8 @@ class TestViewDeriver(unittest.TestCase): def outer_view(context, request): self.assertEqual(request.wrapped_response, inner_response) self.assertEqual(request.wrapped_body, inner_response.body) - self.assertEqual(request.wrapped_view, inner_view) + self.assertEqual(request.wrapped_view.__original_view__, + inner_view) return Response('outer ' + request.wrapped_body) self.config.registry.registerAdapter( outer_view, (IViewClassifier, None, None), IView, 'owrap') @@ -3996,7 +4030,7 @@ class TestViewDeriver(unittest.TestCase): self.assertEqual(response.body, 'outer OK') def test_with_wrapper_viewname_notfound(self): - from webob import Response + from pyramid.response import Response inner_response = Response('OK') def inner_view(context, request): return inner_response @@ -4006,13 +4040,14 @@ class TestViewDeriver(unittest.TestCase): self.assertRaises(ValueError, wrapped, None, request) def test_as_newstyle_class_context_and_request_attr_and_renderer(self): + response = DummyResponse() class renderer(object): def render_view(inself, req, resp, view_inst, ctx): self.assertEqual(req, request) self.assertEqual(resp, {'a':'1'}) self.assertEqual(view_inst.__class__, View) self.assertEqual(ctx, context) - return resp + return response class View(object): def __init__(self, context, request): pass @@ -4026,16 +4061,17 @@ class TestViewDeriver(unittest.TestCase): self.assertEqual(result.__name__, View.__name__) request = self._makeRequest() context = testing.DummyResource() - self.assertEqual(result(context, request), {'a':'1'}) + self.assertEqual(result(context, request), response) def test_as_newstyle_class_requestonly_attr_and_renderer(self): + response = DummyResponse() class renderer(object): def render_view(inself, req, resp, view_inst, ctx): self.assertEqual(req, request) self.assertEqual(resp, {'a':'1'}) self.assertEqual(view_inst.__class__, View) self.assertEqual(ctx, context) - return resp + return response class View(object): def __init__(self, request): pass @@ -4049,16 +4085,17 @@ class TestViewDeriver(unittest.TestCase): self.assertEqual(result.__name__, View.__name__) request = self._makeRequest() context = testing.DummyResource() - self.assertEqual(result(context, request), {'a':'1'}) + self.assertEqual(result(context, request), response) def test_as_oldstyle_cls_context_request_attr_and_renderer(self): + response = DummyResponse() class renderer(object): def render_view(inself, req, resp, view_inst, ctx): self.assertEqual(req, request) self.assertEqual(resp, {'a':'1'}) self.assertEqual(view_inst.__class__, View) self.assertEqual(ctx, context) - return resp + return response class View: def __init__(self, context, request): pass @@ -4072,16 +4109,17 @@ class TestViewDeriver(unittest.TestCase): self.assertEqual(result.__name__, View.__name__) request = self._makeRequest() context = testing.DummyResource() - self.assertEqual(result(context, request), {'a':'1'}) + self.assertEqual(result(context, request), response) def test_as_oldstyle_cls_requestonly_attr_and_renderer(self): + response = DummyResponse() class renderer(object): def render_view(inself, req, resp, view_inst, ctx): self.assertEqual(req, request) self.assertEqual(resp, {'a':'1'}) self.assertEqual(view_inst.__class__, View) self.assertEqual(ctx, context) - return resp + return response class View: def __init__(self, request): pass @@ -4095,16 +4133,17 @@ class TestViewDeriver(unittest.TestCase): self.assertEqual(result.__name__, View.__name__) request = self._makeRequest() context = testing.DummyResource() - self.assertEqual(result(context, request), {'a':'1'}) + self.assertEqual(result(context, request), response) def test_as_instance_context_and_request_attr_and_renderer(self): + response = DummyResponse() class renderer(object): def render_view(inself, req, resp, view_inst, ctx): self.assertEqual(req, request) self.assertEqual(resp, {'a':'1'}) self.assertEqual(view_inst, view) self.assertEqual(ctx, context) - return resp + return response class View: def index(self, context, request): return {'a':'1'} @@ -4116,16 +4155,17 @@ class TestViewDeriver(unittest.TestCase): self.assertEqual(result.__doc__, view.__doc__) request = self._makeRequest() context = testing.DummyResource() - self.assertEqual(result(context, request), {'a':'1'}) + self.assertEqual(result(context, request), response) def test_as_instance_requestonly_attr_and_renderer(self): + response = DummyResponse() class renderer(object): def render_view(inself, req, resp, view_inst, ctx): self.assertEqual(req, request) self.assertEqual(resp, {'a':'1'}) self.assertEqual(view_inst, view) self.assertEqual(ctx, context) - return resp + return response class View: def index(self, request): return {'a':'1'} @@ -4137,58 +4177,63 @@ class TestViewDeriver(unittest.TestCase): self.assertEqual(result.__doc__, view.__doc__) request = self._makeRequest() context = testing.DummyResource() - self.assertEqual(result(context, request), {'a':'1'}) + self.assertEqual(result(context, request), response) def test_with_view_mapper_config_specified(self): + response = DummyResponse() class mapper(object): def __init__(self, **kw): self.kw = kw def __call__(self, view): def wrapped(context, request): - return 'OK' + return response return wrapped def view(context, request): return 'NOTOK' deriver = self._makeOne(mapper=mapper) result = deriver(view) - self.assertFalse(result is view) - self.assertEqual(result(None, None), 'OK') + self.assertFalse(result.__wraps__ is view) + self.assertEqual(result(None, None), response) def test_with_view_mapper_view_specified(self): + from pyramid.response import Response + response = Response() def mapper(**kw): def inner(view): def superinner(context, request): self.assertEqual(request, None) - return 'OK' + return response return superinner return inner def view(context, request): return 'NOTOK' view.__view_mapper__ = mapper deriver = self._makeOne() result = deriver(view) - self.assertFalse(result is view) - self.assertEqual(result(None, None), 'OK') + self.assertFalse(result.__wraps__ is view) + self.assertEqual(result(None, None), response) def test_with_view_mapper_default_mapper_specified(self): + from pyramid.response import Response + response = Response() def mapper(**kw): def inner(view): def superinner(context, request): self.assertEqual(request, None) - return 'OK' + return response return superinner return inner self.config.set_view_mapper(mapper) def view(context, request): return 'NOTOK' deriver = self._makeOne() result = deriver(view) - self.assertFalse(result is view) - self.assertEqual(result(None, None), 'OK') + self.assertFalse(result.__wraps__ is view) + self.assertEqual(result(None, None), response) def test_attr_wrapped_view_branching_default_phash(self): from pyramid.config import DEFAULT_PHASH def view(context, request): pass deriver = self._makeOne(phash=DEFAULT_PHASH) result = deriver(view) - self.assertEqual(result, view) + self.assertEqual(result.__wraps__, view) def test_attr_wrapped_view_branching_nondefault_phash(self): def view(context, request): pass @@ -4198,7 +4243,7 @@ class TestViewDeriver(unittest.TestCase): def test_http_cached_view_integer(self): import datetime - from webob import Response + from pyramid.response import Response response = Response('OK') def inner_view(context, request): return response @@ -4218,7 +4263,7 @@ class TestViewDeriver(unittest.TestCase): def test_http_cached_view_timedelta(self): import datetime - from webob import Response + from pyramid.response import Response response = Response('OK') def inner_view(context, request): return response @@ -4238,7 +4283,7 @@ class TestViewDeriver(unittest.TestCase): def test_http_cached_view_tuple(self): import datetime - from webob import Response + from pyramid.response import Response response = Response('OK') def inner_view(context, request): return response @@ -4257,7 +4302,7 @@ class TestViewDeriver(unittest.TestCase): self.assertEqual(headers['Cache-Control'], 'max-age=3600, public') def test_http_cached_view_tuple_seconds_None(self): - from webob import Response + from pyramid.response import Response response = Response('OK') def inner_view(context, request): return response @@ -4273,17 +4318,20 @@ class TestViewDeriver(unittest.TestCase): self.assertFalse('Expires' in headers) self.assertEqual(headers['Cache-Control'], 'public') - def test_http_cached_view_nonresponse_object_returned_downstream(self): + def test_http_cached_view_prevent_auto_set(self): + from pyramid.response import Response + response = Response() + response.cache_control.prevent_auto = True def inner_view(context, request): - return None + return response deriver = self._makeOne(http_cache=3600) result = deriver(inner_view) - self.assertFalse(result is inner_view) - self.assertEqual(inner_view.__module__, result.__module__) - self.assertEqual(inner_view.__doc__, result.__doc__) request = self._makeRequest() result = result(None, request) - self.assertEqual(result, None) # doesn't blow up + self.assertEqual(result, response) # doesn't blow up + headers = dict(result.headerlist) + self.assertFalse('Expires' in headers) + self.assertFalse('Cache-Control' in headers) def test_http_cached_view_bad_tuple(self): from pyramid.exceptions import ConfigurationError @@ -5402,4 +5450,8 @@ def parse_httpdate(s): def assert_similar_datetime(one, two): for attr in ('year', 'month', 'day', 'hour', 'minute'): assert(getattr(one, attr) == getattr(two, attr)) + +from pyramid.interfaces import IResponse +class DummyResponse(object): + implements(IResponse) diff --git a/pyramid/tests/test_integration.py b/pyramid/tests/test_integration.py index dd77d3aec..0ef1e1631 100644 --- a/pyramid/tests/test_integration.py +++ b/pyramid/tests/test_integration.py @@ -39,7 +39,7 @@ class WGSIAppPlusViewConfigTests(unittest.TestCase): reg = config.registry view = reg.adapters.lookup( (IViewClassifier, IRequest, INothing), IView, name='') - self.assertEqual(view, wsgiapptest) + self.assertEqual(view.__original_view__, wsgiapptest) here = os.path.dirname(__file__) staticapp = static(os.path.join(here, 'fixtures')) diff --git a/pyramid/tests/test_request.py b/pyramid/tests/test_request.py index 0c1c78721..74bc25359 100644 --- a/pyramid/tests/test_request.py +++ b/pyramid/tests/test_request.py @@ -233,25 +233,28 @@ class TestRequest(unittest.TestCase): request.registry.registerAdapter(adapter, (Foo,), IResponse) self.assertEqual(request.is_response(foo), True) - def test_json_incorrect_mimetype(self): - request = self._makeOne({}) - self.assertEqual(request.json, None) + def test_json_body_invalid_json(self): + request = self._makeOne({'REQUEST_METHOD':'POST'}) + request.body = '{' + self.assertRaises(ValueError, getattr, request, 'json_body') - def test_json_correct_mimetype(self): - request = self._makeOne({}) - request.content_type = 'application/json' + def test_json_body_valid_json(self): + request = self._makeOne({'REQUEST_METHOD':'POST'}) request.body = '{"a":1}' - self.assertEqual(request.json, {'a':1}) + self.assertEqual(request.json_body, {'a':1}) - def test_json_alternate_charset(self): + def test_json_body_alternate_charset(self): from pyramid.compat import json - request = self._makeOne({}) - request.content_type = 'application/json' + request = self._makeOne({'REQUEST_METHOD':'POST'}) request.charset = 'latin-1' la = unicode('La Pe\xc3\xb1a', 'utf-8') body = json.dumps({'a':la}, encoding='latin-1') request.body = body - self.assertEqual(request.json, {'a':la}) + self.assertEqual(request.json_body, {'a':la}) + + def test_json_body_GET_request(self): + request = self._makeOne({'REQUEST_METHOD':'GET'}) + self.assertRaises(ValueError, getattr, request, 'json_body') class TestRequestDeprecatedMethods(unittest.TestCase): def setUp(self): diff --git a/pyramid/tests/test_router.py b/pyramid/tests/test_router.py index 5fd2cf01e..af311cfc2 100644 --- a/pyramid/tests/test_router.py +++ b/pyramid/tests/test_router.py @@ -4,9 +4,8 @@ from pyramid import testing class TestRouter(unittest.TestCase): def setUp(self): - testing.setUp() - from pyramid.threadlocal import get_current_registry - self.registry = get_current_registry() + self.config = testing.setUp() + self.registry = self.config.registry def tearDown(self): testing.tearDown() @@ -242,7 +241,8 @@ class TestRouter(unittest.TestCase): self._registerTraverserFactory(context) environ = self._makeEnviron() view = DummyView('abc') - self._registerView(view, '', IViewClassifier, None, None) + self._registerView(self.config.derive_view(view), '', IViewClassifier, + None, None) router = self._makeOne() start_response = DummyStartResponse() self.assertRaises(ValueError, router, environ, start_response) @@ -255,7 +255,8 @@ class TestRouter(unittest.TestCase): self._registerTraverserFactory(context) environ = self._makeEnviron() view = DummyView('abc') - self._registerView(view, '', IViewClassifier, None, None) + self._registerView(self.config.derive_view(view), '', + IViewClassifier, None, None) router = self._makeOne() start_response = DummyStartResponse() def make_response(s): @@ -273,7 +274,8 @@ class TestRouter(unittest.TestCase): response.app_iter = ['Hello world'] view = DummyView(response) environ = self._makeEnviron() - self._registerView(view, '', IViewClassifier, None, None) + self._registerView(self.config.derive_view(view), '', + IViewClassifier, None, None) self._registerRootFactory(context) router = self._makeOne() start_response = DummyStartResponse() @@ -856,9 +858,12 @@ class TestRouter(unittest.TestCase): environ = self._makeEnviron() response = DummyResponse() view = DummyView(response, raise_exception=RuntimeError) - self._registerView(view, '', IViewClassifier, IRequest, None) + + self._registerView(self.config.derive_view(view), '', + IViewClassifier, IRequest, None) exception_view = DummyView(None) - self._registerView(exception_view, '', IExceptionViewClassifier, + self._registerView(self.config.derive_view(exception_view), '', + IExceptionViewClassifier, IRequest, RuntimeError) router = self._makeOne() start_response = DummyStartResponse() diff --git a/pyramid/tests/test_view.py b/pyramid/tests/test_view.py index ce00454fc..6bb3b01a0 100644 --- a/pyramid/tests/test_view.py +++ b/pyramid/tests/test_view.py @@ -121,19 +121,6 @@ class RenderViewToIterableTests(BaseTest, unittest.TestCase): secure=True) self.assertEqual(iterable, ()) - def test_call_view_returns_iresponse_adaptable(self): - from pyramid.response import Response - request = self._makeRequest() - context = self._makeContext() - view = make_view('123') - self._registerView(request.registry, view, 'registered') - def str_response(s): - return Response(s) - request.registry.registerAdapter(str_response, (str,), IResponse) - iterable = self._callFUT(context, request, name='registered', - secure=True) - self.assertEqual(iterable, ['123']) - def test_call_view_registered_insecure_no_call_permissive(self): context = self._makeContext() request = self._makeRequest() diff --git a/pyramid/tests/venusianapp/__init__.py b/pyramid/tests/venusianapp/__init__.py new file mode 100644 index 000000000..ce5e07238 --- /dev/null +++ b/pyramid/tests/venusianapp/__init__.py @@ -0,0 +1,14 @@ +import venusian + +def foo(wrapped): + def bar(scanner, name, wrapped): + scanner.config.a = scanner.a + venusian.attach(wrapped, bar) + return wrapped + +@foo +def hello(): + pass + +hello() # appease coverage + diff --git a/pyramid/view.py b/pyramid/view.py index ea20a19c2..ef7352301 100644 --- a/pyramid/view.py +++ b/pyramid/view.py @@ -4,7 +4,6 @@ import venusian from zope.interface import providedBy from zope.deprecation import deprecated -from pyramid.interfaces import IResponse from pyramid.interfaces import IRoutesMapper from pyramid.interfaces import IView from pyramid.interfaces import IViewClassifier @@ -101,11 +100,6 @@ def render_view_to_iterable(context, request, name='', secure=True): response = render_view_to_response(context, request, name, secure) if response is None: return None - try: - reg = request.registry - except AttributeError: - reg = get_current_registry() - response = reg.queryAdapterOrSelf(response, IResponse) return response.app_iter def render_view(context, request, name='', secure=True): |
