summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--repoze/bfg/sampleapp/configure.zcml2
-rw-r--r--repoze/bfg/sampleapp/views.py4
-rw-r--r--repoze/bfg/tests/fixtureapp/configure.zcml1
-rw-r--r--repoze/bfg/tests/fixtureapp/views.py4
-rw-r--r--repoze/bfg/tests/test_zcml.py84
-rw-r--r--repoze/bfg/zcml.py28
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(