From 19473e78e61ad084f07a0f7820a75b6c64d93dcd Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Thu, 17 Sep 2009 06:14:27 +0000 Subject: - Add a ``string`` renderer. This renderer converts a non-Response return value of any view callble into a string. It is documented in the "Views" narrative chapter. --- CHANGES.txt | 4 ++++ docs/narr/views.rst | 35 ++++++++++++++++++++++++++++++++++- repoze/bfg/includes/configure.zcml | 5 +++++ repoze/bfg/renderers.py | 7 +++++++ repoze/bfg/router.py | 4 ++-- repoze/bfg/tests/test_renderers.py | 22 ++++++++++++++++++++++ 6 files changed, 74 insertions(+), 3 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 8e48e544f..eeada7e49 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,6 +1,10 @@ Next release ============ +- Add a ``string`` renderer. This renderer converts a non-Response + return value of any view callble into a string. It is documented in + the "Views" narrative chapter. + - Give the ``route`` ZCML directive the ``view_attr`` and ``view_renderer`` parameters (bring up to speed with 1.1a3 features). These can also be spelled as ``attr`` and ``renderer``. diff --git a/docs/narr/views.rst b/docs/narr/views.rst index 74d95480c..b64fd2a4b 100644 --- a/docs/narr/views.rst +++ b/docs/narr/views.rst @@ -795,6 +795,39 @@ Several built-in "renderers" exist in :mod:`repoze.bfg`. These renderers can be used in the ``renderer`` attribute of view configurations. +``string``: String Renderer +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``string`` renderer is a renderer which renders a view callable +result to a string. If a view callable returns a non-Response object, +and the ``string`` renderer is associated in that view's +configuration, the result will be to run the object through the Python +``str`` function to generate a string. Note that if a Unicode object +is returned, it is not ``str()`` -ified. + +Here's an example of a view that returns a dictionary. If the +``string`` renderer is specified in the configuration for this view, +the view will render the returned dictionary to the ``str()`` +representation of the dictionary: + +.. code-block:: python + :linenos: + + from webob import Response + from repoze.bfg.view import bfg_view + + @bfg_view(renderer='string') + def hello_world(context, request): + return {'content':'Hello!'} + +The body of the response returned by such a view will be a string +representing the ``str()`` serialization of the return value: + +.. code-block: python + :linenos: + + {'content': 'Hello!'} + ``json``: JSON Renderer ~~~~~~~~~~~~~~~~~~~~~~~ @@ -802,7 +835,7 @@ The ``json`` renderer is a renderer which renders view callable results to :term:`JSON`. If a view callable returns a non-Response object it is called. It passes the return value through the ``simplejson.dumps`` function, and wraps the result in a response -object. For example: +object. Here's an example of a view that returns a dictionary. If the ``json`` renderer is specified in the configuration for this view, the diff --git a/repoze/bfg/includes/configure.zcml b/repoze/bfg/includes/configure.zcml index 37cd4d75a..60119b2c9 100644 --- a/repoze/bfg/includes/configure.zcml +++ b/repoze/bfg/includes/configure.zcml @@ -33,4 +33,9 @@ name="json" /> + + diff --git a/repoze/bfg/renderers.py b/repoze/bfg/renderers.py index 503131400..c5aed2906 100644 --- a/repoze/bfg/renderers.py +++ b/repoze/bfg/renderers.py @@ -22,6 +22,13 @@ def json_renderer_factory(name): return json.dumps(value) return _render +def string_renderer_factory(name): + def _render(value): + if not isinstance(value, basestring): + value = str(value) + return value + return _render + # utility functions def template_renderer_factory(path, impl, level=3): diff --git a/repoze/bfg/router.py b/repoze/bfg/router.py index d9502a435..e8497331b 100644 --- a/repoze/bfg/router.py +++ b/repoze/bfg/router.py @@ -114,8 +114,8 @@ class Router(object): return response.app_iter except AttributeError: raise ValueError( - 'Non-response object returned from view %s: %r' % - (view_name, response)) + 'Non-response object returned from view named %s ' + '(and no renderer): %r' % (view_name, response)) provides = map(providedBy, (context, request)) view_callable = registry.adapters.lookup( diff --git a/repoze/bfg/tests/test_renderers.py b/repoze/bfg/tests/test_renderers.py index 6e33f4ce5..d1acc0285 100644 --- a/repoze/bfg/tests/test_renderers.py +++ b/repoze/bfg/tests/test_renderers.py @@ -178,7 +178,29 @@ class Test_json_renderer_factory(unittest.TestCase): renderer = self._callFUT(None) result = renderer({'a':1}) self.assertEqual(result, '{"a": 1}') + +class Test_string_renderer_factory(unittest.TestCase): + def _callFUT(self, name): + from repoze.bfg.renderers import string_renderer_factory + return string_renderer_factory(name) + + def test_it_unicode(self): + renderer = self._callFUT(None) + value = unicode('La Pe\xc3\xb1a', 'utf-8') + result = renderer(value) + self.assertEqual(result, value) + def test_it_str(self): + renderer = self._callFUT(None) + value = 'La Pe\xc3\xb1a' + result = renderer(value) + self.assertEqual(result, value) + + def test_it_other(self): + renderer = self._callFUT(None) + value = None + result = renderer(value) + self.assertEqual(result, 'None') class DummyFactory: def __init__(self, renderer): -- cgit v1.2.3