[Checkins] SVN: grok/branches/snowsprint-viewlets2/src/grok/ Make
it possible for viewlets to auto-associate with a viewlet manager.
Martijn Faassen
faassen at infrae.com
Thu Jan 24 12:54:29 EST 2008
Log message for revision 83184:
Make it possible for viewlets to auto-associate with a viewlet manager.
Refactored the way context is determined into a more generic functionality
that can also determine the module-level viewletmanager.
Changed:
A grok/branches/snowsprint-viewlets2/src/grok/ftests/viewlet/viewlet_manager_association.py
A grok/branches/snowsprint-viewlets2/src/grok/ftests/viewlet/viewlet_manager_association_templates/
A grok/branches/snowsprint-viewlets2/src/grok/ftests/viewlet/viewlet_manager_association_templates/index.pt
U grok/branches/snowsprint-viewlets2/src/grok/meta.py
A grok/branches/snowsprint-viewlets2/src/grok/tests/viewlet/viewlet_ambiguous_manager.py
U grok/branches/snowsprint-viewlets2/src/grok/tests/viewlet/viewlet_render_and_template.py
U grok/branches/snowsprint-viewlets2/src/grok/util.py
-=-
Added: grok/branches/snowsprint-viewlets2/src/grok/ftests/viewlet/viewlet_manager_association.py
===================================================================
--- grok/branches/snowsprint-viewlets2/src/grok/ftests/viewlet/viewlet_manager_association.py (rev 0)
+++ grok/branches/snowsprint-viewlets2/src/grok/ftests/viewlet/viewlet_manager_association.py 2008-01-24 17:54:28 UTC (rev 83184)
@@ -0,0 +1,33 @@
+"""
+We check whether viewlets automatically associate with a viewletmanager (if
+only one of them is present).
+
+Set up the model object to view::
+
+ >>> root = getRootFolder()
+ >>> root['cave'] = Cave()
+
+Viewing the cave object should result in the viewlet being displayed::
+
+ >>> from zope.testbrowser.testing import Browser
+ >>> browser = Browser()
+ >>> browser.handleErrors = False
+ >>> browser.open("http://localhost/cave")
+ >>> print browser.contents
+ Me say HI
+
+"""
+import grok
+
+class CavemenViewletManager(grok.ViewletManager):
+ grok.name('manage.cavemen')
+
+class FredViewlet(grok.Viewlet):
+ def render(self):
+ return "Me say HI"
+
+class Cave(grok.Model):
+ pass
+
+class Index(grok.View):
+ pass
Added: grok/branches/snowsprint-viewlets2/src/grok/ftests/viewlet/viewlet_manager_association_templates/index.pt
===================================================================
--- grok/branches/snowsprint-viewlets2/src/grok/ftests/viewlet/viewlet_manager_association_templates/index.pt (rev 0)
+++ grok/branches/snowsprint-viewlets2/src/grok/ftests/viewlet/viewlet_manager_association_templates/index.pt 2008-01-24 17:54:28 UTC (rev 83184)
@@ -0,0 +1 @@
+<tal:block replace="structure provider:manage.cavemen" />
Modified: grok/branches/snowsprint-viewlets2/src/grok/meta.py
===================================================================
--- grok/branches/snowsprint-viewlets2/src/grok/meta.py 2008-01-24 17:48:16 UTC (rev 83183)
+++ grok/branches/snowsprint-viewlets2/src/grok/meta.py 2008-01-24 17:54:28 UTC (rev 83184)
@@ -49,16 +49,20 @@
import grok
from grok import components, formlib, templatereg
from grok.util import check_adapts, get_default_permission, make_checker
-from grok.util import check_context, determine_module_context
-from grok.util import determine_class_context
+from grok.util import check_module_component, determine_module_component
+from grok.util import determine_class_component
from grok.util import determine_class_directive, public_methods_from_class
from grok.rest import RestPublisher
from grok.interfaces import IRESTSkinType
def get_context(module_info, factory):
- context = module_info.getAnnotation('grok.context', None)
- return determine_class_context(factory, context)
+ return determine_class_component(module_info, factory,
+ 'context', 'grok.context')
+def get_viewletmanager(module_info, factory):
+ return determine_class_component(module_info, factory,
+ 'viewletmanager', 'grok.viewletmanager')
+
def get_name_classname(factory):
return get_name(factory, factory.__name__.lower())
@@ -76,13 +80,23 @@
priority = 1001
def grok(self, name, module, module_info, config, **kw):
- possible_contexts = martian.scan_for_classes(module, [grok.Model,
- grok.Container])
- context = determine_module_context(module_info, possible_contexts)
+ context = determine_module_component(module_info, 'grok.context',
+ [grok.Model, grok.Container])
module.__grok_context__ = context
return True
+class ViewletManagerContextGrokker(martian.GlobalGrokker):
+
+ priority = 1001
+
+ def grok(self, name, module, module_info, config, **kw):
+ viewletmanager = determine_module_component(module_info,
+ 'grok.viewletmanager',
+ [grok.ViewletManager])
+ module.__grok_viewletmanager__ = viewletmanager
+ return True
+
class AdapterGrokker(martian.ClassGrokker):
component_class = grok.Adapter
@@ -454,7 +468,8 @@
if interfaces is None:
# There's no explicit interfaces defined, so we assume the
# module context to be the thing adapted.
- check_context(module_info.getModule(), context)
+ check_module_component(module_info.getModule(), context,
+ 'context', 'grok.context')
interfaces = (context, )
config.action(
@@ -887,15 +902,15 @@
view = determine_class_directive('grok.view', factory,
module_info, default=IBrowserView)
- view_layer = determine_class_directive('grok.layer', factory,
- module_info,
- default=IDefaultBrowserLayer)
+ viewlet_layer = determine_class_directive('grok.layer', factory,
+ module_info,
+ default=IDefaultBrowserLayer)
config.action(
- discriminator = ('viewletManager', view_context, view_layer,
+ discriminator = ('viewletManager', view_context, viewlet_layer,
view, name),
callable = component.provideAdapter,
- args = (factory, (view_context, view_layer, view),
+ args = (factory, (view_context, viewlet_layer, view),
IViewletManager, name)
)
@@ -906,7 +921,7 @@
def grok(self, name, factory, module_info, config, **kw):
viewlet_name = get_name_classname(factory)
- view_context = get_context(module_info, factory)
+ viewlet_context = get_context(module_info, factory)
factory.module_info = module_info # to make /static available
@@ -920,20 +935,16 @@
view = determine_class_directive('grok.view', factory,
module_info, default=IBrowserView)
- view_layer = determine_class_directive('grok.layer', factory,
- module_info,
- default=IDefaultBrowserLayer)
- viewletmanager = determine_class_directive('grok.viewletmanager',
- factory, module_info,
- None)
- if viewletmanager is None:
- raise GrokError("XXX This is a temporary grok error")
+ viewlet_layer = determine_class_directive('grok.layer', factory,
+ module_info,
+ default=IDefaultBrowserLayer)
+ viewletmanager = get_viewletmanager(module_info, factory)
config.action(
- discriminator = ('viewlet', view_context, view_layer,
+ discriminator = ('viewlet', viewlet_context, viewlet_layer,
view, viewletmanager, viewlet_name),
callable = component.provideAdapter,
- args = (factory, (view_context, view_layer, view,
+ args = (factory, (viewlet_context, viewlet_layer, view,
viewletmanager), IViewlet, viewlet_name)
)
Added: grok/branches/snowsprint-viewlets2/src/grok/tests/viewlet/viewlet_ambiguous_manager.py
===================================================================
--- grok/branches/snowsprint-viewlets2/src/grok/tests/viewlet/viewlet_ambiguous_manager.py (rev 0)
+++ grok/branches/snowsprint-viewlets2/src/grok/tests/viewlet/viewlet_ambiguous_manager.py 2008-01-24 17:54:28 UTC (rev 83184)
@@ -0,0 +1,29 @@
+"""
+When there are two or more viewletmanagers available in the module,
+a viewlet will not auto-associate but instead raise an error.
+
+ >>> grok.testing.grok(__name__)
+ Traceback (most recent call last):
+ ...
+ GrokError: Multiple possible viewletmanagers for <class 'grok.tests.viewlet.viewlet_ambiguous_manager.Viewlet'>, please use grok.viewletmanager.
+
+"""
+
+import grok
+from zope.interface import Interface
+
+class ViewletManager(grok.ViewletManager):
+ grok.name('foo')
+ grok.context(Interface)
+
+class ViewletManager2(grok.ViewletManager):
+ grok.name('bar')
+ grok.context(Interface)
+
+class Viewlet(grok.Viewlet):
+ grok.context(Interface)
+
+ def render(self):
+ return "Render method"
+
+
Modified: grok/branches/snowsprint-viewlets2/src/grok/tests/viewlet/viewlet_render_and_template.py
===================================================================
--- grok/branches/snowsprint-viewlets2/src/grok/tests/viewlet/viewlet_render_and_template.py 2008-01-24 17:48:16 UTC (rev 83183)
+++ grok/branches/snowsprint-viewlets2/src/grok/tests/viewlet/viewlet_render_and_template.py 2008-01-24 17:54:28 UTC (rev 83184)
@@ -1,5 +1,5 @@
"""
-We viewlet is not allowed to define its own render method and have a template
+A viewlet is not allowed to define its own render method and have a template
associated with it at the same time.
>>> grok.testing.grok(__name__)
Modified: grok/branches/snowsprint-viewlets2/src/grok/util.py
===================================================================
--- grok/branches/snowsprint-viewlets2/src/grok/util.py 2008-01-24 17:48:16 UTC (rev 83183)
+++ grok/branches/snowsprint-viewlets2/src/grok/util.py 2008-01-24 17:54:28 UTC (rev 83184)
@@ -25,7 +25,7 @@
from zope.security.interfaces import IPermission
from martian.error import GrokError, GrokImportError
-from martian.util import class_annotation, methods_from_class
+from martian.util import class_annotation, methods_from_class, scan_for_classes
def check_adapts(class_):
if component.adaptedBy(class_) is None:
@@ -125,32 +125,66 @@
# if components have a grok.order directive, sort by that
return sorted(components, key=_sort_key)
-AMBIGUOUS_CONTEXT = object()
-def check_context(component, context):
- if context is None:
- raise GrokError("No module-level context for %r, please use "
- "grok.context." % component, component)
- elif context is AMBIGUOUS_CONTEXT:
- raise GrokError("Multiple possible contexts for %r, please use "
- "grok.context." % component, component)
+AMBIGUOUS_COMPONENT = object()
+def check_module_component(factory, component,
+ component_name, component_directive):
+ """Raise error if module-level component cannot be determined.
-def determine_module_context(module_info, models):
- if len(models) == 0:
- context = None
- elif len(models) == 1:
- context = models[0]
- else:
- context = AMBIGUOUS_CONTEXT
+ If the module-level component is None, it's never been specified;
+ raise error telling developer to specify.
- module_context = module_info.getAnnotation('grok.context', None)
- if module_context:
- context = module_context
+ if the module-level component is AMBIGUOUS_COMPONENT, raise
+ an error telling developer to specify which one to use.
+ """
+ if component is None:
+ raise GrokError("No module-level %s for %r, please use "
+ "%s." % (component_name, factory, component_directive),
+ factory)
+ elif component is AMBIGUOUS_COMPONENT:
+ raise GrokError("Multiple possible %ss for %r, please use "
+ "%s." % (component_name, factory, component_directive),
+ factory)
+
+def determine_module_component(module_info, annotation, classes):
+ """Determine module-level component.
- return context
+ The module-level component can be set explicitly using the
+ annotation (such as grok.context).
+ If there is no annotation, the module-level component is determined
+ by scanning for subclasses of any in the list of classes.
-def determine_class_context(class_, module_context):
- context = class_annotation(class_, 'grok.context', module_context)
- check_context(class_, context)
- return context
+ If there is no module-level component, the module-level component is
+ None.
+ If there is one module-level component, it is returned.
+
+ If there are more than one module-level component, AMBIGUOUS_COMPONENT
+ is returned.
+ """
+ components = scan_for_classes(module_info.getModule(), classes)
+ if len(components) == 0:
+ component = None
+ elif len(components) == 1:
+ component = components[0]
+ else:
+ component= AMBIGUOUS_COMPONENT
+
+ module_component = module_info.getAnnotation(annotation, None)
+ if module_component:
+ component = module_component
+ return component
+
+
+def determine_class_component(module_info, class_,
+ component_name, component_directive):
+ """Determine component for a class.
+
+ Determine a component for a class. If no class-specific component exists,
+ try falling back on module-level component.
+ """
+ module_component = module_info.getAnnotation(component_directive, None)
+ component = class_annotation(class_, component_directive, module_component)
+ check_module_component(class_, component,
+ component_name, component_directive)
+ return component
More information about the Checkins
mailing list