[Checkins] SVN: grokcore.view/trunk/ Revert the CodeView split. Fix again the template = case.
Sylvain Viollon
sylvain at infrae.com
Wed Sep 16 06:06:09 EDT 2009
Log message for revision 104134:
Revert the CodeView split. Fix again the template = case.
Changed:
U grokcore.view/trunk/CHANGES.txt
U grokcore.view/trunk/src/grokcore/view/__init__.py
U grokcore.view/trunk/src/grokcore/view/components.py
U grokcore.view/trunk/src/grokcore/view/ftests/url/redirect.py
U grokcore.view/trunk/src/grokcore/view/ftests/url/url.py
U grokcore.view/trunk/src/grokcore/view/ftests/url/url_function.py
U grokcore.view/trunk/src/grokcore/view/ftests/view/argument.py
U grokcore.view/trunk/src/grokcore/view/ftests/view/macros.py
U grokcore.view/trunk/src/grokcore/view/ftests/view/require.py
U grokcore.view/trunk/src/grokcore/view/ftests/view/skindirective.py
U grokcore.view/trunk/src/grokcore/view/interfaces.py
U grokcore.view/trunk/src/grokcore/view/meta/views.py
U grokcore.view/trunk/src/grokcore/view/templatereg.py
U grokcore.view/trunk/src/grokcore/view/tests/skin/conflict.py
U grokcore.view/trunk/src/grokcore/view/tests/template/pluggability.py
D grokcore.view/trunk/src/grokcore/view/tests/view/codeview.py
D grokcore.view/trunk/src/grokcore/view/tests/view/codeviewnorender.py
U grokcore.view/trunk/src/grokcore/view/tests/view/dirtemplateandrender.py
D grokcore.view/trunk/src/grokcore/view/tests/view/norenderinview.py
D grokcore.view/trunk/src/grokcore/view/tests/view/notemplate.py
U grokcore.view/trunk/src/grokcore/view/tests/view/templatenotfound.py
A grokcore.view/trunk/src/grokcore/view/tests/view/templates/
U grokcore.view/trunk/src/grokcore/view/tests/view/view.py
U grokcore.view/trunk/src/grokcore/view/tests/view/view_decorator.py
D grokcore.view/trunk/src/grokcore/view/tests/view/view_templates/
D grokcore.view/trunk/src/grokcore/view/tests/view/viewrenderbasemethod.py
U grokcore.view/trunk/src/grokcore/view/tests/view/viewtemplateequal.py
D grokcore.view/trunk/src/grokcore/view/tests/view/viewwithrender.py
-=-
Modified: grokcore.view/trunk/CHANGES.txt
===================================================================
--- grokcore.view/trunk/CHANGES.txt 2009-09-16 09:48:34 UTC (rev 104133)
+++ grokcore.view/trunk/CHANGES.txt 2009-09-16 10:06:08 UTC (rev 104134)
@@ -8,7 +8,7 @@
copy; a local copy for all grokcore packages is just too hard to
maintain.
-- Fix View and CodeView interfaces.
+- Revert the splitting CodeView/View.
- Fix the template = way to associate a template to a view.
Modified: grokcore.view/trunk/src/grokcore/view/__init__.py
===================================================================
--- grokcore.view/trunk/src/grokcore/view/__init__.py 2009-09-16 09:48:34 UTC (rev 104133)
+++ grokcore.view/trunk/src/grokcore/view/__init__.py 2009-09-16 10:06:08 UTC (rev 104134)
@@ -19,7 +19,7 @@
from zope.publisher.interfaces.browser import IBrowserRequest
from zope.publisher.interfaces.browser import IDefaultBrowserLayer
-from grokcore.view.components import View, CodeView
+from grokcore.view.components import View
from grokcore.view.components import PageTemplate, PageTemplateFile
from grokcore.view.components import DirectoryResource
from grokcore.view.directive import layer, template, templatedir, skin, path
Modified: grokcore.view/trunk/src/grokcore/view/components.py
===================================================================
--- grokcore.view/trunk/src/grokcore/view/components.py 2009-09-16 09:48:34 UTC (rev 104133)
+++ grokcore.view/trunk/src/grokcore/view/components.py 2009-09-16 10:06:08 UTC (rev 104134)
@@ -31,12 +31,13 @@
from grokcore.view import interfaces, util
-class BaseView(BrowserPage):
- interface.implements(interfaces.IGrokBaseView)
+class View(BrowserPage):
+ interface.implements(interfaces.IGrokView)
def __init__(self, context, request):
- super(BaseView, self).__init__(context, request)
+ super(View, self).__init__(context, request)
self.__name__ = getattr(self, '__view_name__', None)
+
if getattr(self, 'module_info', None) is not None:
self.static = component.queryAdapter(
self.request,
@@ -46,12 +47,51 @@
else:
self.static = None
- def update(self, **kwargs):
- pass
+ @property
+ def response(self):
+ return self.request.response
- def redirect(self, url):
- return self.request.response.redirect(url)
+ def __call__(self):
+ mapply(self.update, (), self.request)
+ if self.request.response.getStatus() in (302, 303):
+ # A redirect was triggered somewhere in update(). Don't
+ # continue rendering the template or doing anything else.
+ return
+ template = getattr(self, 'template', None)
+ if template is not None:
+ return self._render_template()
+ return mapply(self.render, (), self.request)
+
+ def _render_template(self):
+ return self.template.render(self)
+
+ def default_namespace(self):
+ namespace = {}
+ namespace['context'] = self.context
+ namespace['request'] = self.request
+ namespace['static'] = self.static
+ namespace['view'] = self
+ return namespace
+
+ def namespace(self):
+ return {}
+
+ def __getitem__(self, key):
+ # This is BBB code for Zope page templates only:
+ if not isinstance(self.template, PageTemplate):
+ raise AttributeError("View has no item %s" % key)
+
+ value = self.template._template.macros[key]
+ # When this deprecation is done with, this whole __getitem__ can
+ # be removed.
+ warnings.warn("Calling macros directly on the view is deprecated. "
+ "Please use context/@@viewname/macros/macroname\n"
+ "View %r, macro %s" % (self, key),
+ DeprecationWarning, 1)
+ return value
+
+
def url(self, obj=None, name=None, data=None):
"""Return string for the URL based on the obj and name. The data
argument is used to form a CGI query string.
@@ -79,70 +119,18 @@
return util.url(self.request, obj, name, data=data)
- @property
- def response(self):
- return self.request.response
+ def redirect(self, url):
+ return self.request.response.redirect(url)
- def default_namespace(self):
- namespace = {}
- namespace['context'] = self.context
- namespace['request'] = self.request
- namespace['static'] = self.static
- namespace['view'] = self
- return namespace
+ def update(self, **kwargs):
+ pass
- def namespace(self):
- return {}
+ def render(self, **kwargs):
+ pass
+ render.base_method = True
-class CodeView(BaseView):
- interface.implements(interfaces.IGrokCodeView)
-
- def __init__(self, context, request):
- super(CodeView, self).__init__(context, request)
-
- def __call__(self, *args, **kwargs):
- mapply(self.update, (), self.request)
- if self.request.response.getStatus() in (302, 303):
- # A redirect was triggered somewhere in update(). Don't
- # continue rendering the template or doing anything else.
- return
-
- return mapply(self.render, (), self.request)
-
-
-class View(BaseView):
-
- interface.implements(interfaces.IGrokView)
-
- def __init__(self, context, request):
- super(View, self).__init__(context, request)
-
- def __call__(self, *args, **kwargs):
- mapply(self.update, (), self.request)
- if self.request.response.getStatus() in (302, 303):
- # A redirect was triggered somewhere in update(). Don't
- # continue rendering the template or doing anything else.
- return
-
- return self.template.render(self)
-
- def __getitem__(self, key):
- # This is BBB code for Zope page templates only:
- if not isinstance(self.template, PageTemplate):
- raise AttributeError("View has no item %s" % key)
-
- value = self.template._template.macros[key]
- # When this deprecation is done with, this whole __getitem__ can
- # be removed.
- warnings.warn("Calling macros directly on the view is deprecated. "
- "Please use context/@@viewname/macros/macroname\n"
- "View %r, macro %s" % (self, key),
- DeprecationWarning, 1)
- return value
-
-
class BaseTemplate(object):
"""Any sort of page template"""
@@ -211,12 +199,15 @@
namespace.update(view.namespace())
return namespace
+
class TrustedPageTemplate(TrustedAppPT, pagetemplate.PageTemplate):
pass
+
class TrustedFilePageTemplate(TrustedAppPT, pagetemplatefile.PageTemplateFile):
pass
+
class PageTemplate(GrokTemplate):
def setFromString(self, string):
@@ -239,7 +230,7 @@
factory.macros = property(_get_macros)
def render(self, view):
- assert interfaces.IGrokBaseView.providedBy(view)
+ assert interfaces.IGrokView.providedBy(view)
namespace = self.getNamespace(view)
template = self._template
namespace.update(template.pt_getContext())
@@ -254,6 +245,7 @@
_prefix = os.path.dirname(module.__file__)
self.setFromFilename(filename, _prefix)
+
class DirectoryResource(directoryresource.DirectoryResource):
# We subclass this, because we want to override factories for
# .pt and .html file types, not creating pagetemplate resources.
@@ -268,8 +260,10 @@
# having defined the DirectoryResourceFactory class.
directory_factory = None
+
class DirectoryResourceFactory(directoryresource.DirectoryResourceFactory):
# We need this to allow hooking up our own DirectoryResource class.
factoryClass = DirectoryResource
+
DirectoryResource.directory_factory = DirectoryResourceFactory
Modified: grokcore.view/trunk/src/grokcore/view/ftests/url/redirect.py
===================================================================
--- grokcore.view/trunk/src/grokcore/view/ftests/url/redirect.py 2009-09-16 09:48:34 UTC (rev 104133)
+++ grokcore.view/trunk/src/grokcore/view/ftests/url/redirect.py 2009-09-16 10:06:08 UTC (rev 104134)
@@ -12,18 +12,18 @@
>>> browser.open('http://localhost/manfred')
>>> browser.url
'http://localhost/manfred/another'
-
+
"""
import grokcore.view as grok
class Mammoth(grok.Context):
pass
-class Index(grok.CodeView):
+class Index(grok.View):
def render(self):
self.redirect(self.url('another'))
-class Another(grok.CodeView):
+class Another(grok.View):
def render(self):
return "Another view"
Modified: grokcore.view/trunk/src/grokcore/view/ftests/url/url.py
===================================================================
--- grokcore.view/trunk/src/grokcore/view/ftests/url/url.py 2009-09-16 09:48:34 UTC (rev 104133)
+++ grokcore.view/trunk/src/grokcore/view/ftests/url/url.py 2009-09-16 10:06:08 UTC (rev 104134)
@@ -180,18 +180,18 @@
grok.context(Mammoth)
-class Index(grok.CodeView):
+class Index(grok.View):
def render(self):
return self.url()
-class Another(grok.CodeView):
+class Another(grok.View):
def render(self):
return self.url()
class YetAnother(grok.View):
pass
-class Multiplier(grok.CodeView):
+class Multiplier(grok.View):
def update(self, age=0):
self.age = age
Modified: grokcore.view/trunk/src/grokcore/view/ftests/url/url_function.py
===================================================================
--- grokcore.view/trunk/src/grokcore/view/ftests/url/url_function.py 2009-09-16 09:48:34 UTC (rev 104133)
+++ grokcore.view/trunk/src/grokcore/view/ftests/url/url_function.py 2009-09-16 10:06:08 UTC (rev 104134)
@@ -61,26 +61,20 @@
>>> expected = unicode('http://127.0.0.1/herd/árgh', 'UTF-8')
>>> urllib.unquote(u).decode('utf-8') == expected
True
-
"""
import grokcore.view as grok
from grokcore.view import url
from zope.app.container.contained import Contained
-
class Mammoth(Contained):
pass
grok.context(Mammoth)
-
-class Index(grok.CodeView):
+class Index(grok.View):
def render(self):
return url(self.request, self)
-
class Another(grok.View):
- pass
-
-
-another = grok.PageTemplate('<p tal:replace="view/url" />')
+ def render(self):
+ return url(self.request, self)
Modified: grokcore.view/trunk/src/grokcore/view/ftests/view/argument.py
===================================================================
--- grokcore.view/trunk/src/grokcore/view/ftests/view/argument.py 2009-09-16 09:48:34 UTC (rev 104133)
+++ grokcore.view/trunk/src/grokcore/view/ftests/view/argument.py 2009-09-16 10:06:08 UTC (rev 104134)
@@ -49,18 +49,15 @@
"""
import grokcore.view as grok
-
class Mammoth(grok.Context):
pass
-
-class RenderWithArguments(grok.CodeView):
+class RenderWithArguments(grok.View):
grok.name('render')
def render(self, message, another):
return "Message: %s\nAnother: %s" % (message, another)
-
class UpdateWithArguments(grok.View):
grok.name('update')
grok.template('update')
@@ -69,7 +66,6 @@
self.message = message
self.another = another
-
update = grok.PageTemplate("""
Coming to us from update():
Message: <span tal:replace="view/message" />
Modified: grokcore.view/trunk/src/grokcore/view/ftests/view/macros.py
===================================================================
--- grokcore.view/trunk/src/grokcore/view/ftests/view/macros.py 2009-09-16 09:48:34 UTC (rev 104133)
+++ grokcore.view/trunk/src/grokcore/view/ftests/view/macros.py 2009-09-16 10:06:08 UTC (rev 104134)
@@ -19,8 +19,7 @@
>>> browser.open("http://localhost/manfred/@@dancing")
Traceback (most recent call last):
- ...
- TraversalError: (<grokcore.view.ftests.view.macros.DancingHall object at ...>, 'macros')
+ AttributeError: 'DancingHall' object has no attribute 'template'
If the view has an attribute with the same name as a macro, the macro
shadows the view. XXX This should probably generate a warning at runtime.
@@ -72,36 +71,26 @@
>>> open(template_file, 'w').write(before)
+
"""
import grokcore.view as grok
-
class Mammoth(grok.Context):
pass
+class DancingHall(grok.View):
-class DancingHall(grok.CodeView):
-
def render(self):
- return "Bla Bla Dancing Hall"
+ return "A nice large dancing hall for mammoths."
-
class Grilled(grok.View):
def update(self):
self.spices = "Pepper and salt"
-
-grilled = grok.PageTemplate("""\
-<html metal:define-macro="spices">
-Curry
-</html>""")
-
-
class Painting(grok.View):
pass
-
painting = grok.PageTemplate("""\
<html metal:use-macro="context/@@layout/macros/main">
<div metal:fill-slot="slot">
@@ -110,40 +99,38 @@
</html>
""")
-
class Layout(grok.View):
# Layout template is in macros_templates/layout.pt for reload test
# purposes.
pass
-
class Dancing(grok.View):
pass
-
dancing = grok.PageTemplate("""\
<html metal:use-macro="context/@@dancinghall/macros/something">
</html>
""")
-
class GrillDish(grok.View):
pass
-
grilldish = grok.PageTemplate("""
<html metal:use-macro="context/@@grilled/macros/spices">
</html>""")
-
-
class Burnt(grok.View):
pass
-
burnt = grok.PageTemplate("""\
<html metal:use-macro="context/@@grilled/spices">
</html>""")
+class Grilled(grok.View):
+ pass
+grilled = grok.PageTemplate("""\
+<html metal:define-macro="spices">
+Curry
+</html>""")
Modified: grokcore.view/trunk/src/grokcore/view/ftests/view/require.py
===================================================================
--- grokcore.view/trunk/src/grokcore/view/ftests/view/require.py 2009-09-16 09:48:34 UTC (rev 104133)
+++ grokcore.view/trunk/src/grokcore/view/ftests/view/require.py 2009-09-16 10:06:08 UTC (rev 104134)
@@ -27,20 +27,17 @@
import grokcore.view as grok
import zope.interface
-
class ViewPainting(grok.Permission):
grok.name('cave.ViewPainting')
-
-class Painting(grok.CodeView):
+class Painting(grok.View):
grok.context(zope.interface.Interface)
grok.require(ViewPainting)
def render(self):
return 'What a beautiful painting.'
-
-class PublicNudity(grok.CodeView):
+class PublicNudity(grok.View):
grok.context(zope.interface.Interface)
grok.require(grok.Public)
Modified: grokcore.view/trunk/src/grokcore/view/ftests/view/skindirective.py
===================================================================
--- grokcore.view/trunk/src/grokcore/view/ftests/view/skindirective.py 2009-09-16 09:48:34 UTC (rev 104133)
+++ grokcore.view/trunk/src/grokcore/view/ftests/view/skindirective.py 2009-09-16 10:06:08 UTC (rev 104134)
@@ -47,14 +47,14 @@
</html>
""")
-class MoreDrawings(grok.CodeView):
+class MoreDrawings(grok.View):
grok.layer(rotterdam)
def render(self):
return "Pretty"
-class EvenMoreDrawings(grok.CodeView):
+class EvenMoreDrawings(grok.View):
grok.layer(MySkinLayer)
def render(self):
Modified: grokcore.view/trunk/src/grokcore/view/interfaces.py
===================================================================
--- grokcore.view/trunk/src/grokcore/view/interfaces.py 2009-09-16 09:48:34 UTC (rev 104133)
+++ grokcore.view/trunk/src/grokcore/view/interfaces.py 2009-09-16 10:06:08 UTC (rev 104134)
@@ -19,7 +19,6 @@
class IBaseClasses(Interface):
View = Attribute("Base class for browser views.")
- CodeView = Attribute("Base class for browser views with render().")
DirectoryResource = Attribute("Base class to create new "
"directory resource.")
@@ -74,7 +73,7 @@
IDefaultBrowserLayer = Attribute('Default layer for browser views.')
-class IGrokBaseView(IBrowserPage, IBrowserView):
+class IGrokView(IBrowserPage, IBrowserView):
"""Grok views all provide this interface."""
context = Attribute('context', "Object that the view presents.")
@@ -84,6 +83,9 @@
response = Attribute('response', "Response object that is "
"associated with the current request.")
+ static = Attribute('static', "Directory resource containing "
+ "the static files of the view's package.")
+
def redirect(url):
"""Redirect to given URL"""
@@ -104,19 +106,6 @@
as a cgi query string.
"""
- def update(**kw):
- """This method is meant to be implemented by grok.View
- subclasses. It will be called *before* the view's associated
- template is rendered and can be used to pre-compute values
- for the template.
-
- update() can take arbitrary keyword parameters which will be
- filled in from the request (in that case they *must* be
- present in the request)."""
-
- static = Attribute('static', "Directory resource containing "
- "the static files of the view's package.")
-
def default_namespace():
"""Returns a dictionary of namespaces that the template
implementation expects to always be available.
@@ -133,8 +122,15 @@
developer.
"""
+ def update(**kw):
+ """This method is meant to be implemented by grok.View
+ subclasses. It will be called *before* the view's associated
+ template is rendered and can be used to pre-compute values
+ for the template.
-class IGrokCodeView(IGrokBaseView):
+ update() can take arbitrary keyword parameters which will be
+ filled in from the request (in that case they *must* be
+ present in the request)."""
def render(**kw):
"""A view can either be rendered by an associated template, or
@@ -146,12 +142,12 @@
filled in from the request (in that case they *must* be
present in the request)."""
+ def __call__():
+ """This is the main method called by Zope to render the
+ view. You can use that method if you whish to render the
+ view."""
-class IGrokView(IGrokBaseView):
- """Marker Interface for Views with a template
- """
-
class ITemplateFileFactory(Interface):
"""Utility that generates templates from files in template directories.
"""
Modified: grokcore.view/trunk/src/grokcore/view/meta/views.py
===================================================================
--- grokcore.view/trunk/src/grokcore/view/meta/views.py 2009-09-16 09:48:34 UTC (rev 104133)
+++ grokcore.view/trunk/src/grokcore/view/meta/views.py 2009-09-16 10:06:08 UTC (rev 104134)
@@ -46,18 +46,14 @@
return super(ViewGrokker, self).grok(name, factory, module_info, **kw)
def execute(self, factory, config, context, layer, name, **kw):
- # Make sure that we have a render Method
- render = getattr(factory, 'render', None)
- if render and not getattr(render, 'base_method', False):
- raise GrokError("View Class '%s' has a render method, use CodeView instead" % factory, factory)
-
# find templates
templates = factory.module_info.getAnnotation('grok.templates', None)
- config.action(
- discriminator=None,
- callable=self.checkTemplates,
- args=(templates, factory.module_info, factory)
- )
+ if templates is not None:
+ config.action(
+ discriminator=None,
+ callable=self.checkTemplates,
+ args=(templates, factory.module_info, factory)
+ )
# safety belt: make sure that the programmer didn't use
# @grok.require on any of the view's methods.
@@ -80,54 +76,21 @@
)
return True
-
def checkTemplates(self, templates, module_info, factory):
- templates.checkTemplates(module_info, factory, 'view')
+ def has_render(factory):
+ render = getattr(factory, 'render', None)
+ base_method = getattr(render, 'base_method', False)
+ return render and not base_method
-class CodeViewGrokker(martian.ClassGrokker):
- martian.component(components.CodeView)
- martian.directive(grokcore.component.context)
- martian.directive(grokcore.view.layer, default=IDefaultBrowserLayer)
- martian.directive(grokcore.component.name, get_default=default_view_name)
+ def has_no_render(factory):
+ return not getattr(factory, 'render', None)
+ templates.checkTemplates(module_info, factory, 'view',
+ has_render, has_no_render)
- def grok(self, name, factory, module_info, **kw):
- # Need to store the module info object on the view class so that it
- # can look up the 'static' resource directory.
- factory.module_info = module_info
- return super(CodeViewGrokker, self).grok(name, factory, module_info, **kw)
- def execute(self, factory, config, context, layer, name, **kw):
-
- # Make sure that we have a render Method
- render = getattr(factory, 'render', None)
- if not render:
- raise GrokError("CodeView Class '%s' without an render method" % factory, factory)
-
- # safety belt: make sure that the programmer didn't use
- # @grok.require on any of the view's methods.
- methods = util.methods_from_class(factory)
- for method in methods:
- if grokcore.security.require.bind().get(method) is not None:
- raise GrokError('The @grok.require decorator is used for '
- 'method %r in view %r. It may only be used '
- 'for XML-RPC methods.'
- % (method.__name__, factory), factory)
-
- # __view_name__ is needed to support IAbsoluteURL on views
- factory.__view_name__ = name
- adapts = (context, layer)
-
- config.action(
- discriminator=('adapter', adapts, interface.Interface, name),
- callable=component.provideAdapter,
- args=(factory, adapts, interface.Interface, name),
- )
- return True
-
-
class ViewSecurityGrokker(martian.ClassGrokker):
- martian.component(components.BaseView)
+ martian.component(components.View)
martian.directive(grokcore.security.require, name='permission')
def execute(self, factory, config, permission, **kw):
Modified: grokcore.view/trunk/src/grokcore/view/templatereg.py
===================================================================
--- grokcore.view/trunk/src/grokcore/view/templatereg.py 2009-09-16 09:48:34 UTC (rev 104133)
+++ grokcore.view/trunk/src/grokcore/view/templatereg.py 2009-09-16 10:06:08 UTC (rev 104134)
@@ -4,7 +4,7 @@
import grokcore.component
import grokcore.view
from martian.error import GrokError
-from grokcore.view.interfaces import ITemplateFileFactory
+from grokcore.view.interfaces import ITemplateFileFactory, ITemplate
from grokcore.view.components import PageTemplate
class TemplateRegistry(object):
@@ -90,7 +90,9 @@
module_info.dotted_name, ', '.join(unassociated)))
warnings.warn(msg, UserWarning, 1)
- def checkTemplates(self, module_info, factory, component_name):
+ def checkTemplates(self, module_info, factory, component_name,
+ has_render, has_no_render):
+ # TODO: remove has_no_render arg, it's not used anymore
factory_name = factory.__name__.lower()
template_name = grokcore.view.template.bind().get(factory)
if template_name is None:
@@ -105,15 +107,38 @@
"a template called '%s'."
% (component_name, factory, template_name,
factory_name), factory)
+
+ # Check if view already have a template
+ factory_have_template = (
+ getattr(factory, 'template', None) is not None and
+ ITemplate.providedBy(factory.template))
+
+ # Lookup a template in the registry
template = self.get(template_name)
if template is not None:
self.markAssociated(template_name)
factory.template = template
- elif getattr(factory, 'template', None) is None:
- raise GrokError("%s %r has no associated template." %
+ factory_have_template = True
+
+ if factory_have_template and has_render(factory):
+ # we do not accept render and template both for a view
+ # (unless it's a form, they happen to have render.
+ raise GrokError(
+ "Multiple possible ways to render %s %r. "
+ "It has both a 'render' method as well as "
+ "an associated template." %
+ (component_name, factory), factory)
+
+ if not factory_have_template and not has_render(factory):
+ # we do not accept a view without any way to render it
+ raise GrokError("%s %r has no associated template or "
+ "'render' method." %
(component_name.title(), factory), factory)
- factory.template._initFactory(factory)
+ if factory_have_template:
+ factory.template._initFactory(factory)
+
+
class PageTemplateFileFactory(grokcore.component.GlobalUtility):
grokcore.component.implements(ITemplateFileFactory)
grokcore.component.name('pt')
Modified: grokcore.view/trunk/src/grokcore/view/tests/skin/conflict.py
===================================================================
--- grokcore.view/trunk/src/grokcore/view/tests/skin/conflict.py 2009-09-16 09:48:34 UTC (rev 104133)
+++ grokcore.view/trunk/src/grokcore/view/tests/skin/conflict.py 2009-09-16 10:06:08 UTC (rev 104134)
@@ -10,10 +10,8 @@
import grokcore.view as grok
-
class Skin1(grok.IBrowserRequest):
grok.skin('foo')
-
class Skin2(grok.IBrowserRequest):
grok.skin('foo')
Modified: grokcore.view/trunk/src/grokcore/view/tests/template/pluggability.py
===================================================================
--- grokcore.view/trunk/src/grokcore/view/tests/template/pluggability.py 2009-09-16 09:48:34 UTC (rev 104133)
+++ grokcore.view/trunk/src/grokcore/view/tests/template/pluggability.py 2009-09-16 10:06:08 UTC (rev 104134)
@@ -2,12 +2,12 @@
Testing the plugging in of a template language
>>> grok.testing.grok(__name__)
-
+
>>> cave = Cave()
>>> from zope.publisher.browser import TestRequest
>>> request = TestRequest()
>>> from zope import component
-
+
# The inline template should work:
>>> view = component.getMultiAdapter((cave, request), name='sebaayeni')
>>> print view()
@@ -23,7 +23,7 @@
>>> print view()
<html><body>Kakadu is in Australia</body></html>
- # We should be able to extend the namespac in the view and
+ # We should be able to extend the namespac in the view and
>>> view = component.getMultiAdapter((cave, request), name='sierra')
>>> print view()
<html><body>Sierra de San Fransisco is in Mexico</body></html>
@@ -33,15 +33,14 @@
# Dummy template language:
class MyTemplate(object):
-
+
def __init__(self, text):
self._text = text
-
+
def render(self, **kw):
# Silliest template language ever:
return self._text % kw
-
class MyPageTemplate(grok.components.GrokTemplate):
def setFromString(self, string):
@@ -71,19 +70,19 @@
class Sebaayeni(grok.View):
pass
-
+
sebaayeni = MyPageTemplate('<html><body>Sebaayeni is in South Africa</body></html>')
class Lascaux(grok.View):
pass
-
+
lascaux = MyPageTemplate(filename='lascaux.html')
class Kakadu(grok.View):
pass
class Sierra(grok.View):
-
+
def namespace(self):
return {'cave': 'Sierra de San Fransisco',
'country': 'Mexico'}
Deleted: grokcore.view/trunk/src/grokcore/view/tests/view/codeview.py
===================================================================
--- grokcore.view/trunk/src/grokcore/view/tests/view/codeview.py 2009-09-16 09:48:34 UTC (rev 104133)
+++ grokcore.view/trunk/src/grokcore/view/tests/view/codeview.py 2009-09-16 10:06:08 UTC (rev 104134)
@@ -1,29 +0,0 @@
-"""
-
- >>> grok.testing.grok(__name__)
-
- >>> from zope.publisher.browser import TestRequest
- >>> from zope.interface.verify import verifyObject
- >>> from zope.component import getMultiAdapter
- >>> from grokcore.view.interfaces import IGrokCodeView
-
- >>> mammoth = Mammoth()
-
- >>> code_view = getMultiAdapter((mammoth, TestRequest()), name="cavepainting")
- >>> print code_view()
- A cave painting of a mammoth
-
- >>> verifyObject(IGrokCodeView, code_view)
- True
-
-"""
-
-import grokcore.view as grok
-
-class Mammoth(grok.Context):
- pass
-
-class CavePainting(grok.CodeView):
-
- def render(self, **kwargs):
- return 'A cave painting of a mammoth'
Deleted: grokcore.view/trunk/src/grokcore/view/tests/view/codeviewnorender.py
===================================================================
--- grokcore.view/trunk/src/grokcore/view/tests/view/codeviewnorender.py 2009-09-16 09:48:34 UTC (rev 104133)
+++ grokcore.view/trunk/src/grokcore/view/tests/view/codeviewnorender.py 2009-09-16 10:06:08 UTC (rev 104134)
@@ -1,16 +0,0 @@
-"""
-
- >>> grok.testing.grok(__name__)
- Traceback (most recent call last):
- ...
- GrokError: CodeView Class '<class 'grokcore.view.tests.view.codeviewnorender.CaveTiger'>' without an render method
-
-"""
-
-import grokcore.view as grok
-
-class Mammoth(grok.Context):
- pass
-
-class CaveTiger(grok.CodeView):
- pass
Modified: grokcore.view/trunk/src/grokcore/view/tests/view/dirtemplateandrender.py
===================================================================
--- grokcore.view/trunk/src/grokcore/view/tests/view/dirtemplateandrender.py 2009-09-16 09:48:34 UTC (rev 104133)
+++ grokcore.view/trunk/src/grokcore/view/tests/view/dirtemplateandrender.py 2009-09-16 10:06:08 UTC (rev 104134)
@@ -1,13 +1,15 @@
"""
-A View may only have an associated template. Not a render-method, for that
-you must use CodeView. Here we check that this also works for templates in a
-template-directory:
+A View may either have an associated template or a render-method. Here
+we check that this also works for templates in a template-directory:
- >>> grok.testing.grok(__name__)
- Traceback (most recent call last):
+ >>> grok.testing.grok(__name__)
+ Traceback (most recent call last):
...
- GrokError: View Class '<class 'grokcore.view.tests.view.dirtemplateandrender.CavePainting'>' has a render method, use CodeView instead
-
+ ConfigurationExecutionError: martian.error.GrokError: Multiple possible ways to render view
+ <class 'grokcore.view.tests.view.dirtemplateandrender.CavePainting'>.
+ It has both a 'render' method as well as an associated template.
+ in:
+
"""
import grokcore.view as grok
Deleted: grokcore.view/trunk/src/grokcore/view/tests/view/norenderinview.py
===================================================================
--- grokcore.view/trunk/src/grokcore/view/tests/view/norenderinview.py 2009-09-16 09:48:34 UTC (rev 104133)
+++ grokcore.view/trunk/src/grokcore/view/tests/view/norenderinview.py 2009-09-16 10:06:08 UTC (rev 104134)
@@ -1,20 +0,0 @@
-"""
-Only a template may be specified, not a render() method. Use CodeView if you
-want a render method.
-
- >>> grok.testing.grok(__name__)
- Traceback (most recent call last):
- ...
- GrokError: View Class '<class 'grokcore.view.tests.view.norenderinview.CavePainting'>' has a render method, use CodeView instead
-
-"""
-import grokcore.view as grok
-
-class Mammoth(grok.Context):
- pass
-
-class CavePainting(grok.View):
- def render(self):
- pass
-
-cavepainting = grok.PageTemplate("nothing")
Deleted: grokcore.view/trunk/src/grokcore/view/tests/view/notemplate.py
===================================================================
--- grokcore.view/trunk/src/grokcore/view/tests/view/notemplate.py 2009-09-16 09:48:34 UTC (rev 104133)
+++ grokcore.view/trunk/src/grokcore/view/tests/view/notemplate.py 2009-09-16 10:06:08 UTC (rev 104134)
@@ -1,19 +0,0 @@
-"""
-Views need an associated template.
-
- >>> grok.testing.grok(__name__)
- Traceback (most recent call last):
- ...
- ConfigurationExecutionError: <class 'martian.error.GrokError'>: View <class 'grokcore.view.tests.view.notemplate.CavePainting'> has no associated template.
- in:
- <BLANKLINE>
-
-"""
-
-import grokcore.view as grok
-
-class Mammoth(grok.Context):
- pass
-
-class CavePainting(grok.View):
- pass
Modified: grokcore.view/trunk/src/grokcore/view/tests/view/templatenotfound.py
===================================================================
--- grokcore.view/trunk/src/grokcore/view/tests/view/templatenotfound.py 2009-09-16 09:48:34 UTC (rev 104133)
+++ grokcore.view/trunk/src/grokcore/view/tests/view/templatenotfound.py 2009-09-16 10:06:08 UTC (rev 104134)
@@ -2,15 +2,13 @@
This should fail because ``grok.template`` points to a non-existing
template:
- >>> grok.testing.grok(__name__)
- Traceback (most recent call last):
+ >>> grok.testing.grok(__name__)
+ Traceback (most recent call last):
...
- ConfigurationExecutionError: <class 'martian.error.GrokError'>: View <class 'grokcore.view.tests.view.templatenotfound.Painting'> has no associated template.
- in:
-
-
+ ConfigurationExecutionError: martian.error.GrokError: View <class 'grokcore.view.tests.view.templatenotfound.Painting'>
+ has no associated template or 'render' method.
+ in:
"""
-
import grokcore.view as grok
class Mammoth(grok.Context):
Modified: grokcore.view/trunk/src/grokcore/view/tests/view/view.py
===================================================================
--- grokcore.view/trunk/src/grokcore/view/tests/view/view.py 2009-09-16 09:48:34 UTC (rev 104133)
+++ grokcore.view/trunk/src/grokcore/view/tests/view/view.py 2009-09-16 10:06:08 UTC (rev 104134)
@@ -2,9 +2,6 @@
>>> grok.testing.grok(__name__)
- >>> from zope.interface.verify import verifyObject
- >>> from grokcore.view.interfaces import IGrokView
-
We should find the ``cavepainting`` view for a mammoth:
>>> manfred = Mammoth()
@@ -12,23 +9,24 @@
>>> request = TestRequest()
>>> from zope import component
>>> view = component.getMultiAdapter((manfred, request), name='cavepainting')
- >>> print view()
- A cave painting of a mammoth
+ >>> view()
+ 'A cave painting of a mammoth'
>>> view.context is manfred
True
>>> view.request is request
True
+
+ >>> from zope.interface.verify import verifyObject
+ >>> from grokcore.view.interfaces import IGrokView
>>> verifyObject(IGrokView, view)
True
Look up a view with a name explicitly set with ``grok.name``:
>>> view = component.getMultiAdapter((manfred, request), name='meal')
- >>> print view()
- Mammoth burger
- >>> verifyObject(IGrokView, view)
- True
+ >>> view()
+ 'Mammoth burger'
There's no view 'food':
@@ -41,14 +39,20 @@
import grokcore.view as grok
+
class Mammoth(grok.Context):
pass
+
class CavePainting(grok.View):
- pass
+ def render(self, **kwargs):
+ return 'A cave painting of a mammoth'
+
+
class Food(grok.View):
"""Grok says: ME NO SEE MAMMOTH, ME SEE MEAL!"""
grok.name('meal')
- grok.template('meal')
+ def render(self):
+ return 'Mammoth burger'
Modified: grokcore.view/trunk/src/grokcore/view/tests/view/view_decorator.py
===================================================================
--- grokcore.view/trunk/src/grokcore/view/tests/view/view_decorator.py 2009-09-16 09:48:34 UTC (rev 104133)
+++ grokcore.view/trunk/src/grokcore/view/tests/view/view_decorator.py 2009-09-16 10:06:08 UTC (rev 104134)
@@ -12,12 +12,10 @@
import grokcore.view as grok
import zope.interface
-
class Bogus(grok.Permission):
grok.name('bogus.perm')
-
-class BogusView(grok.CodeView):
+class BogusView(grok.View):
grok.context(zope.interface.Interface)
@grok.require(Bogus)
Deleted: grokcore.view/trunk/src/grokcore/view/tests/view/viewrenderbasemethod.py
===================================================================
--- grokcore.view/trunk/src/grokcore/view/tests/view/viewrenderbasemethod.py 2009-09-16 09:48:34 UTC (rev 104133)
+++ grokcore.view/trunk/src/grokcore/view/tests/view/viewrenderbasemethod.py 2009-09-16 10:06:08 UTC (rev 104134)
@@ -1,28 +0,0 @@
-"""
-
- >>> grok.testing.grok(__name__)
-
- >>> from zope.publisher.browser import TestRequest
- >>> from zope.component import getMultiAdapter
-
- >>> mammoth = Mammoth()
-
- >>> view = getMultiAdapter((mammoth, TestRequest()), name="cavepicture")
- >>> print view()
- <b> cave picture </b>
-
-"""
-
-import grokcore.view as grok
-
-class Mammoth(grok.Context):
- pass
-
-class CavePicture(grok.View):
-
- def render(self):
- return 'A cave painting of a mammoth'
-
- render.base_method = True
-
-cavepicture = grok.PageTemplate('<b> cave picture </b>')
Modified: grokcore.view/trunk/src/grokcore/view/tests/view/viewtemplateequal.py
===================================================================
--- grokcore.view/trunk/src/grokcore/view/tests/view/viewtemplateequal.py 2009-09-16 09:48:34 UTC (rev 104133)
+++ grokcore.view/trunk/src/grokcore/view/tests/view/viewtemplateequal.py 2009-09-16 10:06:08 UTC (rev 104134)
@@ -30,5 +30,5 @@
pass
class CavePainting(grok.View):
- template = grok.PageTemplate(filename='view_templates/cavepainting.pt')
+ template = grok.PageTemplate(filename='templates/cavepainting.pt')
Deleted: grokcore.view/trunk/src/grokcore/view/tests/view/viewwithrender.py
===================================================================
--- grokcore.view/trunk/src/grokcore/view/tests/view/viewwithrender.py 2009-09-16 09:48:34 UTC (rev 104133)
+++ grokcore.view/trunk/src/grokcore/view/tests/view/viewwithrender.py 2009-09-16 10:06:08 UTC (rev 104134)
@@ -1,18 +0,0 @@
-"""
-
- >>> grok.testing.grok(__name__)
- Traceback (most recent call last):
- ...
- GrokError: View Class '<class 'grokcore.view.tests.view.viewwithrender.CavePainting'>' has a render method, use CodeView instead
-
-"""
-
-import grokcore.view as grok
-
-class Mammoth(grok.Context):
- pass
-
-class CavePainting(grok.View):
-
- def render(self):
- return 'A cave painting of a mammoth'
More information about the checkins
mailing list