[Checkins] SVN: grok/branches/grokcore.xxx/ factor out a
ViewGrokkerBase to grokcore.view;
move also dependencies like template directive or GrokForm component
Godefroid Chapelle
gotcha at bubblenet.be
Thu Jul 17 11:36:52 EDT 2008
Log message for revision 88450:
factor out a ViewGrokkerBase to grokcore.view; move also dependencies like template directive or GrokForm component
Changed:
U grok/branches/grokcore.xxx/devel/grokcore.view/src/grokcore/view/__init__.py
U grok/branches/grokcore.xxx/devel/grokcore.view/src/grokcore/view/components.py
U grok/branches/grokcore.xxx/devel/grokcore.view/src/grokcore/view/directive.py
A grok/branches/grokcore.xxx/devel/grokcore.view/src/grokcore/view/formlib.py
U grok/branches/grokcore.xxx/devel/grokcore.view/src/grokcore/view/util.py
U grok/branches/grokcore.xxx/src/grok/__init__.py
U grok/branches/grokcore.xxx/src/grok/components.py
U grok/branches/grokcore.xxx/src/grok/directive.py
D grok/branches/grokcore.xxx/src/grok/formlib.py
U grok/branches/grokcore.xxx/src/grok/meta.py
-=-
Modified: grok/branches/grokcore.xxx/devel/grokcore.view/src/grokcore/view/__init__.py
===================================================================
--- grok/branches/grokcore.xxx/devel/grokcore.view/src/grokcore/view/__init__.py 2008-07-17 15:17:56 UTC (rev 88449)
+++ grok/branches/grokcore.xxx/devel/grokcore.view/src/grokcore/view/__init__.py 2008-07-17 15:36:52 UTC (rev 88450)
@@ -1,3 +1,3 @@
-from directive import layer, view, viewletmanager
+from directive import layer, view, require, template, templatedir
from util import url
-from components import ViewMixin
+from components import ViewMixin, Permission, GrokForm
Modified: grok/branches/grokcore.xxx/devel/grokcore.view/src/grokcore/view/components.py
===================================================================
--- grok/branches/grokcore.xxx/devel/grokcore.view/src/grokcore/view/components.py 2008-07-17 15:17:56 UTC (rev 88449)
+++ grok/branches/grokcore.xxx/devel/grokcore.view/src/grokcore/view/components.py 2008-07-17 15:36:52 UTC (rev 88450)
@@ -2,10 +2,15 @@
from zope import interface
from zope.publisher.publish import mapply
+from zope.security.permission import Permission
from grokcore.view import util
+class Permission(Permission):
+ pass
+
+
class ViewMixin(object):
def _initialize(self):
@@ -75,3 +80,56 @@
def application_url(self, name=None):
raise NotImplementedError
+
+
+class GrokForm(object):
+ """Mix-in to consolidate zope.formlib's forms with grok.View and to
+ add some more useful methods.
+
+ The consolidation needs to happen because zope.formlib's Forms have
+ update/render methods which have different meanings than
+ grok.View's update/render methods. We deal with this issue by
+ 'renaming' zope.formlib's update() to update_form() and by
+ disallowing subclasses to have custom render() methods."""
+
+ def update(self):
+ """Subclasses can override this method just like on regular
+ grok.Views. It will be called before any form processing
+ happens."""
+
+ def update_form(self):
+ """Update the form, i.e. process form input using widgets.
+
+ On zope.formlib forms, this is what the update() method is.
+ In grok views, the update() method has a different meaning.
+ That's why this method is called update_form() in grok forms."""
+ super(GrokForm, self).update()
+
+ def render(self):
+ """Render the form, either using the form template or whatever
+ the actions returned in form_result."""
+ # if the form has been updated, it will already have a result
+ if self.form_result is None:
+ if self.form_reset:
+ # we reset, in case data has changed in a way that
+ # causes the widgets to have different data
+ self.resetForm()
+ self.form_reset = False
+ self.form_result = self._render_template()
+
+ return self.form_result
+
+ # Mark the render() method as a method from the base class. That
+ # way we can detect whether somebody overrides render() in a
+ # subclass (which we don't allow).
+ render.base_method = True
+
+ 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
+
+ self.update_form()
+ return self.render()
Modified: grok/branches/grokcore.xxx/devel/grokcore.view/src/grokcore/view/directive.py
===================================================================
--- grok/branches/grokcore.xxx/devel/grokcore.view/src/grokcore/view/directive.py 2008-07-17 15:17:56 UTC (rev 88449)
+++ grok/branches/grokcore.xxx/devel/grokcore.view/src/grokcore/view/directive.py 2008-07-17 15:36:52 UTC (rev 88450)
@@ -1,8 +1,29 @@
+import sys
import martian
-from grokcore.component.scan import UnambiguousComponentScope
+from martian import util
+from martian.directive import StoreMultipleTimes
+from martian.error import GrokError
+from martian.error import GrokImportError
+
from zope.publisher.interfaces.browser import IBrowserView
+from grokcore.view.components import Permission
+import grokcore.component
+
+
+class template(martian.Directive):
+ scope = martian.CLASS
+ store = martian.ONCE
+ validate = martian.validateText
+
+
+class templatedir(martian.Directive):
+ scope = martian.MODULE
+ store = martian.ONCE
+ validate = martian.validateText
+
+
class OneInterfaceOrClassOnClassOrModule(martian.Directive):
"""Convenience base class. Not for public use."""
scope = martian.CLASS_OR_MODULE
@@ -14,9 +35,49 @@
pass
-class viewletmanager(OneInterfaceOrClassOnClassOrModule):
- scope = UnambiguousComponentScope('viewletmanager')
+class view(OneInterfaceOrClassOnClassOrModule):
+ default = IBrowserView
-class view(OneInterfaceOrClassOnClassOrModule):
- default = IBrowserView
+class RequireDirectiveStore(StoreMultipleTimes):
+
+ def get(self, directive, component, default):
+ permissions = getattr(component, directive.dotted_name(), default)
+ if (permissions is default) or not permissions:
+ return default
+ if len(permissions) > 1:
+ raise GrokError('grok.require was called multiple times in '
+ '%r. It may only be set once for a class.'
+ % component, component)
+ return permissions[0]
+
+ def pop(self, locals_, directive):
+ return locals_[directive.dotted_name()].pop()
+
+
+class require(martian.Directive):
+ scope = martian.CLASS
+ store = RequireDirectiveStore()
+
+ def validate(self, value):
+ if util.check_subclass(value, Permission):
+ return
+ if util.not_unicode_or_ascii(value):
+ raise GrokImportError(
+ "You can only pass unicode, ASCII, or a subclass "
+ "of grok.Permission to the '%s' directive." % self.name)
+
+ def factory(self, value):
+ if util.check_subclass(value, Permission):
+ return grokcore.component.name.bind().get(value)
+ return value
+
+ def __call__(self, func):
+ # grok.require can be used both as a class-level directive and
+ # as a decorator for methods. Therefore we return a decorator
+ # here, which may be used for methods, or simply ignored when
+ # used as a directive.
+ frame = sys._getframe(1)
+ permission = self.store.pop(frame.f_locals, self)
+ self.set(func, [permission])
+ return func
Copied: grok/branches/grokcore.xxx/devel/grokcore.view/src/grokcore/view/formlib.py (from rev 88446, grok/branches/grokcore.xxx/src/grok/formlib.py)
===================================================================
--- grok/branches/grokcore.xxx/devel/grokcore.view/src/grokcore/view/formlib.py (rev 0)
+++ grok/branches/grokcore.xxx/devel/grokcore.view/src/grokcore/view/formlib.py 2008-07-17 15:36:52 UTC (rev 88450)
@@ -0,0 +1,124 @@
+import types
+from zope import interface, event, lifecycleevent
+from zope.interface.interfaces import IInterface
+from zope.formlib import form
+from zope.schema.interfaces import IField
+
+class action(form.action):
+ """We override the action decorator we pass in our custom Action.
+ """
+ def __call__(self, success):
+ action = Action(self.label, success=success, **self.options)
+ self.actions.append(action)
+ return action
+
+class Action(form.Action):
+ def success(self, data):
+ if self.success_handler is not None:
+ return self.success_handler(self.form, **data)
+
+def Fields(*args, **kw):
+ fields = []
+ for key, value in kw.items():
+ if IField.providedBy(value):
+ value.__name__ = key
+ fields.append(value)
+ del kw[key]
+ fields.sort(key=lambda field: field.order)
+ return form.Fields(*(args + tuple(fields)), **kw)
+
+def get_auto_fields(context):
+ """Get the form fields for context.
+ """
+ # for an interface context, we generate them from that interface
+ if IInterface.providedBy(context):
+ return form.Fields(context)
+ # if we have a non-interface context, we're autogenerating them
+ # from any schemas defined by the context
+ fields = form.Fields(*most_specialized_interfaces(context))
+ # we pull in this field by default, but we don't want it in our form
+ fields = fields.omit('__name__')
+ return fields
+
+AutoFields = get_auto_fields
+
+def most_specialized_interfaces(context):
+ """Get interfaces for an object without any duplicates.
+
+ Interfaces in a declaration for an object may already have been seen
+ because it is also inherited by another interface. Don't return the
+ interface twice, as that would result in duplicate names when creating
+ the form.
+ """
+ declaration = interface.implementedBy(context)
+ seen = []
+ for iface in declaration.flattened():
+ if interface_seen(seen, iface):
+ continue
+ seen.append(iface)
+ return seen
+
+def interface_seen(seen, iface):
+ """Return True if interface already is seen.
+ """
+ for seen_iface in seen:
+ if seen_iface.extends(iface):
+ return True
+ return False
+
+def apply_data(context, form_fields, data, adapters=None, update=False):
+ """Save form data (``data`` dict) on a ``context`` object.
+
+ This is a beefed up version of zope.formlib.form.applyChanges().
+ It allows you to specify whether values should be compared with
+ the attributes on already existing objects or not, using the
+ ``update`` parameter.
+
+ Unlike zope.formlib.form.applyChanges(), it will return a
+ dictionary of interfaces and their fields that were changed. This
+ is necessary to appropriately send IObjectModifiedEvents.
+ """
+ if adapters is None:
+ adapters = {}
+
+ changes = {}
+
+ for form_field in form_fields:
+ field = form_field.field
+ # Adapt context, if necessary
+ interface = form_field.interface
+ adapter = adapters.get(interface)
+ if adapter is None:
+ if interface is None:
+ adapter = context
+ else:
+ adapter = interface(context)
+ adapters[interface] = adapter
+
+ name = form_field.__name__
+ newvalue = data.get(name, form_field) # using form_field as marker
+
+ if update:
+ if ((newvalue is not form_field) and
+ (field.get(adapter) != newvalue)):
+ field.set(adapter, newvalue)
+ changes.setdefault(interface, []).append(name)
+ else:
+ if newvalue is not form_field:
+ field.set(adapter, newvalue)
+ changes.setdefault(interface, []).append(name)
+
+ return changes
+
+def apply_data_event(context, form_fields, data, adapters=None, update=False):
+ """Like apply_data, but also sends an IObjectModifiedEvent.
+ """
+ changes = apply_data(context, form_fields, data, adapters, update)
+
+ if changes:
+ descriptions = []
+ for interface, names in changes.items():
+ descriptions.append(lifecycleevent.Attributes(interface, *names))
+ event.notify(lifecycleevent.ObjectModifiedEvent(context, *descriptions))
+
+ return changes
Property changes on: grok/branches/grokcore.xxx/devel/grokcore.view/src/grokcore/view/formlib.py
___________________________________________________________________
Name: svn:mergeinfo
+
Modified: grok/branches/grokcore.xxx/devel/grokcore.view/src/grokcore/view/util.py
===================================================================
--- grok/branches/grokcore.xxx/devel/grokcore.view/src/grokcore/view/util.py 2008-07-17 15:17:56 UTC (rev 88449)
+++ grok/branches/grokcore.xxx/devel/grokcore.view/src/grokcore/view/util.py 2008-07-17 15:36:52 UTC (rev 88450)
@@ -18,3 +18,7 @@
or item for item in v]
url += '?' + urllib.urlencode(data, doseq=True)
return url
+
+
+def default_view_name(factory, module=None, **data):
+ return factory.__name__.lower()
Modified: grok/branches/grokcore.xxx/src/grok/__init__.py
===================================================================
--- grok/branches/grokcore.xxx/src/grok/__init__.py 2008-07-17 15:17:56 UTC (rev 88449)
+++ grok/branches/grokcore.xxx/src/grok/__init__.py 2008-07-17 15:36:52 UTC (rev 88450)
@@ -38,7 +38,7 @@
from grok.components import Site, LocalUtility, Annotation
from grok.components import Application, Form, AddForm, EditForm, DisplayForm
from grok.components import Indexes
-from grok.components import Permission, Role, Public
+from grok.components import Role, Public
from grok.components import Skin, IGrokLayer
from grok.components import RESTProtocol, IRESTLayer
from grok.interfaces import IRESTSkinType
@@ -48,17 +48,19 @@
from grokcore.component.directive import (
context, name, title, description, provides, global_utility, direct)
from grok.directive import (
- template, templatedir, local_utility, permissions, require, site,
- traversable, order)
-from grokcore.view import layer, viewletmanager, view
+ local_utility, permissions, site,
+ traversable, order, viewletmanager)
from grokcore.component.decorators import subscribe, adapter, implementer
from martian.error import GrokError, GrokImportError
+from grokcore.view import layer, view, require, template, templatedir
+from grokcore.view import Permission
+
# BBB These two functions are meant for test fixtures and should be
# imported from grok.testing, not from grok.
from grok.testing import grok, grok_component
-from grok.formlib import action, AutoFields, Fields
+from grokcore.view.formlib import action, AutoFields, Fields
from grokcore.view import url
# Our __init__ provides the grok API directly so using 'import grok' is enough.
Modified: grok/branches/grokcore.xxx/src/grok/components.py
===================================================================
--- grok/branches/grokcore.xxx/src/grok/components.py 2008-07-17 15:17:56 UTC (rev 88449)
+++ grok/branches/grokcore.xxx/src/grok/components.py 2008-07-17 15:36:52 UTC (rev 88450)
@@ -25,7 +25,6 @@
from zope import component
from zope import interface
from zope.interface.common import idatetime
-from zope.security.permission import Permission
from zope.securitypolicy.role import Role
from zope.publisher.browser import BrowserPage
from zope.publisher.interfaces import NotFound
@@ -58,7 +57,9 @@
import z3c.flashmessage.interfaces
import martian.util
-from grok import interfaces, formlib, util
+from grok import interfaces, util
+from grokcore.view import formlib
+from grokcore.view import GrokForm
class Model(Contained, persistent.Persistent):
@@ -442,60 +443,6 @@
'templates', 'default_display_form.pt'))
default_display_template.__grok_name__ = 'default_display_form'
-
-class GrokForm(object):
- """Mix-in to consolidate zope.formlib's forms with grok.View and to
- add some more useful methods.
-
- The consolidation needs to happen because zope.formlib's Forms have
- update/render methods which have different meanings than
- grok.View's update/render methods. We deal with this issue by
- 'renaming' zope.formlib's update() to update_form() and by
- disallowing subclasses to have custom render() methods."""
-
- def update(self):
- """Subclasses can override this method just like on regular
- grok.Views. It will be called before any form processing
- happens."""
-
- def update_form(self):
- """Update the form, i.e. process form input using widgets.
-
- On zope.formlib forms, this is what the update() method is.
- In grok views, the update() method has a different meaning.
- That's why this method is called update_form() in grok forms."""
- super(GrokForm, self).update()
-
- def render(self):
- """Render the form, either using the form template or whatever
- the actions returned in form_result."""
- # if the form has been updated, it will already have a result
- if self.form_result is None:
- if self.form_reset:
- # we reset, in case data has changed in a way that
- # causes the widgets to have different data
- self.resetForm()
- self.form_reset = False
- self.form_result = self._render_template()
-
- return self.form_result
-
- # Mark the render() method as a method from the base class. That
- # way we can detect whether somebody overrides render() in a
- # subclass (which we don't allow).
- render.base_method = True
-
- 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
-
- self.update_form()
- return self.render()
-
-
class Form(GrokForm, form.FormBase, View):
# We're only reusing the form implementation from zope.formlib, we
# explicitly don't want to inherit the interface semantics (mostly
@@ -587,9 +534,6 @@
Indexes = IndexesClass('Indexes')
-class Permission(Permission):
- pass
-
Public = 'zope.Public'
class Role(Role):
Modified: grok/branches/grokcore.xxx/src/grok/directive.py
===================================================================
--- grok/branches/grokcore.xxx/src/grok/directive.py 2008-07-17 15:17:56 UTC (rev 88449)
+++ grok/branches/grokcore.xxx/src/grok/directive.py 2008-07-17 15:36:52 UTC (rev 88450)
@@ -25,17 +25,13 @@
from martian.directive import StoreMultipleTimes
from grok import components
+from grokcore.component.scan import UnambiguousComponentScope
+from grokcore.view.directive import OneInterfaceOrClassOnClassOrModule
+
# Define grok directives
-class template(martian.Directive):
- scope = martian.CLASS
- store = martian.ONCE
- validate = martian.validateText
+class viewletmanager(OneInterfaceOrClassOnClassOrModule):
+ scope = UnambiguousComponentScope('viewletmanager')
-class templatedir(martian.Directive):
- scope = martian.MODULE
- store = martian.ONCE
- validate = martian.validateText
-
class local_utility(martian.Directive):
scope = martian.CLASS
store = martian.DICT
@@ -104,48 +100,6 @@
return cmp(self.order, other.order)
-class RequireDirectiveStore(StoreMultipleTimes):
-
- def get(self, directive, component, default):
- permissions = getattr(component, directive.dotted_name(), default)
- if (permissions is default) or not permissions:
- return default
- if len(permissions) > 1:
- raise GrokError('grok.require was called multiple times in '
- '%r. It may only be set once for a class.'
- % component, component)
- return permissions[0]
-
- def pop(self, locals_, directive):
- return locals_[directive.dotted_name()].pop()
-
-class require(martian.Directive):
- scope = martian.CLASS
- store = RequireDirectiveStore()
-
- def validate(self, value):
- if util.check_subclass(value, components.Permission):
- return
- if util.not_unicode_or_ascii(value):
- raise GrokImportError(
- "You can only pass unicode, ASCII, or a subclass "
- "of grok.Permission to the '%s' directive." % self.name)
-
- def factory(self, value):
- if util.check_subclass(value, components.Permission):
- return grok.name.bind().get(value)
- return value
-
- def __call__(self, func):
- # grok.require can be used both as a class-level directive and
- # as a decorator for methods. Therefore we return a decorator
- # here, which may be used for methods, or simply ignored when
- # used as a directive.
- frame = sys._getframe(1)
- permission = self.store.pop(frame.f_locals, self)
- self.set(func, [permission])
- return func
-
class site(martian.Directive):
scope = martian.CLASS
store = martian.ONCE
Deleted: grok/branches/grokcore.xxx/src/grok/formlib.py
===================================================================
--- grok/branches/grokcore.xxx/src/grok/formlib.py 2008-07-17 15:17:56 UTC (rev 88449)
+++ grok/branches/grokcore.xxx/src/grok/formlib.py 2008-07-17 15:36:52 UTC (rev 88450)
@@ -1,124 +0,0 @@
-import types
-from zope import interface, event, lifecycleevent
-from zope.interface.interfaces import IInterface
-from zope.formlib import form
-from zope.schema.interfaces import IField
-
-class action(form.action):
- """We override the action decorator we pass in our custom Action.
- """
- def __call__(self, success):
- action = Action(self.label, success=success, **self.options)
- self.actions.append(action)
- return action
-
-class Action(form.Action):
- def success(self, data):
- if self.success_handler is not None:
- return self.success_handler(self.form, **data)
-
-def Fields(*args, **kw):
- fields = []
- for key, value in kw.items():
- if IField.providedBy(value):
- value.__name__ = key
- fields.append(value)
- del kw[key]
- fields.sort(key=lambda field: field.order)
- return form.Fields(*(args + tuple(fields)), **kw)
-
-def get_auto_fields(context):
- """Get the form fields for context.
- """
- # for an interface context, we generate them from that interface
- if IInterface.providedBy(context):
- return form.Fields(context)
- # if we have a non-interface context, we're autogenerating them
- # from any schemas defined by the context
- fields = form.Fields(*most_specialized_interfaces(context))
- # we pull in this field by default, but we don't want it in our form
- fields = fields.omit('__name__')
- return fields
-
-AutoFields = get_auto_fields
-
-def most_specialized_interfaces(context):
- """Get interfaces for an object without any duplicates.
-
- Interfaces in a declaration for an object may already have been seen
- because it is also inherited by another interface. Don't return the
- interface twice, as that would result in duplicate names when creating
- the form.
- """
- declaration = interface.implementedBy(context)
- seen = []
- for iface in declaration.flattened():
- if interface_seen(seen, iface):
- continue
- seen.append(iface)
- return seen
-
-def interface_seen(seen, iface):
- """Return True if interface already is seen.
- """
- for seen_iface in seen:
- if seen_iface.extends(iface):
- return True
- return False
-
-def apply_data(context, form_fields, data, adapters=None, update=False):
- """Save form data (``data`` dict) on a ``context`` object.
-
- This is a beefed up version of zope.formlib.form.applyChanges().
- It allows you to specify whether values should be compared with
- the attributes on already existing objects or not, using the
- ``update`` parameter.
-
- Unlike zope.formlib.form.applyChanges(), it will return a
- dictionary of interfaces and their fields that were changed. This
- is necessary to appropriately send IObjectModifiedEvents.
- """
- if adapters is None:
- adapters = {}
-
- changes = {}
-
- for form_field in form_fields:
- field = form_field.field
- # Adapt context, if necessary
- interface = form_field.interface
- adapter = adapters.get(interface)
- if adapter is None:
- if interface is None:
- adapter = context
- else:
- adapter = interface(context)
- adapters[interface] = adapter
-
- name = form_field.__name__
- newvalue = data.get(name, form_field) # using form_field as marker
-
- if update:
- if ((newvalue is not form_field) and
- (field.get(adapter) != newvalue)):
- field.set(adapter, newvalue)
- changes.setdefault(interface, []).append(name)
- else:
- if newvalue is not form_field:
- field.set(adapter, newvalue)
- changes.setdefault(interface, []).append(name)
-
- return changes
-
-def apply_data_event(context, form_fields, data, adapters=None, update=False):
- """Like apply_data, but also sends an IObjectModifiedEvent.
- """
- changes = apply_data(context, form_fields, data, adapters, update)
-
- if changes:
- descriptions = []
- for interface, names in changes.items():
- descriptions.append(lifecycleevent.Attributes(interface, *names))
- event.notify(lifecycleevent.ObjectModifiedEvent(context, *descriptions))
-
- return changes
Modified: grok/branches/grokcore.xxx/src/grok/meta.py
===================================================================
--- grok/branches/grokcore.xxx/src/grok/meta.py 2008-07-17 15:17:56 UTC (rev 88449)
+++ grok/branches/grokcore.xxx/src/grok/meta.py 2008-07-17 15:36:52 UTC (rev 88450)
@@ -49,9 +49,11 @@
import grokcore.view
import grokcore.view.templatereg
+from grokcore.view.meta import ViewGrokkerBase
+from grokcore.view.util import default_view_name
import grok
-from grok import components, formlib
+from grok import components
from grok.util import make_checker
from grok.interfaces import IRESTSkinType
from grok.interfaces import IViewletManager as IGrokViewletManager
@@ -59,9 +61,6 @@
from grokcore.component.scan import determine_module_component
-def default_view_name(factory, module=None, **data):
- return factory.__name__.lower()
-
def default_fallback_to_name(factory, module, name, **data):
return name
@@ -145,79 +144,17 @@
return True
-class ViewGrokker(martian.ClassGrokker):
+class ViewGrokker(ViewGrokkerBase):
martian.component(grokcore.view.ViewMixin)
- martian.directive(grok.context)
- martian.directive(grok.layer, default=IDefaultBrowserLayer)
- martian.directive(grok.name, get_default=default_view_name)
- martian.directive(grok.require, name='permission')
- 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(ViewGrokker, self).grok(name, factory, module_info, **kw)
-
- def execute(self, factory, config, context, layer, name, permission, **kw):
- if util.check_subclass(factory, components.GrokForm):
- # setup form_fields from context class if we've encountered a form
- if getattr(factory, 'form_fields', None) is None:
- factory.form_fields = formlib.get_auto_fields(context)
-
- if not getattr(factory.render, 'base_method', False):
- raise GrokError(
- "It is not allowed to specify a custom 'render' "
- "method for form %r. Forms either use the default "
- "template or a custom-supplied one." % factory,
- factory)
-
- # find templates
- templates = factory.module_info.getAnnotation('grok.templates', None)
- 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.
- methods = util.methods_from_class(factory)
- for method in methods:
- if grok.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)
-
+ def protectName(self, config, factory, permission):
config.action(
- discriminator=('adapter', adapts, interface.Interface, name),
- callable=component.provideAdapter,
- args=(factory, adapts, interface.Interface, name),
- )
-
- config.action(
discriminator=('protectName', factory, '__call__'),
callable=make_checker,
args=(factory, factory, permission),
)
- return True
- def checkTemplates(self, templates, module_info, factory):
- def has_render(factory):
- return (getattr(factory, 'render', None) and
- not util.check_subclass(factory, grok.components.GrokForm))
- def has_no_render(factory):
- return not getattr(factory, 'render', None)
- templates.checkTemplates(module_info, factory, 'view',
- has_render, has_no_render)
-
-
class JSONGrokker(martian.MethodGrokker):
martian.component(grok.JSON)
martian.directive(grok.context)
More information about the Checkins
mailing list