diff options
| author | Chris McDonough <chrism@plope.com> | 2010-11-01 00:43:43 -0400 |
|---|---|---|
| committer | Chris McDonough <chrism@plope.com> | 2010-11-01 00:43:43 -0400 |
| commit | f5fa3f9e2a754ce199386e3f20735cd2dfbbc3fc (patch) | |
| tree | 2c53687d943aad9e28a116453a20fbc80c329406 | |
| parent | 6f1973b325cba5600eb91ff6982baf68b4567336 (diff) | |
| download | pyramid-f5fa3f9e2a754ce199386e3f20735cd2dfbbc3fc.tar.gz pyramid-f5fa3f9e2a754ce199386e3f20735cd2dfbbc3fc.tar.bz2 pyramid-f5fa3f9e2a754ce199386e3f20735cd2dfbbc3fc.zip | |
for performance reasons (to avoid unnecessary ZCA lookups), pass the helper object itself to a renderer rather than a dictionary derivation)
| -rw-r--r-- | CHANGES.txt | 15 | ||||
| -rw-r--r-- | docs/narr/views.rst | 16 | ||||
| -rw-r--r-- | pyramid/configuration.py | 7 | ||||
| -rw-r--r-- | pyramid/mako_templating.py | 6 | ||||
| -rw-r--r-- | pyramid/renderers.py | 54 | ||||
| -rw-r--r-- | pyramid/testing.py | 2 | ||||
| -rw-r--r-- | pyramid/tests/test_configuration.py | 24 | ||||
| -rw-r--r-- | pyramid/tests/test_mako_templating.py | 36 | ||||
| -rw-r--r-- | pyramid/tests/test_renderers.py | 106 | ||||
| -rw-r--r-- | pyramid/tests/test_testing.py | 12 |
10 files changed, 170 insertions, 108 deletions
diff --git a/CHANGES.txt b/CHANGES.txt index b54f1a920..9f948ffe2 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -94,14 +94,15 @@ Backwards Incompatibilities (with BFG 1.3.X) - ``pyramid.renderers.rendered_response`` function removed; use ``render_pyramid.renderers.render_to_response`` instead. -- Renderer factories now accept a *dictionary* rather than an absolute resource - specification or an absolute path. The dictonary contains the following - keys: ``name`` (the ``renderer=`` value), ``package`` (the 'current package' - when the renderer configuration statement was found), ``type``: the renderer - type, ``registry``: the current registry, and ``settings``: the deployment - settings dictionary. +- Renderer factories now accept an *info object* rather than an absolute + resource specification or an absolute path. The object has the following + attributes: ``name`` (the ``renderer=`` value), ``package`` (the 'current + package' when the renderer configuration statement was found), ``type``: the + renderer type, ``registry``: the current registry, and ``settings``: the + deployment settings dictionary. Third-party ``repoze.bfg`` renderer implementations that must be ported to Pyramid will need to account for this. - This change was made to support more flexible Mako template rendering. + This change was made primarily to support more flexible Mako template + rendering. diff --git a/docs/narr/views.rst b/docs/narr/views.rst index 7e3dfebf1..e1983222d 100644 --- a/docs/narr/views.rst +++ b/docs/narr/views.rst @@ -739,8 +739,8 @@ following interface: class RendererFactory: def __init__(self, info): - """ Constructor: ``info`` will be a dictionary containing - the following keys: ``name`` (the renderer name), ``package`` + """ Constructor: ``info`` will be an object having the + the following attributes: ``name`` (the renderer name), ``package`` (the package that was 'current' at the time the renderer was registered), ``type`` (the renderer type name), ``registry`` (the current application registry) and ``settings`` (the @@ -757,14 +757,14 @@ following interface: There are essentially two different kinds of renderer factories: - A renderer factory which expects to accept a :term:`resource specification` - or an absolute path as the ``name`` value in the ``info`` value fed to its - constructor. These renderer factories are registered with a ``name`` value - that begins with a dot (``.``). These types of renderer factories usually - relate to a file on the filesystem, such as a template. + or an absolute path as the ``name`` attribute of the ``info`` object fed to + its constructor. These renderer factories are registered with a ``name`` + value that begins with a dot (``.``). These types of renderer factories + usually relate to a file on the filesystem, such as a template. - A renderer factory which expects to accept a token that does not represent a - filesystem path or a resource specification in the ``name`` value of the - ``info`` dict fed to its constructor. These renderer factories are + filesystem path or a resource specification in the ``name`` attribute of the + ``info`` object fed to its constructor. These renderer factories are registered with a ``name`` value that does not begin with a dot. These renderer factories are typically object serializers. diff --git a/pyramid/configuration.py b/pyramid/configuration.py index bc4c6a7e3..bf5dcce2d 100644 --- a/pyramid/configuration.py +++ b/pyramid/configuration.py @@ -2101,17 +2101,16 @@ class Configurator(object): """ from pyramid.testing import DummyRendererFactory helper = RendererHelper(name=path, registry=self.registry) - factory = helper.factory + factory = self.registry.queryUtility(IRendererFactory, name=helper.type) if not isinstance(factory, DummyRendererFactory): - factory = DummyRendererFactory(helper.type, - helper.factory) + factory = DummyRendererFactory(helper.type, factory) self.registry.registerUtility(factory, IRendererFactory, name=helper.type) from pyramid.testing import DummyTemplateRenderer if renderer is None: renderer = DummyTemplateRenderer() - factory.add(helper.name, renderer) + factory.add(path, renderer) return renderer testing_add_template = testing_add_renderer diff --git a/pyramid/mako_templating.py b/pyramid/mako_templating.py index 9dc2b09e8..bf51257a0 100644 --- a/pyramid/mako_templating.py +++ b/pyramid/mako_templating.py @@ -52,9 +52,9 @@ class PkgResourceTemplateLookup(TemplateLookup): def renderer_factory(info): - path = info['name'] - registry = info['registry'] - settings = info['settings'] or {} + path = info.name + registry = info.registry + settings = info.settings lookup = registry.queryUtility(IMakoLookup) if lookup is None: reload_templates = settings.get('reload_templates', False) diff --git a/pyramid/renderers.py b/pyramid/renderers.py index 6c2d20cce..8ad02270c 100644 --- a/pyramid/renderers.py +++ b/pyramid/renderers.py @@ -59,9 +59,9 @@ def render(renderer_name, value, request=None, package=None): registry = None if package is None: package = caller_package() - renderer = RendererHelper(name=renderer_name, package=package, - registry=registry) - return renderer.render(value, None, request=request) + helper = RendererHelper(name=renderer_name, package=package, + registry=registry) + return helper.render(value, None, request=request) def render_to_response(renderer_name, value, request=None, package=None): """ Using the renderer specified as ``renderer_name`` (a template @@ -102,9 +102,9 @@ def render_to_response(renderer_name, value, request=None, package=None): registry = None if package is None: package = caller_package() - renderer = RendererHelper(name=renderer_name, package=package, - registry=registry) - return renderer.render_to_response(value, None, request=request) + helper = RendererHelper(name=renderer_name, package=package, + registry=registry) + return helper.render_to_response(value, None, request=request) def get_renderer(renderer_name, package=None): """ Return the renderer object for the renderer named as @@ -120,8 +120,8 @@ def get_renderer(renderer_name, package=None): """ if package is None: package = caller_package() - renderer = RendererHelper(name=renderer_name, package=package) - return renderer.get_renderer() + helper = RendererHelper(name=renderer_name, package=package) + return helper.renderer # concrete renderer factory implementations (also API) @@ -154,10 +154,9 @@ def string_renderer_factory(info): registry_lock = threading.Lock() def template_renderer_factory(info, impl, lock=registry_lock): - reg = info['registry'] - spec = info['name'] - package = info['package'] - settings = info['settings'] + spec = info.name + reg = info.registry + package = info.package isabs = os.path.isabs(spec) @@ -197,6 +196,7 @@ def template_renderer_factory(info, impl, lock=registry_lock): raise ValueError( 'Missing template resource: %s (%s)' % (spec, abspath)) renderer = impl(abspath) + settings = info.settings if settings and not settings.get('reload_resources'): # cache the template try: @@ -208,43 +208,39 @@ def template_renderer_factory(info, impl, lock=registry_lock): return renderer def renderer_from_name(path, package=None): # XXX deprecate? - return RendererHelper(name=path, package=package).get_renderer() + return RendererHelper(name=path, package=package).renderer class RendererHelper(object): def __init__(self, name=None, package=None, registry=None): - if registry is None: - registry = get_current_registry() - if name and '.' in name: rtype = os.path.splitext(name)[1] else: rtype = name - factory = registry.queryUtility(IRendererFactory, name=rtype) + if registry is None: + registry = get_current_registry() self.name = name self.package = package self.type = rtype - self.factory = factory self.registry = registry @reify - def renderer(self): + def settings(self): settings = self.registry.queryUtility(ISettings) - if self.factory is None: + return settings + + @reify + def renderer(self): + factory = self.registry.queryUtility(IRendererFactory, name=self.type) + if factory is None: raise ValueError( 'No such renderer factory %s' % str(self.type)) - return self.factory({ - 'name':self.name, - 'type':self.type, - 'package':self.package, - 'registry':self.registry, - 'settings':settings, - }) - + return factory(self) + def get_renderer(self): return self.renderer - + def render(self, value, system_values, request=None): renderer = self.renderer if system_values is None: diff --git a/pyramid/testing.py b/pyramid/testing.py index 26873680e..11cb63ad4 100644 --- a/pyramid/testing.py +++ b/pyramid/testing.py @@ -711,7 +711,7 @@ class DummyRendererFactory(object): self.renderers[relative] = renderer def __call__(self, info): - spec = info['name'] + spec = info.name renderer = self.renderers.get(spec) if renderer is None: if ':' in spec: diff --git a/pyramid/tests/test_configuration.py b/pyramid/tests/test_configuration.py index 5a75fdae4..482bf323d 100644 --- a/pyramid/tests/test_configuration.py +++ b/pyramid/tests/test_configuration.py @@ -1371,11 +1371,12 @@ class ConfiguratorTests(unittest.TestCase): result = wrapper(None, request) self.assertEqual(result.body, 'Hello!') settings = config.registry.queryUtility(ISettings) - self.assertEqual(renderer.info, - {'registry':config.registry, 'type': '.txt', - 'name': 'pyramid.tests:fixtures/minimal.txt', - 'package': pyramid.tests, - 'settings':settings}) + result = renderer.info + self.assertEqual(result.registry, config.registry) + self.assertEqual(result.type, '.txt') + self.assertEqual(result.package, pyramid.tests) + self.assertEqual(result.name, fixture) + self.assertEqual(result.settings, settings) def test_add_view_with_template_renderer_no_callable(self): import pyramid.tests @@ -1389,13 +1390,12 @@ class ConfiguratorTests(unittest.TestCase): result = wrapper(None, request) self.assertEqual(result.body, 'Hello!') settings = config.registry.queryUtility(ISettings) - self.assertEqual(renderer.info, - {'registry':config.registry, - 'type': '.txt', - 'name': 'pyramid.tests:fixtures/minimal.txt', - 'package':pyramid.tests, - 'settings':settings, - }) + result = renderer.info + self.assertEqual(result.registry, config.registry) + self.assertEqual(result.type, '.txt') + self.assertEqual(result.package, pyramid.tests) + self.assertEqual(result.name, fixture) + self.assertEqual(result.settings, settings) def test_add_view_with_request_type_as_iface(self): from zope.interface import directlyProvides diff --git a/pyramid/tests/test_mako_templating.py b/pyramid/tests/test_mako_templating.py index 3b1c7fd24..e0c02550b 100644 --- a/pyramid/tests/test_mako_templating.py +++ b/pyramid/tests/test_mako_templating.py @@ -21,15 +21,23 @@ class Test_renderer_factory(Base, unittest.TestCase): def test_no_directories(self): from pyramid.exceptions import ConfigurationError - info = {'name':'helloworld.mak', 'package':None, - 'registry':self.config.registry, 'settings':None} + info = DummyRendererInfo({ + 'name':'helloworld.mak', + 'package':None, + 'registry':self.config.registry, + 'settings':{}, + }) self.assertRaises(ConfigurationError, self._callFUT, info) def test_no_lookup(self): from pyramid.mako_templating import IMakoLookup settings = {'mako.directories':self.templates_dir} - info = {'name':'helloworld.mak', 'package':None, - 'registry':self.config.registry, 'settings':settings} + info = DummyRendererInfo({ + 'name':'helloworld.mak', + 'package':None, + 'registry':self.config.registry, + 'settings':settings, + }) renderer = self._callFUT(info) lookup = self.config.registry.getUtility(IMakoLookup) self.assertEqual(lookup.directories, [self.templates_dir]) @@ -41,8 +49,12 @@ class Test_renderer_factory(Base, unittest.TestCase): from pyramid.mako_templating import IMakoLookup twice = self.templates_dir + '\n' + self.templates_dir settings = {'mako.directories':twice} - info = {'name':'helloworld.mak', 'package':None, - 'registry':self.config.registry, 'settings':settings} + info = DummyRendererInfo({ + 'name':'helloworld.mak', + 'package':None, + 'registry':self.config.registry, + 'settings':settings, + }) self._callFUT(info) lookup = self.config.registry.getUtility(IMakoLookup) self.assertEqual(lookup.directories, [self.templates_dir]*2) @@ -51,8 +63,12 @@ class Test_renderer_factory(Base, unittest.TestCase): from pyramid.mako_templating import IMakoLookup lookup = dict() self.config.registry.registerUtility(lookup, IMakoLookup) - info = {'name':'helloworld.mak', 'package':None, - 'registry':self.config.registry, 'settings':{}} + info = DummyRendererInfo({ + 'name':'helloworld.mak', + 'package':None, + 'registry':self.config.registry, + 'settings':{}, + }) renderer = self._callFUT(info) self.assertEqual(renderer.lookup, lookup) self.assertEqual(renderer.path, 'helloworld.mak') @@ -225,3 +241,7 @@ class DummyLookup(object): self.values = values return u'result' +class DummyRendererInfo(object): + def __init__(self, kw): + self.__dict__.update(kw) + diff --git a/pyramid/tests/test_renderers.py b/pyramid/tests/test_renderers.py index 80c04c940..8e06cb543 100644 --- a/pyramid/tests/test_renderers.py +++ b/pyramid/tests/test_renderers.py @@ -18,8 +18,12 @@ class TestTemplateRendererFactory(unittest.TestCase): from pyramid.interfaces import ITemplateRenderer abspath = '/wont/exist' testing.registerUtility({}, ITemplateRenderer, name=abspath) - info = {'name':abspath, 'package':None, - 'registry':self.config.registry, 'settings':{}} + info = DummyRendererInfo({ + 'name':abspath, + 'package':None, + 'registry':self.config.registry, + 'settings':{}, + }) self.assertRaises(ValueError, self._callFUT, info, None) def test_abspath_alreadyregistered(self): @@ -28,8 +32,12 @@ class TestTemplateRendererFactory(unittest.TestCase): abspath = os.path.abspath(__file__) renderer = {} testing.registerUtility(renderer, ITemplateRenderer, name=abspath) - info = {'name':abspath, 'package':None, - 'registry':self.config.registry, 'settings':{}} + info = DummyRendererInfo({ + 'name':abspath, + 'package':None, + 'registry':self.config.registry, + 'settings':{}, + }) result = self._callFUT(info, None) self.failUnless(result is renderer) @@ -39,8 +47,12 @@ class TestTemplateRendererFactory(unittest.TestCase): abspath = os.path.abspath(__file__) renderer = {} testing.registerUtility(renderer, ITemplateRenderer, name=abspath) - info = {'name':abspath, 'package':None, - 'registry':self.config.registry, 'settings':{}} + info = DummyRendererInfo({ + 'name':abspath, + 'package':None, + 'registry':self.config.registry, + 'settings':{}, + }) result = self._callFUT(info, None) self.failUnless(result is renderer) @@ -49,8 +61,12 @@ class TestTemplateRendererFactory(unittest.TestCase): from pyramid.interfaces import ITemplateRenderer testing.registerUtility(renderer, ITemplateRenderer, name='foo/bar') spec = 'foo/bar' - info = {'name':spec, 'package':None, - 'registry':self.config.registry, 'settings':{}} + info = DummyRendererInfo({ + 'name':spec, + 'package':None, + 'registry':self.config.registry, + 'settings':{}, + }) result = self._callFUT(info, None) self.failUnless(renderer is result) @@ -61,15 +77,23 @@ class TestTemplateRendererFactory(unittest.TestCase): spec = 'bar/baz' testing.registerUtility(renderer, ITemplateRenderer, name='pyramid.tests:bar/baz') - info = {'name':spec, 'package':pyramid.tests, - 'registry':self.config.registry, 'settings':{}} + info = DummyRendererInfo({ + 'name':spec, + 'package':pyramid.tests, + 'registry':self.config.registry, + 'settings':{}, + }) result = self._callFUT(info, None) self.failUnless(renderer is result) def test_spec_notfound(self): spec = 'pyramid.tests:wont/exist' - info = {'name':spec, 'package':None, 'registry':self.config.registry, - 'settings':{}} + info = DummyRendererInfo({ + 'name':spec, + 'package':None, + 'registry':self.config.registry, + 'settings':{}, + }) self.assertRaises(ValueError, self._callFUT, info, None) def test_spec_alreadyregistered(self): @@ -78,8 +102,12 @@ class TestTemplateRendererFactory(unittest.TestCase): module_name = tests.__name__ relpath = 'test_renderers.py' spec = '%s:%s' % (module_name, relpath) - info = {'name':spec, 'package':None, 'registry':self.config.registry, - 'settings':{}} + info = DummyRendererInfo({ + 'name':spec, + 'package':None, + 'registry':self.config.registry, + 'settings':{}, + }) renderer = {} testing.registerUtility(renderer, ITemplateRenderer, name=spec) result = self._callFUT(info, None) @@ -93,8 +121,12 @@ class TestTemplateRendererFactory(unittest.TestCase): renderer = {} factory = DummyFactory(renderer) spec = '%s:%s' % (module_name, relpath) - info = {'name':spec, 'package':None, 'registry':self.config.registry, - 'settings':{}} + info = DummyRendererInfo({ + 'name':spec, + 'package':None, + 'registry':self.config.registry, + 'settings':{}, + }) result = self._callFUT(info, factory) self.failUnless(result is renderer) path = os.path.abspath(__file__) @@ -113,8 +145,12 @@ class TestTemplateRendererFactory(unittest.TestCase): renderer = {} factory = DummyFactory(renderer) spec = 'test_renderers.py' - info = {'name':spec, 'package':pyramid.tests, - 'registry':self.config.registry, 'settings':{}} + info = DummyRendererInfo({ + 'name':spec, + 'package':pyramid.tests, + 'registry':self.config.registry, + 'settings':{}, + }) result = self._callFUT(info, factory) self.failUnless(result is renderer) spec = '%s:%s' % ('pyramid.tests', 'test_renderers.py') @@ -130,8 +166,12 @@ class TestTemplateRendererFactory(unittest.TestCase): renderer = {} factory = DummyFactory(renderer) spec = 'test_renderers.py' - info = {'name':spec, 'package':pyramid.tests, - 'registry':self.config.registry, 'settings':settings} + info = DummyRendererInfo({ + 'name':spec, + 'package':pyramid.tests, + 'registry':self.config.registry, + 'settings':settings, + }) result = self._callFUT(info, factory) self.failUnless(result is renderer) spec = '%s:%s' % ('pyramid.tests', 'test_renderers.py') @@ -164,12 +204,11 @@ class TestRendererFromName(unittest.TestCase): return info testing.registerUtility(factory, IRendererFactory, name='.pt') result = self._callFUT(fixture) - self.assertEqual(result, {'registry':registry, - 'type':'.pt', - 'package':None, - 'name':fixture, - 'settings':settings, - }) + self.assertEqual(result.registry, registry) + self.assertEqual(result.type, '.pt') + self.assertEqual(result.package, None) + self.assertEqual(result.name, fixture) + self.assertEqual(result.settings, settings) def test_it_with_package(self): import pyramid @@ -186,12 +225,11 @@ class TestRendererFromName(unittest.TestCase): return info testing.registerUtility(factory, IRendererFactory, name='.pt') result = self._callFUT(fixture, pyramid) - self.assertEqual(result, {'registry':registry, - 'type':'.pt', - 'package':pyramid, - 'name':fixture, - 'settings':settings, - }) + self.assertEqual(result.registry, registry) + self.assertEqual(result.type, '.pt') + self.assertEqual(result.package, pyramid) + self.assertEqual(result.name, fixture) + self.assertEqual(result.settings, settings) def test_it_no_renderer(self): self.assertRaises(ValueError, self._callFUT, 'foo') @@ -494,3 +532,7 @@ class DummyFactory: return self.renderer +class DummyRendererInfo(object): + def __init__(self, kw): + self.__dict__.update(kw) + diff --git a/pyramid/tests/test_testing.py b/pyramid/tests/test_testing.py index 5929ce650..8336bcec5 100644 --- a/pyramid/tests/test_testing.py +++ b/pyramid/tests/test_testing.py @@ -655,25 +655,25 @@ class TestDummyRendererFactory(unittest.TestCase): def test_call(self): f = self._makeOne('name', None) f.renderers['spec'] = 'renderer' - info = {'name':'spec'} + info = DummyRendererInfo({'name':'spec'}) self.assertEqual(f(info), 'renderer') def test_call2(self): f = self._makeOne('name', None) f.renderers['spec'] = 'renderer' - info = {'name':'spec:spec'} + info = DummyRendererInfo({'name':'spec:spec'}) self.assertEqual(f(info), 'renderer') def test_call3(self): def factory(spec): return 'renderer' f = self._makeOne('name', factory) - info = {'name':'spec'} + info = DummyRendererInfo({'name':'spec'}) self.assertEqual(f(info), 'renderer') def test_call_miss(self): f = self._makeOne('name', None) - info = {'name':'spec'} + info = DummyRendererInfo({'name':'spec'}) self.assertRaises(KeyError, f, info) class TestMockTemplate(unittest.TestCase): @@ -715,3 +715,7 @@ class DummyRegistry(object): def __init__(self, name=''): self.inited = self.inited + 1 +class DummyRendererInfo(object): + def __init__(self, kw): + self.__dict__.update(kw) + |
