summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES.txt26
-rw-r--r--RELEASING.txt25
-rw-r--r--docs/api/request.rst10
-rw-r--r--docs/designdefense.rst9
-rw-r--r--docs/glossary.rst3
-rw-r--r--docs/narr/sessions.rst2
-rw-r--r--docs/narr/webob.rst54
-rw-r--r--docs/whatsnew-1.1.rst12
-rw-r--r--pyramid/config.py149
-rw-r--r--pyramid/request.py5
-rw-r--r--pyramid/router.py11
-rw-r--r--pyramid/tests/restbugapp/views.py2
-rw-r--r--pyramid/tests/test_config.py236
-rw-r--r--pyramid/tests/test_integration.py2
-rw-r--r--pyramid/tests/test_request.py25
-rw-r--r--pyramid/tests/test_router.py21
-rw-r--r--pyramid/tests/test_view.py13
-rw-r--r--pyramid/tests/venusianapp/__init__.py14
-rw-r--r--pyramid/view.py6
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):