summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES.txt10
-rw-r--r--TODO.txt10
-rw-r--r--docs/api/request.rst7
-rw-r--r--docs/designdefense.rst9
-rw-r--r--docs/whatsnew-1.1.rst10
-rw-r--r--pyramid/config.py22
-rw-r--r--pyramid/request.py7
-rw-r--r--pyramid/tests/test_config.py5
-rw-r--r--pyramid/tests/test_request.py20
-rw-r--r--pyramid/tests/venusianapp/__init__.py14
10 files changed, 107 insertions, 7 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index 67163d3e7..041ff0bb7 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -4,6 +4,16 @@ Next release
Features
--------
+- 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 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``.
+
- A new value ``http_cache`` can be used as a view configuration
parameter.
diff --git a/TODO.txt b/TODO.txt
index fc64163e1..ab0e6da41 100644
--- a/TODO.txt
+++ b/TODO.txt
@@ -6,6 +6,16 @@ Must-Have
- Github issues fixes.
+- add_route discriminator wrong
+
+- tutorial models.initialize_sql doesn't match scaffold
+ (DBSession.rollback()/transaction.abort() in scaffold vs. "pass" in
+ tutorial)
+
+- Allow views to override http_cache headers.
+
+- request.JSON dictionary?
+
Should-Have
-----------
diff --git a/docs/api/request.rst b/docs/api/request.rst
index 27ce395ac..5dfb2ae9a 100644
--- a/docs/api/request.rst
+++ b/docs/api/request.rst
@@ -180,6 +180,13 @@
object (exposed to view code as ``request.response``) to influence
rendered response behavior.
+ .. 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``.
+
.. note::
For information about the API of a :term:`multidict` structure (such as
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/whatsnew-1.1.rst b/docs/whatsnew-1.1.rst
index 783f2caaa..a6bb8e99d 100644
--- a/docs/whatsnew-1.1.rst
+++ b/docs/whatsnew-1.1.rst
@@ -94,6 +94,16 @@ Default HTTP Exception View
Minor Feature Additions
-----------------------
+- 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 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``.
+
- 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 41af9e832..c4f75c39d 100644
--- a/pyramid/config.py
+++ b/pyramid/config.py
@@ -1085,7 +1085,7 @@ class Configurator(object):
The ``renderer`` attribute is optional. If it is not
defined, the "null" renderer is assumed (no rendering is
performed and the value is passed back to the upstream
- :app:`Pyramid` machinery unmolested).
+ :app:`Pyramid` machinery unmodified).
http_cache
@@ -1950,7 +1950,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 +1970,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
diff --git a/pyramid/request.py b/pyramid/request.py
index cc5137869..a3848461f 100644
--- a/pyramid/request.py
+++ b/pyramid/request.py
@@ -10,6 +10,7 @@ from pyramid.interfaces import IResponse
from pyramid.interfaces import ISessionFactory
from pyramid.interfaces import IResponseFactory
+from pyramid.compat import json
from pyramid.exceptions import ConfigurationError
from pyramid.decorator import reify
from pyramid.response import Response
@@ -489,6 +490,12 @@ class Request(BaseRequest, DeprecatedRequestMethods):
return False
return adapted is ob
+ @property
+ def json(self):
+ if self.content_type == 'application/json':
+ return json.loads(self.body, encoding=self.charset)
+
+
def route_request_iface(name, bases=()):
iface = InterfaceClass('%s_IRequest' % name, bases=bases)
# for exception view lookups
diff --git a/pyramid/tests/test_config.py b/pyramid/tests/test_config.py
index 4827cdd70..ad5e5a89a 100644
--- a/pyramid/tests/test_config.py
+++ b/pyramid/tests/test_config.py
@@ -2850,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)
diff --git a/pyramid/tests/test_request.py b/pyramid/tests/test_request.py
index 76426b8a8..e65d484ed 100644
--- a/pyramid/tests/test_request.py
+++ b/pyramid/tests/test_request.py
@@ -233,6 +233,26 @@ 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_correct_mimetype(self):
+ request = self._makeOne({'REQUEST_METHOD':'POST'})
+ request.content_type = 'application/json'
+ request.body = '{"a":1}'
+ self.assertEqual(request.json, {'a':1})
+
+ def test_json_alternate_charset(self):
+ from pyramid.compat import json
+ request = self._makeOne({'REQUEST_METHOD':'POST'})
+ request.content_type = 'application/json'
+ 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})
+
class TestRequestDeprecatedMethods(unittest.TestCase):
def setUp(self):
self.config = testing.setUp()
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
+