summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris McDonough <chrism@plope.com>2010-11-01 00:43:43 -0400
committerChris McDonough <chrism@plope.com>2010-11-01 00:43:43 -0400
commitf5fa3f9e2a754ce199386e3f20735cd2dfbbc3fc (patch)
tree2c53687d943aad9e28a116453a20fbc80c329406
parent6f1973b325cba5600eb91ff6982baf68b4567336 (diff)
downloadpyramid-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.txt15
-rw-r--r--docs/narr/views.rst16
-rw-r--r--pyramid/configuration.py7
-rw-r--r--pyramid/mako_templating.py6
-rw-r--r--pyramid/renderers.py54
-rw-r--r--pyramid/testing.py2
-rw-r--r--pyramid/tests/test_configuration.py24
-rw-r--r--pyramid/tests/test_mako_templating.py36
-rw-r--r--pyramid/tests/test_renderers.py106
-rw-r--r--pyramid/tests/test_testing.py12
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)
+