summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris McDonough <chrism@agendaless.com>2009-09-16 18:25:31 +0000
committerChris McDonough <chrism@agendaless.com>2009-09-16 18:25:31 +0000
commit470737a5f5a7d86b809b260b9dbc09f266d4b69c (patch)
treea3df44da970fe2e8db956b105acfc228f0319c9c
parent6eca545a5571618bd7498fa68571d8e0e21fecf1 (diff)
downloadpyramid-470737a5f5a7d86b809b260b9dbc09f266d4b69c.tar.gz
pyramid-470737a5f5a7d86b809b260b9dbc09f266d4b69c.tar.bz2
pyramid-470737a5f5a7d86b809b260b9dbc09f266d4b69c.zip
- The ``repoze.bfg.testing.registerDummyRenderer`` API has been
deprecated in favor of ``repoze.bfg.testing.registerTemplateRenderer``. A deprecation warning is *not* issued at import time for the former name; it will exist "forever". - The ``repoze.bfg.templating.renderer_from_cache`` function has been moved to ``repoze.bfg.renderer.template_renderer_factory``. This was never an API, but code in the wild was spotted that used it. A deprecation warning is issued at import time for the former. - Better error message when a wrapper view returns None.
-rw-r--r--CHANGES.txt100
-rw-r--r--docs/api/testing.rst2
-rw-r--r--docs/narr/unittesting.rst6
-rw-r--r--repoze/bfg/testing.py16
-rw-r--r--repoze/bfg/tests/test_testing.py8
-rw-r--r--repoze/bfg/tests/test_zcml.py13
-rw-r--r--repoze/bfg/zcml.py16
7 files changed, 107 insertions, 54 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index 6a9f76a7f..1d9e0c27f 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,37 +1,20 @@
Next release
============
-- When used under Python < 2.6, BFG now has an installation time
- dependency on the ``simplejson`` package.
-
-- The previous release (1.1a2) added a view configuration attribute
- named ``template``. In this release, the attribute has been renamed
- to ``renderer``. This signifies that the attribute is more generic:
- it can now be not just a template name but any renderer name (ala
- ``json``). A "renderer" is an object which accepts the return value
- of a view and converts it to a string. This includes, but is not
- limited to, templating systems.
-
-- In the previous release (1.1a2), the Chameleon text template
- renderer was used if the system didn't associate the ``template``
- view configuration value with a filename with a "known" extension.
- In this release, you must use a ``renderer`` attribute which is a
- path that ends with a ``.txt`` extension
- (e.g. ``templates/foo.txt``) to use the Chameleon text renderer.
+Documentation
+-------------
-- The ``ITemplateRenderer`` interface has been changed. Previously
- its ``__call__`` method accepted ``**kw``. It now accepts a single
- positional parameter named ``kw``.
+- The "Views" narrative chapter in the documentation has been updated
+ extensively to discuss "renderers".
-- The ``ITemplateRendererFactory`` interface has been changed.
- Previously its ``__call__`` method accepted an ``auto_reload``
- keyword parameter. Now it accepts no keyword parameters. Renderers
- are now themselves responsible for determining details of
- auto-reload.
+Features
+--------
-- The ``templating`` module has been removed. The bulk of its
- functionality has been moved to a different module named
- ``renderers``.
+- A ``renderer`` attribute has been added to view configurations,
+ replacing the previous (1.1a2) version's ``template`` attribute. A
+ "renderer" is an object which accepts the return value of a view and
+ converts it to a string. This includes, but is not limited to,
+ templating systems.
- A new interface named ``IRenderer`` was added. The existing
interface, ``ITemplateRenderer`` now derives from this new
@@ -41,9 +24,6 @@ Next release
interface named ``ITemplateRenderer`` now derives from this
interface. This interface is internal.
-- The "Views" narrative chapter in the documentation has been updated
- extensively to discuss "renderers".
-
- The ``view`` attribute of the ``view`` ZCML directive is no longer
required if the ZCML directive also has a ``renderer`` attribute.
This is useful when the renderer is a template renderer and no names
@@ -52,9 +32,6 @@ Next release
- A new zcml directive ``renderer`` has been added. It is documented
in the "Views" narrative chapter of the documentation.
-- The ``template_renderer`` ZCML directive introduced in 1.1a2 has
- been removed. It has been replaced by the ``renderer`` directive.
-
- A ZCML ``view`` directive (and the associated ``bfg_view``
decorator) can now accept a "wrapper" value. If a "wrapper" value
is supplied, it is the value of a separate view's *name* attribute.
@@ -69,6 +46,61 @@ Next release
between views using only ZCML or decorators (as opposed always using
ZPT METAL and analogues to wrap view renderings in outer wrappers).
+Dependencies
+------------
+
+- When used under Python < 2.6, BFG now has an installation time
+ dependency on the ``simplejson`` package.
+
+Deprecations
+------------
+
+- The ``repoze.bfg.testing.registerDummyRenderer`` API has been
+ deprecated in favor of
+ ``repoze.bfg.testing.registerTemplateRenderer``. A deprecation
+ warning is *not* issued at import time for the former name; it will
+ exist "forever".
+
+- The ``repoze.bfg.templating.renderer_from_cache`` function has been
+ moved to ``repoze.bfg.renderer.template_renderer_factory``. This
+ was never an API, but code in the wild was spotted that used it. A
+ deprecation warning is issued at import time for the former.
+
+Backwards Incompatibilities
+---------------------------
+
+- The ``ITemplateRenderer`` interface has been changed. Previously
+ its ``__call__`` method accepted ``**kw``. It now accepts a single
+ positional parameter named ``kw``. This is mostly an internal
+ change, but it was exposed in APIs in one place: if you've used the
+ ``repoze.bfg.testing.registerDummyRenderer`` API in your tests with
+ a custom "renderer" argument with your own renderer implementation,
+ you will need to change that renderer implementation to accept
+ ``kw`` instead of ``**kw`` in its ``__call__`` method.
+
+- The ``ITemplateRendererFactory`` interface has been changed.
+ Previously its ``__call__`` method accepted an ``auto_reload``
+ keyword parameter. Now its ``__call__`` method accepts no keyword
+ parameters. Renderers are now themselves responsible for
+ determining details of auto-reload. This is purely an internal
+ change. This interface was never external.
+
+- The ``template_renderer`` ZCML directive introduced in 1.1a2 has
+ been removed. It has been replaced by the ``renderer`` directive.
+
+- The previous release (1.1a2) added a view configuration attribute
+ named ``template``. In this release, the attribute has been renamed
+ to ``renderer``. This signifies that the attribute is more generic:
+ it can now be not just a template name but any renderer name (ala
+ ``json``).
+
+- In the previous release (1.1a2), the Chameleon text template
+ renderer was used if the system didn't associate the ``template``
+ view configuration value with a filename with a "known" extension.
+ In this release, you must use a ``renderer`` attribute which is a
+ path that ends with a ``.txt`` extension
+ (e.g. ``templates/foo.txt``) to use the Chameleon text renderer.
+
1.1a2 (2009-09-14)
==================
diff --git a/docs/api/testing.rst b/docs/api/testing.rst
index 7870ed1d3..80342e0f6 100644
--- a/docs/api/testing.rst
+++ b/docs/api/testing.rst
@@ -11,7 +11,7 @@
.. autofunction:: registerEventListener
- .. autofunction:: registerDummyRenderer
+ .. autofunction:: registerTemplateRenderer
.. autofunction:: registerView
diff --git a/docs/narr/unittesting.rst b/docs/narr/unittesting.rst
index 22a36318a..064be4739 100644
--- a/docs/narr/unittesting.rst
+++ b/docs/narr/unittesting.rst
@@ -57,7 +57,7 @@ unittest TestCase that used the testing API.
def test_view_fn_not_submitted(self):
from my.package import view_fn
- renderer = testing.registerDummyRenderer('templates/show.pt')
+ renderer = testing.registerTemplateRenderer('templates/show.pt')
context = testing.DummyModel()
request = testing.DummyRequest()
response = view_fn(context, request)
@@ -65,7 +65,7 @@ unittest TestCase that used the testing API.
def test_view_fn_submitted(self):
from my.package import view_fn
- renderer = testing.registerDummyRenderer('templates/submitted.pt')
+ renderer = testing.registerTemplateRenderer('templates/submitted.pt')
context = testing.DummyModel()
request = testing.DummyRequest()
request.params['say'] = 'Yo'
@@ -81,7 +81,7 @@ The first test method, ``test_view_fn_not_submitted`` tests the
``view_fn`` function in the case that no "form" values (represented by
request.params) have been submitted. Its first line registers a
"dummy template renderer" named ``templates/show.pt`` via the
-``registerDummyRenderer`` function (a ``repoze.bfg.testing`` API);
+``registerTemplateRenderer`` function (a ``repoze.bfg.testing`` API);
this function returns a DummyTemplateRenderer instance which we hang
on to for later. We then create a ``DummyRequest`` object (it
simulates a WebOb request object), and we create a ``DummyModel``
diff --git a/repoze/bfg/testing.py b/repoze/bfg/testing.py
index bdf60de40..7b694b242 100644
--- a/repoze/bfg/testing.py
+++ b/repoze/bfg/testing.py
@@ -69,11 +69,11 @@ def registerEventListener(event_iface=Interface):
registerSubscriber(subscriber, event_iface)
return L
-def registerDummyRenderer(path, renderer=None):
- """ Register a 'renderer' at ``path`` (usually a relative filename
- ala ``templates/foo.pt``) and return the renderer object. If the
- ``renderer`` argument is None, a 'dummy' renderer will be used.
- This function is useful when testing code that calls the
+def registerTemplateRenderer(path, renderer=None):
+ """ Register a 'template renderer' at ``path`` (usually a relative
+ filename ala ``templates/foo.pt``) and return the renderer object.
+ If the ``renderer`` argument is None, a 'dummy' renderer will be
+ used. This function is useful when testing code that calls the
``render_template_to_response`` or any other ``render_template*``
API of any of the built-in templating systems."""
from repoze.bfg.interfaces import ITemplateRenderer
@@ -81,6 +81,10 @@ def registerDummyRenderer(path, renderer=None):
renderer = DummyTemplateRenderer()
return registerUtility(renderer, ITemplateRenderer, path)
+# registerDummyRenderer is a deprecated alias that should never be removed
+# (far too much usage in the wild)
+registerDummyRenderer = registerTemplateRenderer
+
def registerView(name, result='', view=None, for_=(Interface, Interface),
permission=None):
""" Registers ``repoze.bfg`` view function under the name
@@ -251,7 +255,7 @@ class DummySecurityPolicy:
class DummyTemplateRenderer:
"""
An instance of this class is returned from
- ``registerDummyRenderer``. It has a helper function (``assert_``)
+ ``registerTemplateRenderer``. It has a helper function (``assert_``)
that makes it possible to make an assertion which compares data
passed to the renderer by the view function against expected
key/value pairs.
diff --git a/repoze/bfg/tests/test_testing.py b/repoze/bfg/tests/test_testing.py
index f479106ce..6c6b55337 100644
--- a/repoze/bfg/tests/test_testing.py
+++ b/repoze/bfg/tests/test_testing.py
@@ -54,20 +54,20 @@ class TestTestingFunctions(unittest.TestCase):
from repoze.bfg.traversal import find_model
self.assertEqual(find_model(None, '/ob1'), ob1)
- def test_registerDummyRenderer(self):
+ def test_registerTemplateRenderer(self):
from repoze.bfg import testing
- renderer = testing.registerDummyRenderer('templates/foo')
+ renderer = testing.registerTemplateRenderer('templates/foo')
from repoze.bfg.testing import DummyTemplateRenderer
self.failUnless(isinstance(renderer, DummyTemplateRenderer))
from repoze.bfg.chameleon_zpt import render_template_to_response
response = render_template_to_response('templates/foo', foo=1, bar=2)
self.assertEqual(dict(foo=1, bar=2), renderer._received)
- def test_registerDummyRenderer_explicitrenderer(self):
+ def test_registerTemplateRenderer_explicitrenderer(self):
from repoze.bfg import testing
def renderer(kw):
raise ValueError
- renderer = testing.registerDummyRenderer('templates/foo', renderer)
+ renderer = testing.registerTemplateRenderer('templates/foo', renderer)
from repoze.bfg.chameleon_zpt import render_template_to_response
self.assertRaises(ValueError, render_template_to_response,
'templates/foo', foo=1, bar=2)
diff --git a/repoze/bfg/tests/test_zcml.py b/repoze/bfg/tests/test_zcml.py
index 21d55504d..7af9ab193 100644
--- a/repoze/bfg/tests/test_zcml.py
+++ b/repoze/bfg/tests/test_zcml.py
@@ -1376,7 +1376,8 @@ class TestDeriveView(unittest.TestCase):
return Response('outer ' + request.wrapped_body)
sm = getSiteManager()
sm.registerAdapter(outer_view, (None, None), IView, 'owrap')
- result = self._callFUT(inner_view, wrapper_viewname='owrap')
+ result = self._callFUT(inner_view, viewname='inner',
+ wrapper_viewname='owrap')
self.failIf(result is inner_view)
self.assertEqual(inner_view.__module__, result.__module__)
self.assertEqual(inner_view.__doc__, result.__doc__)
@@ -1384,6 +1385,16 @@ class TestDeriveView(unittest.TestCase):
response = result(None, request)
self.assertEqual(response.body, 'outer OK')
+ def test_view_with_wrapper_viewname_notfound(self):
+ from webob import Response
+ inner_response = Response('OK')
+ def inner_view(context, request):
+ return inner_response
+ request = DummyRequest()
+ wrapped = self._callFUT(
+ inner_view, viewname='inner', wrapper_viewname='owrap')
+ result = self.assertRaises(ValueError, wrapped, None, request)
+
class TestConnectRouteFunction(unittest.TestCase):
def setUp(self):
cleanUp()
diff --git a/repoze/bfg/zcml.py b/repoze/bfg/zcml.py
index 94bb7371d..a9a6a95a0 100644
--- a/repoze/bfg/zcml.py
+++ b/repoze/bfg/zcml.py
@@ -182,7 +182,7 @@ def view(
def register():
derived_view = derive_view(view, permission, predicates, attr, renderer,
- wrapper)
+ wrapper, name)
r_for_ = for_
r_request_type = request_type
if r_for_ is None:
@@ -252,15 +252,15 @@ def forbidden(_context, view):
view_utility(_context, view, IForbiddenView)
def derive_view(original_view, permission=None, predicates=(), attr=None,
- renderer=None, wrapper_viewname=None):
+ renderer=None, wrapper_viewname=None, viewname=None):
mapped_view = map_view(original_view, attr, renderer)
- owrapped_view = owrap_view(mapped_view, wrapper_viewname)
+ owrapped_view = owrap_view(mapped_view, viewname, wrapper_viewname)
secured_view = secure_view(owrapped_view, permission)
debug_view = authdebug_view(secured_view, permission)
derived_view = predicate_wrap(debug_view, predicates)
return derived_view
-def owrap_view(view, wrapper_viewname):
+def owrap_view(view, viewname, wrapper_viewname):
if not wrapper_viewname:
return view
def _owrapped_view(context, request):
@@ -268,7 +268,13 @@ def owrap_view(view, wrapper_viewname):
request.wrapped_response = response
request.wrapped_body = response.body
request.wrapped_view = view
- return render_view_to_response(context, request, wrapper_viewname)
+ wrapped_response = render_view_to_response(context, request,
+ wrapper_viewname)
+ if wrapped_response is None:
+ raise ValueError(
+ 'No wrapper view named %r found when executing view named %r' %
+ (wrapper_viewname, viewname))
+ return wrapped_response
decorate_view(_owrapped_view, view)
return _owrapped_view