From 89c94bb61444893084a4e15fd185b7c07477ecad Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Wed, 29 Aug 2012 03:41:28 -0400 Subject: rough cut at supporting 'packagename:dirname/template#macroname.pt' renderer style, ala mako renderer --- pyramid/chameleon_text.py | 2 +- pyramid/chameleon_zpt.py | 17 ++++++++++++----- pyramid/renderers.py | 13 +++++++++++-- pyramid/tests/test_renderers.py | 2 +- 4 files changed, 25 insertions(+), 9 deletions(-) diff --git a/pyramid/chameleon_text.py b/pyramid/chameleon_text.py index 872d3b920..20f614857 100644 --- a/pyramid/chameleon_text.py +++ b/pyramid/chameleon_text.py @@ -27,7 +27,7 @@ def renderer_factory(info): @implementer(ITemplateRenderer) class TextTemplateRenderer(object): - def __init__(self, path, lookup): + def __init__(self, path, lookup, macro=None): self.path = path self.lookup = lookup diff --git a/pyramid/chameleon_zpt.py b/pyramid/chameleon_zpt.py index aa6f89e07..9f9e09850 100644 --- a/pyramid/chameleon_zpt.py +++ b/pyramid/chameleon_zpt.py @@ -26,19 +26,26 @@ def renderer_factory(info): @implementer(ITemplateRenderer) class ZPTTemplateRenderer(object): - def __init__(self, path, lookup): + def __init__(self, path, lookup, macro=None): self.path = path self.lookup = lookup + self.macro = macro @reify # avoid looking up reload_templates before manager pushed def template(self): if sys.platform.startswith('java'): # pragma: no cover raise RuntimeError( 'Chameleon templates are not compatible with Jython') - return PageTemplateFile(self.path, - auto_reload=self.lookup.auto_reload, - debug=self.lookup.debug, - translate=self.lookup.translate) + tf = PageTemplateFile(self.path, + auto_reload=self.lookup.auto_reload, + debug=self.lookup.debug, + translate=self.lookup.translate) + if self.macro: + # render only the portion of the template included in a + # define-macro named the value of self.macro + macro_renderer = tf.macros[self.macro].include + tf._render = macro_renderer + return tf def implementation(self): return self.template diff --git a/pyramid/renderers.py b/pyramid/renderers.py index e526f9997..fe9df33d1 100644 --- a/pyramid/renderers.py +++ b/pyramid/renderers.py @@ -1,5 +1,6 @@ import json import os +import re import pkg_resources import threading @@ -426,7 +427,7 @@ class ChameleonRendererLookup(object): raise ValueError('Missing template file: %s' % spec) renderer = registry.queryUtility(ITemplateRenderer, name=spec) if renderer is None: - renderer = self.impl(spec, self) + renderer = self.impl(spec, self, macro=None) # cache the template try: self.lock.acquire() @@ -438,6 +439,14 @@ class ChameleonRendererLookup(object): # spec is a package:relpath asset spec renderer = registry.queryUtility(ITemplateRenderer, name=spec) if renderer is None: + p = re.compile( + r'(?P[\w_.:/]+)' + r'(?:\#(?P[\w_]+))?' + r'(\.(?P.*))' + ) + asset, macro, ext = p.match(spec).group( + 'asset', 'defname', 'ext') + spec = '%s.%s' % (asset, ext) try: package_name, filename = spec.split(':', 1) except ValueError: # pragma: no cover @@ -450,7 +459,7 @@ class ChameleonRendererLookup(object): if not pkg_resources.resource_exists(package_name, filename): raise ValueError( 'Missing template asset: %s (%s)' % (spec, abspath)) - renderer = self.impl(abspath, self) + renderer = self.impl(abspath, self, macro=macro) settings = info.settings if not settings.get('reload_assets'): # cache the template diff --git a/pyramid/tests/test_renderers.py b/pyramid/tests/test_renderers.py index 495d7dc23..6a8ac64f4 100644 --- a/pyramid/tests/test_renderers.py +++ b/pyramid/tests/test_renderers.py @@ -292,7 +292,7 @@ class TestChameleonRendererLookup(unittest.TestCase): if path.endswith('.pyc'): # pragma: no cover path = path[:-1] self.assertTrue(factory.path.startswith(path)) - self.assertEqual(factory.kw, {}) + self.assertEqual(factory.kw, {'macro':None}) def test___call__reload_assets_true(self): import pyramid.tests -- cgit v1.2.3 From 41049b143c3332a32efca8f801b437eee1c2dd2c Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Wed, 29 Aug 2012 03:49:26 -0400 Subject: add a test --- pyramid/tests/test_renderers.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/pyramid/tests/test_renderers.py b/pyramid/tests/test_renderers.py index 6a8ac64f4..cc3d73fb7 100644 --- a/pyramid/tests/test_renderers.py +++ b/pyramid/tests/test_renderers.py @@ -294,6 +294,31 @@ class TestChameleonRendererLookup(unittest.TestCase): self.assertTrue(factory.path.startswith(path)) self.assertEqual(factory.kw, {'macro':None}) + def test___call__spec_withmacro(self): + import os + from pyramid import tests + module_name = tests.__name__ + relpath = 'fixtures/withmacro#foo.pt' + renderer = {} + factory = DummyFactory(renderer) + spec = '%s:%s' % (module_name, relpath) + info = DummyRendererInfo({ + 'name':spec, + 'package':None, + 'registry':self.config.registry, + 'settings':{}, + 'type':'type', + }) + lookup = self._makeOne(factory) + result = lookup(info) + self.assertTrue(result is renderer) + path = os.path.join( + os.path.dirname(os.path.abspath(__file__)), + 'fixtures', + 'withmacro.pt') + self.assertTrue(factory.path.startswith(path)) + self.assertEqual(factory.kw, {'macro':'foo'}) + def test___call__reload_assets_true(self): import pyramid.tests from pyramid.interfaces import ISettings -- cgit v1.2.3 From c88cafacc70ae325961563bfbd84a72cdaba2a9d Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Wed, 29 Aug 2012 04:06:45 -0400 Subject: add renderer and template to values passed to template during rendering --- pyramid/chameleon_zpt.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pyramid/chameleon_zpt.py b/pyramid/chameleon_zpt.py index 9f9e09850..22b84066b 100644 --- a/pyramid/chameleon_zpt.py +++ b/pyramid/chameleon_zpt.py @@ -52,6 +52,8 @@ class ZPTTemplateRenderer(object): def __call__(self, value, system): try: + system['renderer'] = self + system['template'] = self.template system.update(value) except (TypeError, ValueError): raise ValueError('renderer was passed non-dictionary as value') -- cgit v1.2.3 From 8b55a68adb54783895a91a9e1af800a7f8f22c07 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Wed, 29 Aug 2012 16:06:17 -0400 Subject: garden --- CHANGES.txt | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index a9dd18985..62c37f374 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -81,10 +81,21 @@ Features and ``HTTPMovedPermanently`` exceptions, so these can be caught by the NotFound view (and other exception views). -- The mako renderer now accepts a def name and returns the template def - result for the view being called. The uri format using an asset spec is - package:path/to/template#defname.mako. The old way of returning a tuple - from the view is supported for backward compatibility, ('defname', {}). +- The Mako renderer now accepts a def name in an asset spect. When the def + name is present in the asset spec, the system will render the template def + within the template and will return the result. An example asset spec is + ``package:path/to/template#defname.mako``. This will render the def named + ``defname`` inside the ``template.pt`` package instead of rendering the + entire template. The old way of returning a tuple from the view is + supported for backward compatibility, ('defname', {}). + +- The Chameleon ZPT renderer now accepts a macro name in an asset spec. When + the macro name is present in the asset spec, the system will render the + macro listed as a ``define-macro`` and return the result instead of + rendering the entire template. An example asset spec: + ``package:path/to/template#macroname.pt``. This will render the macro + defined as ``macroname`` within the ``template.pt`` template instead of the + entire templae. - When there is a predicate mismatch exception (seen when no view matches for a given request due to predicates not working), the exception now contains -- cgit v1.2.3 From eecaa867d72d06fec45dd151fcd2e93d02927cef Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Wed, 29 Aug 2012 16:07:54 -0400 Subject: add docs about chameleon zpt macro feature --- docs/narr/templates.rst | 38 +++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/docs/narr/templates.rst b/docs/narr/templates.rst index 860010a1a..adc671766 100644 --- a/docs/narr/templates.rst +++ b/docs/narr/templates.rst @@ -534,6 +534,30 @@ And ``templates/mytemplate.pt`` might look like so: + +Using A Chameleon Macro Name Within a Chameleon ZPT Template +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Sommetime you'd like to render a macro inside of a Chameleon ZPT template +instead of the full Chameleon ZPT template. To render the content of a +``define-macro`` field inside a Chameleon ZPT template, given a Chameleon +template file named ``foo.pt`` and a macro named ``bar`` defined within it +(e.g. ``
...
``, you can configure the +template as a :term:`renderer` like so: + +.. code-block:: python + :linenos: + + from pyramid.view import view_config + + @view_config(renderer='foo#bar.pt') + def my_view(request): + return {'project':'my project'} + +The above will render the ``bar`` macro from within the ``foo.pt`` template +instead of the entire template. + + .. index:: single: Chameleon text templates @@ -714,12 +738,13 @@ This template doesn't use any advanced features of Mako, only the :term:`renderer globals`. See the `the Mako documentation `_ to use more advanced features. -Using def inside Mako Templates -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Using A Mako def name Within a Renderer Name +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -To use a def inside a Mako template, given a :term:`Mako` template file named -``foo.mak`` and a def named ``bar``, you can configure the template as a -:term:`renderer` like so: +Sommetime you'd like to render a ``def`` inside of a Mako template instead of +the full Mako template. To render a def inside a Mako template, given a +:term:`Mako` template file named ``foo.mak`` and a def named ``bar``, you can +configure the template as a :term:`renderer` like so: .. code-block:: python :linenos: @@ -730,6 +755,9 @@ To use a def inside a Mako template, given a :term:`Mako` template file named def my_view(request): return {'project':'my project'} +The above will render the ``bar`` def from within the ``foo.mak`` template +instead of the entire template. + .. index:: single: automatic reloading of templates single: template automatic reload -- cgit v1.2.3 From 3a9232533139456c86483a9a53001b8500e433e9 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Wed, 29 Aug 2012 16:10:26 -0400 Subject: wording --- docs/narr/templates.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/narr/templates.rst b/docs/narr/templates.rst index adc671766..4e6570865 100644 --- a/docs/narr/templates.rst +++ b/docs/narr/templates.rst @@ -535,8 +535,8 @@ And ``templates/mytemplate.pt`` might look like so: -Using A Chameleon Macro Name Within a Chameleon ZPT Template -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Using A Chameleon Macro Name Within a Renderer Name +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Sommetime you'd like to render a macro inside of a Chameleon ZPT template instead of the full Chameleon ZPT template. To render the content of a -- cgit v1.2.3 From 94358e23ec5e9ce56e4a8c3f4a300ffce2e4b9ea Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Wed, 29 Aug 2012 16:16:41 -0400 Subject: forgot a fixture file --- pyramid/tests/fixtures/withmacro.pt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 pyramid/tests/fixtures/withmacro.pt diff --git a/pyramid/tests/fixtures/withmacro.pt b/pyramid/tests/fixtures/withmacro.pt new file mode 100644 index 000000000..bb80475c0 --- /dev/null +++ b/pyramid/tests/fixtures/withmacro.pt @@ -0,0 +1,3 @@ + + Hello! + -- cgit v1.2.3 From 8849fcd5eba1f7b0ab7103807bbd24190c1468a2 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Wed, 29 Aug 2012 16:32:41 -0400 Subject: remove experimental names --- pyramid/chameleon_zpt.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/pyramid/chameleon_zpt.py b/pyramid/chameleon_zpt.py index 22b84066b..9f9e09850 100644 --- a/pyramid/chameleon_zpt.py +++ b/pyramid/chameleon_zpt.py @@ -52,8 +52,6 @@ class ZPTTemplateRenderer(object): def __call__(self, value, system): try: - system['renderer'] = self - system['template'] = self.template system.update(value) except (TypeError, ValueError): raise ValueError('renderer was passed non-dictionary as value') -- cgit v1.2.3 From cc8962d5da32bb30bbfc37c96286282b5ed751ff Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Wed, 29 Aug 2012 17:21:14 -0400 Subject: add newness markers --- docs/narr/renderers.rst | 4 +++- docs/narr/templates.rst | 7 +++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/docs/narr/renderers.rst b/docs/narr/renderers.rst index 57b5bc65b..63287e2cd 100644 --- a/docs/narr/renderers.rst +++ b/docs/narr/renderers.rst @@ -306,7 +306,9 @@ See :class:`pyramid.renderers.JSON` and JSONP Renderer ~~~~~~~~~~~~~~ -.. note:: This feature is new in Pyramid 1.1. +.. note:: + + This feature is new in Pyramid 1.1. :class:`pyramid.renderers.JSONP` is a `JSONP `_ renderer factory helper which diff --git a/docs/narr/templates.rst b/docs/narr/templates.rst index 4e6570865..656cf4773 100644 --- a/docs/narr/templates.rst +++ b/docs/narr/templates.rst @@ -557,6 +557,9 @@ template as a :term:`renderer` like so: The above will render the ``bar`` macro from within the ``foo.pt`` template instead of the entire template. +.. note:: + + This feature is new in Pyramid 1.4. .. index:: single: Chameleon text templates @@ -758,6 +761,10 @@ configure the template as a :term:`renderer` like so: The above will render the ``bar`` def from within the ``foo.mak`` template instead of the entire template. +.. note:: + + This feature is new in Pyramid 1.4. + .. index:: single: automatic reloading of templates single: template automatic reload -- cgit v1.2.3 From eb72972b51f58037d1bc1c2e5d81ee10abd82afe Mon Sep 17 00:00:00 2001 From: Ronan Amicel Date: Thu, 30 Aug 2012 22:49:01 +0300 Subject: Fixed broken link in docs/narr/testing.rst Fixed link to "Dive into Python" (previous mirror is down). --- docs/narr/testing.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/narr/testing.rst b/docs/narr/testing.rst index 5ce2c8a66..50e9d5604 100644 --- a/docs/narr/testing.rst +++ b/docs/narr/testing.rst @@ -52,7 +52,7 @@ The suggested mechanism for unit and integration testing of a :app:`Pyramid` application is the Python :mod:`unittest` module. Although this module is named :mod:`unittest`, it is actually capable of driving both unit and integration tests. A good :mod:`unittest` tutorial is available within `Dive -Into Python `_ by Mark +Into Python `_ by Mark Pilgrim. :app:`Pyramid` provides a number of facilities that make unit, integration, -- cgit v1.2.3