diff options
| author | Chris McDonough <chrism@plope.com> | 2013-09-22 13:32:06 -0400 |
|---|---|---|
| committer | Chris McDonough <chrism@plope.com> | 2013-09-22 13:32:06 -0400 |
| commit | 3d42aa9bb8dea45fb0880d21ec604d6607280587 (patch) | |
| tree | b32cb75eb5eb05f42ac5e1b55e7bdf00492867f0 | |
| parent | bf76bc25cdd952ab8fc977875d7022b601519d6e (diff) | |
| download | pyramid-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.py | 22 | ||||
| -rw-r--r-- | pyramid/tests/test_config/test_views.py | 42 |
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)) |
