summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris McDonough <chrism@plope.com>2013-09-22 13:32:06 -0400
committerChris McDonough <chrism@plope.com>2013-09-22 13:32:06 -0400
commit3d42aa9bb8dea45fb0880d21ec604d6607280587 (patch)
treeb32cb75eb5eb05f42ac5e1b55e7bdf00492867f0
parentbf76bc25cdd952ab8fc977875d7022b601519d6e (diff)
downloadpyramid-3d42aa9bb8dea45fb0880d21ec604d6607280587.tar.gz
pyramid-3d42aa9bb8dea45fb0880d21ec604d6607280587.tar.bz2
pyramid-3d42aa9bb8dea45fb0880d21ec604d6607280587.zip
make sure that missing template renderer factories dont cause a startup time error, and instead behave like other renderers which, when missing, cause pyramid to throw a valueerror at rendering time
-rw-r--r--pyramid/config/views.py22
-rw-r--r--pyramid/tests/test_config/test_views.py42
2 files changed, 62 insertions, 2 deletions
diff --git a/pyramid/config/views.py b/pyramid/config/views.py
index 16deee987..233bbac12 100644
--- a/pyramid/config/views.py
+++ b/pyramid/config/views.py
@@ -1149,6 +1149,8 @@ class ViewsConfiguratorMixin(object):
attr, self.object_description(view))
else:
view_desc = self.object_description(view)
+
+ tmpl_intr = None
view_intr = self.introspectable('views',
discriminator,
@@ -1199,7 +1201,8 @@ class ViewsConfiguratorMixin(object):
renderer = renderers.RendererHelper(
name=None,
package=self.package,
- registry=self.registry)
+ registry=self.registry
+ )
if permission is None:
# intent: will be None if no default permission is registered
@@ -1330,6 +1333,22 @@ class ViewsConfiguratorMixin(object):
multiview,
(IExceptionViewClassifier, request_iface, context),
IMultiView, name=name)
+ renderer_type = getattr(renderer, 'type', None) # gard against None
+ intrspc = self.introspector
+ if (
+ renderer_type is not None and
+ tmpl_intr is not None and
+ intrspc is not None and
+ intrspc.get('renderer factories', renderer_type) is not None
+ ):
+ # allow failure of registered template factories to be deferred
+ # until view execution, like other bad renderer factories; if
+ # we tried to relate this to an existing renderer factory
+ # without checking if it the factory actually existed, we'd end
+ # up with a KeyError at startup time, which is inconsistent
+ # with how other bad renderer registrations behave (they throw
+ # a ValueError at view execution time)
+ tmpl_intr.relate('renderer factories', renderer.type)
if mapper:
mapper_intr = self.introspectable(
@@ -1355,7 +1374,6 @@ class ViewsConfiguratorMixin(object):
tmpl_intr['name'] = renderer.name
tmpl_intr['type'] = renderer.type
tmpl_intr['renderer'] = renderer
- tmpl_intr.relate('renderer factories', renderer.type)
introspectables.append(tmpl_intr)
if permission is not None:
# if a permission exists, register a permission introspectable
diff --git a/pyramid/tests/test_config/test_views.py b/pyramid/tests/test_config/test_views.py
index d9e0d17a6..be2865d30 100644
--- a/pyramid/tests/test_config/test_views.py
+++ b/pyramid/tests/test_config/test_views.py
@@ -109,6 +109,37 @@ class TestViewsConfigurationMixin(unittest.TestCase):
view = self._getViewCallable(config)
self.assertTrue(b'Hello!' in view(None, None).body)
+ def test_add_view_with_tmpl_renderer_factory_introspector_missing(self):
+ config = self._makeOne(autocommit=True)
+ config.introspection = False
+ config.introspector = None
+ config.add_view(renderer='dummy.pt')
+ view = self._getViewCallable(config)
+ self.assertRaises(ValueError, view, None, None)
+
+ def test_add_view_with_tmpl_renderer_factory_no_renderer_factory(self):
+ config = self._makeOne(autocommit=True)
+ introspector = DummyIntrospector()
+ config.introspector = introspector
+ config.add_view(renderer='dummy.pt')
+ self.assertFalse(('renderer factories', '.pt') in
+ introspector.related[-1])
+ view = self._getViewCallable(config)
+ self.assertRaises(ValueError, view, None, None)
+
+ def test_add_view_with_tmpl_renderer_factory_with_renderer_factory(self):
+ config = self._makeOne(autocommit=True)
+ introspector = DummyIntrospector(True)
+ config.introspector = introspector
+ def dummy_factory(helper):
+ return lambda val, system_vals: 'Hello!'
+ config.add_renderer('.pt', dummy_factory)
+ config.add_view(renderer='dummy.pt')
+ self.assertTrue(
+ ('renderer factories', '.pt') in introspector.related[-1])
+ view = self._getViewCallable(config)
+ self.assertTrue(b'Hello!' in view(None, None).body)
+
def test_add_view_wrapped_view_is_decorated(self):
def view(request): # request-only wrapper
""" """
@@ -3954,3 +3985,14 @@ class DummyPredicate(object):
phash = text
+class DummyIntrospector(object):
+ def __init__(self, getval=None):
+ self.related = []
+ self.introspectables = []
+ self.getval = getval
+ def add(self, introspectable):
+ self.introspectables.append(introspectable)
+ def get(self, name, discrim):
+ return self.getval
+ def relate(self, a, b):
+ self.related.append((a, b))