diff options
| author | Chris McDonough <chrism@agendaless.com> | 2008-07-14 08:54:26 +0000 |
|---|---|---|
| committer | Chris McDonough <chrism@agendaless.com> | 2008-07-14 08:54:26 +0000 |
| commit | c0c663bd97e4c7fe1d9971fc8070791a148f106f (patch) | |
| tree | 2ea114deb5b2cc32d9b535666707b4957f2dbef8 | |
| parent | 85427fa0479aefd59bd55dca397b9a36277edade (diff) | |
| download | pyramid-c0c663bd97e4c7fe1d9971fc8070791a148f106f.tar.gz pyramid-c0c663bd97e4c7fe1d9971fc8070791a148f106f.tar.bz2 pyramid-c0c663bd97e4c7fe1d9971fc8070791a148f106f.zip | |
And, just to maximally confuse Paul, come full circle, and don't require that the template be spelled on the class, while still allowing us to pickle the registry actions.
| -rw-r--r-- | repoze/bfg/sampleapp/configure.zcml | 2 | ||||
| -rw-r--r-- | repoze/bfg/sampleapp/views.py | 4 | ||||
| -rw-r--r-- | repoze/bfg/tests/fixtureapp/configure.zcml | 1 | ||||
| -rw-r--r-- | repoze/bfg/tests/fixtureapp/views.py | 4 | ||||
| -rw-r--r-- | repoze/bfg/tests/test_zcml.py | 84 | ||||
| -rw-r--r-- | repoze/bfg/zcml.py | 28 |
6 files changed, 103 insertions, 20 deletions
diff --git a/repoze/bfg/sampleapp/configure.zcml b/repoze/bfg/sampleapp/configure.zcml index d5cba4d33..5e7a83ffd 100644 --- a/repoze/bfg/sampleapp/configure.zcml +++ b/repoze/bfg/sampleapp/configure.zcml @@ -8,6 +8,7 @@ <bfg:view for=".models.IBlog" factory=".views.BlogDefaultView" + template="templates/blog.pt" permission="repoze.view" /> @@ -15,6 +16,7 @@ <bfg:view for=".models.IBlogEntry" factory=".views.BlogEntryDefaultView" + template="templates/blog_entry.pt" permission="repoze.view" /> diff --git a/repoze/bfg/sampleapp/views.py b/repoze/bfg/sampleapp/views.py index 98b285b67..196fce703 100644 --- a/repoze/bfg/sampleapp/views.py +++ b/repoze/bfg/sampleapp/views.py @@ -12,8 +12,6 @@ def datestring(dt): class BlogDefaultView(TemplateView): - template = 'templates/blog.pt' - def getInfo(self): entrydata = [] for name, entry in self.context.items(): @@ -29,8 +27,6 @@ class BlogDefaultView(TemplateView): class BlogEntryDefaultView(TemplateView): - template = 'templates/blog_entry.pt' - def getInfo(self): return { 'name':self.context.__name__, diff --git a/repoze/bfg/tests/fixtureapp/configure.zcml b/repoze/bfg/tests/fixtureapp/configure.zcml index f08cd58ad..99d0708aa 100644 --- a/repoze/bfg/tests/fixtureapp/configure.zcml +++ b/repoze/bfg/tests/fixtureapp/configure.zcml @@ -12,6 +12,7 @@ <bfg:view for=".models.IFixture" + factory=".views.FixtureTemplateView" template="templates/fixture.pt" permission="repoze.view" name="fixture.html" diff --git a/repoze/bfg/tests/fixtureapp/views.py b/repoze/bfg/tests/fixtureapp/views.py index b9b9fc7d9..36fe07cc6 100644 --- a/repoze/bfg/tests/fixtureapp/views.py +++ b/repoze/bfg/tests/fixtureapp/views.py @@ -1,3 +1,5 @@ +from repoze.bfg.view import TemplateView + class FixtureView(object): def __init__(self, context, request): self.context = context @@ -6,3 +8,5 @@ class FixtureView(object): def __call__(self): pass +class FixtureTemplateView(TemplateView): + pass diff --git a/repoze/bfg/tests/test_zcml.py b/repoze/bfg/tests/test_zcml.py index 11f392f78..7aaf6e4c3 100644 --- a/repoze/bfg/tests/test_zcml.py +++ b/repoze/bfg/tests/test_zcml.py @@ -100,34 +100,104 @@ class TestViewDirective(unittest.TestCase, PlacelessSetup): self.assertEqual(regadapt['args'][4], '') self.assertEqual(regadapt['args'][5], None) - def test_template_and_factory_raises(self): + def test_template_and_factory(self): f = self._getFUT() context = DummyContext() - from zope.configuration.exceptions import ConfigurationError - self.assertRaises(ConfigurationError, f, context, 'repoze.view', None, - Dummy, 'minimal.html', 'minimal.pt') + class IFoo: + pass + class DummyView: + pass + f(context, 'repoze.view', IFoo, factory=DummyView, + template='minimal.pt') + actions = context.actions + from repoze.bfg.interfaces import IView + from repoze.bfg.interfaces import IRequest + from repoze.bfg.interfaces import IViewFactory + from zope.component.zcml import handler + from zope.component.interface import provideInterface + + self.assertEqual(len(actions), 3) + + regutil_discriminator = ('utility', IView, context.path('minimal.pt')) + regutil = actions[0] + self.assertEqual(regutil['discriminator'], regutil_discriminator) + self.assertEqual(regutil['callable'], handler) + self.assertEqual(regutil['args'][0], 'registerUtility') + self.assertEqual(regutil['args'][1].template.filename, + context.path('minimal.pt')) + self.assertEqual(regutil['args'][2], IView) + self.assertEqual(regutil['args'][3], context.path('minimal.pt')) + + provide = actions[1] + self.assertEqual(provide['discriminator'], None) + self.assertEqual(provide['callable'], provideInterface) + self.assertEqual(provide['args'][0], '') + self.assertEqual(provide['args'][1], IFoo) + + regadapt = actions[2] + regadapt_discriminator = ('view', IFoo, '', IRequest, IViewFactory) + self.assertEqual(regadapt['discriminator'], regadapt_discriminator) + self.assertEqual(regadapt['callable'], handler) + self.assertEqual(regadapt['args'][0], 'registerAdapter') + self.assertEqual(regadapt['args'][1].template, + context.path('minimal.pt')) + self.assertEqual(regadapt['args'][2], (IFoo, IRequest)) + self.assertEqual(regadapt['args'][3], IViewFactory) + self.assertEqual(regadapt['args'][4], '') + self.assertEqual(regadapt['args'][5], None) class TestTemplateViewFactory(unittest.TestCase): def _getTargetClass(self): from repoze.bfg.zcml import TemplateViewFactory return TemplateViewFactory - def _makeOne(self, template): - return self._getTargetClass()(template) + def _makeOne(self, template, base=None): + return self._getTargetClass()(template, base) def test_instance_conforms_to_IViewFactory(self): from zope.interface.verify import verifyObject from repoze.bfg.interfaces import IViewFactory verifyObject(IViewFactory, self._makeOne('a')) - def test_call(self): + def test_call_templateonly(self): context = DummyContext() template = context.path('minimal.pt') factory = self._makeOne(template) view = factory(None, None) from repoze.bfg.view import TemplateView self.failUnless(isinstance(view, TemplateView)) + self.assertEqual(view.template, template) + def test_call_nonclassbase(self): + context = DummyContext() + def factory(): + pass + template = context.path('minimal.pt') + self.assertRaises(ValueError, self._makeOne, template, factory) + + def test_call_classbase_not_templateview_subclass(self): + context = DummyContext() + template = context.path('minimal.pt') + factory = self._makeOne(template, Dummy) + view = factory(None, None) + from repoze.bfg.view import TemplateView + self.assertEqual(view.__bases__[0], Dummy) + self.assertEqual(view.__bases__[1], TemplateView) + self.assertEqual(view.__name__, 'DynamicTemplateView_For_Dummy') + self.assertEqual(view.template, template) + + def test_call_classbase_templateview_subclass(self): + context = DummyContext() + template = context.path('minimal.pt') + from repoze.bfg.view import TemplateView + class TemplateViewSubclass(TemplateView): + pass + factory = self._makeOne(template, TemplateViewSubclass) + view = factory(None, None) + self.assertEqual(view.__bases__[0], TemplateViewSubclass) + self.assertEqual(view.__name__, + 'DynamicTemplateView_For_TemplateViewSubclass') + self.assertEqual(view.template, template) class Dummy: pass diff --git a/repoze/bfg/zcml.py b/repoze/bfg/zcml.py index a1a2497b5..dc05cca18 100644 --- a/repoze/bfg/zcml.py +++ b/repoze/bfg/zcml.py @@ -1,4 +1,6 @@ +import inspect import os +import new from zope.component.zcml import handler from zope.component.interface import provideInterface @@ -24,11 +26,24 @@ class TemplateViewFactory(object): implements(IViewFactory) - def __init__(self, template): + def __init__(self, template, base=None): + if base is not None: + if not inspect.isclass(base): + raise ValueError('Factory must be a class to be used ' + 'with a template, but %s was supplied' % base) self.template = template + self.base = base def __call__(self, context, request): - factory = TemplateView(context, request) + if self.base and self.base is not TemplateView: + if issubclass(self.base, TemplateView): + bases = (self.base,) + else: + bases = (self.base, TemplateView) + name = 'DynamicTemplateView_For_%s' % self.base.__name__ + factory = new.classobj(name, bases, {}) + else: + factory = TemplateView(context, request) factory.template = self.template return factory @@ -42,14 +57,9 @@ def view(_context, # XXX we do nothing yet with permission - if template and factory: - raise ConfigurationError('A template must not be specified if a ' - 'factory is also specified') - if not (template or factory): raise ConfigurationError( - 'One of template or factory must be specified') - + 'One of template or factory (or both) must be specified') if template: template_abs = os.path.abspath(str(_context.path(template))) @@ -61,7 +71,7 @@ def view(_context, callable = handler, args = ('registerUtility', utility, IView, template_abs), ) - factory = TemplateViewFactory(template_abs) + factory = TemplateViewFactory(template_abs, factory) if for_ is not None: _context.action( |
