[Checkins] SVN: grok/trunk/ Merge sylvain-grokcore-formlib: use grokcore.formlib in the grok trunk.

Martijn Faassen faassen at infrae.com
Mon Sep 29 09:21:23 EDT 2008


Log message for revision 91589:
  Merge sylvain-grokcore-formlib: use grokcore.formlib in the grok trunk.
  
  Thanks Sylvain and Philipp for doing the actual work.
  

Changed:
  U   grok/trunk/CHANGES.txt
  U   grok/trunk/grokwiki/src/grokwiki/page.py
  U   grok/trunk/grokwiki/src/grokwiki/page_templates/edit.pt
  U   grok/trunk/grokwiki/src/grokwiki/wiki.py
  U   grok/trunk/setup.py
  U   grok/trunk/src/grok/__init__.py
  U   grok/trunk/src/grok/components.py
  D   grok/trunk/src/grok/formlib.py
  D   grok/trunk/src/grok/ftests/form/actions.py
  D   grok/trunk/src/grok/ftests/form/addform.py
  D   grok/trunk/src/grok/ftests/form/addform_applydata.py
  D   grok/trunk/src/grok/ftests/form/editform_applydata.py
  D   grok/trunk/src/grok/ftests/form/editform_applydata_schema.py
  D   grok/trunk/src/grok/ftests/form/editform_applydata_schemafields.py
  U   grok/trunk/src/grok/ftests/form/form.py
  D   grok/trunk/src/grok/ftests/form/templateform.py
  D   grok/trunk/src/grok/ftests/form/update.py
  U   grok/trunk/src/grok/interfaces.py
  U   grok/trunk/src/grok/meta.py
  U   grok/trunk/src/grok/meta.zcml
  D   grok/trunk/src/grok/templates/
  U   grok/trunk/src/grok/testing.py
  D   grok/trunk/src/grok/tests/form/
  U   grok/trunk/src/grok/tests/test_grok.py
  U   grok/trunk/versions.cfg

-=-
Modified: grok/trunk/CHANGES.txt
===================================================================
--- grok/trunk/CHANGES.txt	2008-09-29 12:39:34 UTC (rev 91588)
+++ grok/trunk/CHANGES.txt	2008-09-29 13:21:22 UTC (rev 91589)
@@ -30,6 +30,9 @@
 * View-related base classes, directives and grokkers have been moved
   out to a ``grokcore.view`` package.
 
+* Form-related base classes and helpers have been moved out to a
+  ``grokcore.formlib`` package.
+
 Bug fixes
 ---------
 

Modified: grok/trunk/grokwiki/src/grokwiki/page.py
===================================================================
--- grok/trunk/grokwiki/src/grokwiki/page.py	2008-09-29 12:39:34 UTC (rev 91588)
+++ grok/trunk/grokwiki/src/grokwiki/page.py	2008-09-29 13:21:22 UTC (rev 91589)
@@ -57,3 +57,18 @@
         self.context.update(text)
         self.flash('Saved.')
         self.redirect(self.url(self.context))
+
+
+class WikiLayer(grok.IRESTLayer):
+    pass
+
+class PageRest(grok.REST):
+    grok.layer(WikiLayer))
+    
+    def GET(self):
+        return "Hello world"
+    
+class WikiProtocol(grok.RESTProtocol):
+    grok.layer(WikiLayer)
+    grok.name('wiki')
+

Modified: grok/trunk/grokwiki/src/grokwiki/page_templates/edit.pt
===================================================================
--- grok/trunk/grokwiki/src/grokwiki/page_templates/edit.pt	2008-09-29 12:39:34 UTC (rev 91588)
+++ grok/trunk/grokwiki/src/grokwiki/page_templates/edit.pt	2008-09-29 13:21:22 UTC (rev 91589)
@@ -3,7 +3,7 @@
         <h1>Edit &raquo;<span tal:replace="context/__name__">WikiPage</span>&laquo;</h1>
 
         <form tal:attributes="action view/url" method="POST">
-        <textarea name="wikidata" tal:content="context/text" cols="80" rows="20"/><br/>
+        <textarea name="wikidata" tal:content="python:context.text" cols="80" rows="20"/><br/>
         <input type="submit" value="Update"/>
         </form>
     </div>

Modified: grok/trunk/grokwiki/src/grokwiki/wiki.py
===================================================================
--- grok/trunk/grokwiki/src/grokwiki/wiki.py	2008-09-29 12:39:34 UTC (rev 91588)
+++ grok/trunk/grokwiki/src/grokwiki/wiki.py	2008-09-29 13:21:22 UTC (rev 91589)
@@ -24,6 +24,20 @@
     def render(self):
         self.redirect(self.url('home'))
 
+class Hello(grok.View):
+    grok.baseclass()
+    
+    def render(self):
+        return "Hello"
+
+class Hoi(Hello):
+    def render(self):
+        return "Hoi"
+
+class Bonjour(Hello):
+    def render(self):
+        return "Bonjour"
+
 @grok.subscribe(Wiki, grok.IObjectAddedEvent)
 def setupHomepage(wiki, event):
     """Creates a home page for every wiki."""

Modified: grok/trunk/setup.py
===================================================================
--- grok/trunk/setup.py	2008-09-29 12:39:34 UTC (rev 91588)
+++ grok/trunk/setup.py	2008-09-29 13:21:22 UTC (rev 91589)
@@ -37,6 +37,7 @@
     install_requires=['setuptools',
                       'martian >= 0.10',
                       'grokcore.component >= 1.5',
+                      'grokcore.formlib',
                       'grokcore.security',
                       'grokcore.view',
                       'simplejson',

Modified: grok/trunk/src/grok/__init__.py
===================================================================
--- grok/trunk/src/grok/__init__.py	2008-09-29 12:39:34 UTC (rev 91588)
+++ grok/trunk/src/grok/__init__.py	2008-09-29 13:21:22 UTC (rev 91589)
@@ -37,6 +37,10 @@
 from grokcore.view import skin
 from grokcore.view import url
 
+from grokcore.formlib import action
+from grokcore.formlib import AutoFields
+from grokcore.formlib import Fields
+
 from zope.event import notify
 from zope.app.component.hooks import getSite
 from zope.lifecycleevent import (
@@ -68,7 +72,6 @@
 from grok.directive import (local_utility, permissions, site,
                             viewletmanager, view, traversable, order)
 
-from grok.formlib import action, AutoFields, Fields
 
 
 # BBB These two functions are meant for test fixtures and should be

Modified: grok/trunk/src/grok/components.py
===================================================================
--- grok/trunk/src/grok/components.py	2008-09-29 12:39:34 UTC (rev 91588)
+++ grok/trunk/src/grok/components.py	2008-09-29 13:21:22 UTC (rev 91589)
@@ -13,17 +13,12 @@
 ##############################################################################
 """Grok components"""
 
-import os
 import persistent
-import datetime
-import warnings
-import pytz
 import simplejson
 
 import zope.location
 from zope import component
 from zope import interface
-from zope.interface.common import idatetime
 from zope.securitypolicy.role import Role
 from zope.publisher.browser import BrowserPage
 from zope.publisher.interfaces import NotFound
@@ -31,7 +26,6 @@
 from zope.publisher.interfaces.browser import IBrowserPublisher
 from zope.publisher.interfaces.http import IHTTPRequest
 from zope.publisher.publish import mapply
-from zope.formlib import form
 from zope.annotation.interfaces import IAttributeAnnotatable
 
 from zope.app.publisher.browser import getDefaultViewName
@@ -52,7 +46,8 @@
 import martian.util
 
 import grokcore.view
-from grok import interfaces, formlib, util
+import grokcore.formlib
+from grok import interfaces, util
 
 
 class Model(Contained, persistent.Persistent):
@@ -150,6 +145,22 @@
         source.send(message, type)
 
 
+class Form(grokcore.formlib.Form, View):
+    interface.implements(interfaces.IGrokForm)
+
+
+class AddForm(grokcore.formlib.AddForm, View):
+    interface.implements(interfaces.IGrokForm)
+
+
+class DisplayForm(grokcore.formlib.DisplayForm, View):
+    interface.implements(interfaces.IGrokForm)
+
+
+class EditForm(grokcore.formlib.EditForm, View):
+    interface.implements(interfaces.IGrokForm)
+
+
 class XMLRPC(object):
     pass
 
@@ -261,137 +272,6 @@
         return self.context.get(name)
 
 
-default_form_template = grokcore.view.PageTemplateFile(os.path.join(
-    'templates', 'default_edit_form.pt'))
-default_form_template.__grok_name__ = 'default_edit_form'
-default_display_template = grokcore.view.PageTemplateFile(os.path.join(
-    '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
-    # for the different meanings of update/render).
-    interface.implementsOnly(interfaces.IGrokForm)
-
-    template = default_form_template
-
-    def applyData(self, obj, **data):
-        return formlib.apply_data_event(obj, self.form_fields, data,
-                                        self.adapters)
-
-    # BBB -- to be removed in June 2007
-    def applyChanges(self, obj, **data):
-        warnings.warn("The 'applyChanges' method on forms is deprecated "
-                      "and will disappear by June 2007. Please use "
-                      "'applyData' instead.", DeprecationWarning, 2)
-        return bool(self.applyData(obj, **data))
-
-
-class AddForm(Form):
-    pass
-
-
-class EditForm(GrokForm, form.EditFormBase, View):
-    # We're only reusing the form implementation from zope.formlib, we
-    # explicitly don't want to inherit the interface semantics (mostly
-    # for the different meanings of update/render).
-    interface.implementsOnly(interfaces.IGrokForm)
-
-    template = default_form_template
-
-    def applyData(self, obj, **data):
-        return formlib.apply_data_event(obj, self.form_fields, data,
-                                        self.adapters, update=True)
-
-    # BBB -- to be removed in June 2007
-    def applyChanges(self, obj, **data):
-        warnings.warn("The 'applyChanges' method on forms is deprecated "
-                      "and will disappear by June 2007. Please use "
-                      "'applyData' instead.", DeprecationWarning, 2)
-        return bool(self.applyData(obj, **data))
-
-    @formlib.action("Apply")
-    def handle_edit_action(self, **data):
-        if self.applyData(self.context, **data):
-            formatter = self.request.locale.dates.getFormatter(
-                'dateTime', 'medium')
-
-            try:
-                time_zone = idatetime.ITZInfo(self.request)
-            except TypeError:
-                time_zone = pytz.UTC
-
-            self.status = "Updated on %s" % formatter.format(
-                datetime.datetime.now(time_zone)
-                )
-        else:
-            self.status = 'No changes'
-
-
-class DisplayForm(GrokForm, form.DisplayFormBase, View):
-    # We're only reusing the form implementation from zope.formlib, we
-    # explicitly don't want to inherit the interface semantics (mostly
-    # for the different meanings of update/render).
-    interface.implementsOnly(interfaces.IGrokForm)
-
-    template = default_display_template
-
-
 class IndexesClass(object):
     def __init__(self, name, bases=(), attrs=None):
         if attrs is None:

Deleted: grok/trunk/src/grok/formlib.py
===================================================================
--- grok/trunk/src/grok/formlib.py	2008-09-29 12:39:34 UTC (rev 91588)
+++ grok/trunk/src/grok/formlib.py	2008-09-29 13:21:22 UTC (rev 91589)
@@ -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

Deleted: grok/trunk/src/grok/ftests/form/actions.py
===================================================================
--- grok/trunk/src/grok/ftests/form/actions.py	2008-09-29 12:39:34 UTC (rev 91588)
+++ grok/trunk/src/grok/ftests/form/actions.py	2008-09-29 13:21:22 UTC (rev 91589)
@@ -1,81 +0,0 @@
-"""
-Using the @grok.action decorator, different actions can be defined on
-a grok.Form. When @grok.action is used, the default behaviour (the
-'Apply' action) is not available anymore, but it can triggered
-manually by calling self.applyData(object, data).
-
-  >>> getRootFolder()["manfred"] = Mammoth()
-
-  >>> from zope.testbrowser.testing import Browser
-  >>> browser = Browser()
-  >>> browser.handleErrors = False
-  >>> browser.open("http://localhost/manfred/@@edit")
-  >>> browser.getControl(name="form.name").value = "Manfred the Mammoth"
-  >>> browser.getControl(name="form.size").value = "Really big"
-  >>> browser.getControl("Apply").click()
-  >>> print browser.contents
-  <html>...
-  ...Modified!...
-  ...Manfred the Mammoth...
-  ...Really big...
-  ...
-
-Save again without any changes:
-
-  >>> browser.getControl("Apply").click()
-  >>> print browser.contents
-  <html>...
-  ...No changes!...
-  ...
-
-  >>> browser.open("http://localhost/manfred/@@edit")
-  >>> browser.getControl(name="form.name").value = "Manfred the Second"
-  >>> browser.getControl("Hairy").click()
-  >>> print browser.contents
-  <html>...
-  ...Manfred the Second...
-  ...Really big and hairy...
-  ...
-
-  >>> browser.open("http://localhost/manfred/meet")
-  >>> browser.getControl(name="form.other").value = "Ellie"
-  >>> browser.getControl("Meet").click()
-  >>> print browser.contents
-  Manfred the Second meets Ellie
-"""
-import grok
-from zope import schema
-from zope.interface import Interface, implements
-from zope.schema.fieldproperty import FieldProperty
-
-class IMammoth(Interface):
-    name = schema.TextLine(title=u"Name")
-    size = schema.TextLine(title=u"Size", default=u"Quite normal")
-
-class Mammoth(grok.Model):
-    implements(IMammoth)
-    
-    name = FieldProperty(IMammoth['name'])    
-    size = FieldProperty(IMammoth['size'])    
-
-class Edit(grok.EditForm):
-    @grok.action("Apply")
-    def handle_apply(self, **data):
-        if self.applyData(self.context, **data):
-            self.status = 'Modified!'
-        else:
-            self.status = 'No changes!'
-
-    @grok.action("Hairy")
-    def handle_hairy(self, **data):
-        self.applyData(self.context, **data)
-        self.context.size += " and hairy"
-
-class Meet(grok.Form):
-    form_fields = grok.Fields(
-        other = schema.TextLine(title=u'Mammoth to meet with')
-        )
-
-    @grok.action('Meet')
-    def meet(self, other):
-        return self.context.name + ' meets ' + other

Deleted: grok/trunk/src/grok/ftests/form/addform.py
===================================================================
--- grok/trunk/src/grok/ftests/form/addform.py	2008-09-29 12:39:34 UTC (rev 91588)
+++ grok/trunk/src/grok/ftests/form/addform.py	2008-09-29 13:21:22 UTC (rev 91589)
@@ -1,70 +0,0 @@
-"""
-We can use grok.AddForm to render an add form for objects:
-
-  >>> getRootFolder()["zoo"] = Zoo()
-
-  >>> from zope.testbrowser.testing import Browser
-  >>> browser = Browser()
-  >>> browser.handleErrors = False
-
-  >>> browser.open("http://localhost/zoo/@@addmammoth")
-  >>> browser.getControl(name="form.name").value = "Manfred the Mammoth"
-  >>> browser.getControl(name="form.size").value = "Really big"
-  >>> browser.getControl("Add entry").click()
-  >>> print browser.contents
-  Hi, my name is Manfred the Mammoth, and I\'m "Really big"
-
-Instead of calling an object constructor with the form data, we can
-also use the ``applyData`` method to store the data on the object.
-
-  >>> browser.open("http://localhost/zoo/@@addmammothapplydata")
-  >>> browser.getControl(name="form.name").value = "Ellie the Mammoth"
-  >>> browser.getControl(name="form.size").value = "Really small"
-  >>> browser.getControl("Add entry").click()
-  >>> print browser.contents
-  Hi, my name is Ellie the Mammoth, and I\'m "Really small"
-
-"""
-import grok
-from zope import schema
-from zope.interface import Interface, implements
-
-class Zoo(grok.Container):
-    pass
-
-class IMammoth(Interface):
-    name = schema.TextLine(title=u"Name")
-    size = schema.TextLine(title=u"Size", default=u"Quite normal")
-
-class Mammoth(grok.Model):
-    implements(IMammoth)
-
-    def __init__(self, name='', size=''):
-        self.name = name
-        self.size = size
-
-class Index(grok.View):
-    grok.context(Mammoth)
-    def render(self):
-        return 'Hi, my name is %s, and I\'m "%s"' % (self.context.name,
-                                                     self.context.size)
-
-class AddMammoth(grok.AddForm):
-    grok.context(Zoo)
-
-    form_fields = grok.AutoFields(Mammoth)
-
-    @grok.action('Add entry')
-    def add(self, **data):
-        # pass data into Mammoth constructor
-        self.context['manfred'] = manfred = Mammoth(**data)
-        self.redirect(self.url(manfred))
-
-class AddMammothApplyData(AddMammoth):
-
-    @grok.action('Add entry')
-    def add(self, **data):
-        # instantiate Mammoth and then use self.applyData()
-        self.context['ellie'] = ellie = Mammoth()
-        self.applyData(ellie, **data)
-        self.redirect(self.url(ellie))

Deleted: grok/trunk/src/grok/ftests/form/addform_applydata.py
===================================================================
--- grok/trunk/src/grok/ftests/form/addform_applydata.py	2008-09-29 12:39:34 UTC (rev 91588)
+++ grok/trunk/src/grok/ftests/form/addform_applydata.py	2008-09-29 13:21:22 UTC (rev 91589)
@@ -1,66 +0,0 @@
-"""
-We can use AddFrom.applyData to save changes to a newly created
-object.  The object doesn't yet need to have the attributes that are
-going to be set on it.
-
-  >>> getRootFolder()["zoo"] = Zoo()
-
-  >>> from zope.testbrowser.testing import Browser
-  >>> browser = Browser()
-  >>> browser.handleErrors = False
-
-AddForm.applyData() sends an IObjectModifiedEvent after having
-modified the object.  Its return value is True in a Boolean sense when
-the object has been modified:
-
-  >>> browser.open("http://localhost/zoo/@@addmammoth")
-  >>> browser.getControl(name="form.name").value = "Ellie the Mammoth"
-  >>> browser.getControl(name="form.size").value = "Really small"
-  >>> browser.getControl("Add entry").click()
-  An IObjectModifiedEvent was sent for a mammoth with the following changes:
-  IMammoth: name, size
-  >>> print browser.contents
-  There were changes according to applyData.
-
-  >>> browser.open("http://localhost/zoo/ellie")
-  >>> print browser.contents
-  Hi, my name is Ellie the Mammoth, and I\'m "Really small"
-
-"""
-import grok
-from zope import schema, interface
-
-class Zoo(grok.Container):
-    pass
-
-class IMammoth(interface.Interface):
-    name = schema.TextLine(title=u"Name")
-    size = schema.TextLine(title=u"Size")
-
-class Mammoth(grok.Model):
-    grok.implements(IMammoth)
-
-class Index(grok.View):
-    grok.context(Mammoth)
-    def render(self):
-        return 'Hi, my name is %s, and I\'m "%s"' % (self.context.name,
-                                                     self.context.size)
-
-class AddMammoth(grok.AddForm):
-    grok.context(Zoo)
-
-    form_fields = grok.AutoFields(IMammoth)
-
-    @grok.action('Add entry')
-    def add(self, **data):
-        self.context['ellie'] = ellie = Mammoth()
-        if self.applyData(ellie, **data):
-            return 'There were changes according to applyData.'
-        return 'There were no changes according to applyData.'
-
- at grok.subscribe(Mammoth, grok.IObjectModifiedEvent)
-def notify_change_event(mammoth, event):
-    print ("An IObjectModifiedEvent was sent for a mammoth with the "
-           "following changes:")
-    for descr in event.descriptions:
-        print descr.interface.__name__ + ": " + ", ".join(descr.attributes)

Deleted: grok/trunk/src/grok/ftests/form/editform_applydata.py
===================================================================
--- grok/trunk/src/grok/ftests/form/editform_applydata.py	2008-09-29 12:39:34 UTC (rev 91588)
+++ grok/trunk/src/grok/ftests/form/editform_applydata.py	2008-09-29 13:21:22 UTC (rev 91589)
@@ -1,89 +0,0 @@
-"""
-A grok.EditForm uses applyData in update mode to save the form data on
-the object.  Update mode means that only those fields are changed on
-the object that need to be changed.
-
-  >>> getRootFolder()["manfred"] = Mammoth('Manfred the Mammoth', 'Really big')
-
-  >>> from zope.testbrowser.testing import Browser
-  >>> browser = Browser()
-  >>> browser.handleErrors = False
-
-If we don't change any of the fields, there will no object modified
-event and applyData will report no changes:
-
-  >>> browser.open("http://localhost/manfred/@@edit")
-  >>> browser.getControl("Apply").click()
-  >>> 'No changes' in browser.contents
-  True
-
-If we change one field, only that attribute will be changed.  The
-object modified event also reflects that:
-
-  >>> browser.getControl(name="form.name").value = "Manfred the Big Mammoth"
-  >>> browser.getControl("Apply").click()
-  The 'name' property is being set.
-  An IObjectModifiedEvent was sent for a mammoth with the following changes:
-  name
-  >>> 'Updated' in browser.contents
-  True
-
-Let's change the other field:
-
-  >>> browser.getControl(name="form.size").value = "Enormously big"
-  >>> browser.getControl("Apply").click()
-  The 'size' property is being set.
-  An IObjectModifiedEvent was sent for a mammoth with the following changes:
-  size
-  >>> 'Updated' in browser.contents
-  True
-
-And finally let's change both fields:
-
-  >>> browser.getControl(name="form.name").value = "Manfred the Mammoth"
-  >>> browser.getControl(name="form.size").value = "Really big"
-  >>> browser.getControl("Apply").click()
-  The 'name' property is being set.
-  The 'size' property is being set.
-  An IObjectModifiedEvent was sent for a mammoth with the following changes:
-  name, size
-  >>> 'Updated' in browser.contents
-  True
-
-"""
-import grok
-from zope import schema
-
-class Mammoth(grok.Model):
-
-    def __init__(self, name='', size=''):
-        self._name = name
-        self._size = size
-
-    def getName(self):
-        return self._name
-    def setName(self, value):
-        print "The 'name' property is being set."
-        self._name = value
-    name = property(getName, setName)
-
-    def getSize(self):
-        return self._size
-    def setSize(self, value):
-        print "The 'size' property is being set."
-        self._size = value
-    size = property(getSize, setSize)
-
-class Edit(grok.EditForm):
-
-    form_fields = grok.Fields(
-        name = schema.TextLine(title=u"Name"),
-        size = schema.TextLine(title=u"Size")
-        )
-
- at grok.subscribe(Mammoth, grok.IObjectModifiedEvent)
-def notify_change_event(mammoth, event):
-    print ("An IObjectModifiedEvent was sent for a mammoth with the "
-           "following changes:")
-    for descr in event.descriptions:
-        print ", ".join(descr.attributes)

Deleted: grok/trunk/src/grok/ftests/form/editform_applydata_schema.py
===================================================================
--- grok/trunk/src/grok/ftests/form/editform_applydata_schema.py	2008-09-29 12:39:34 UTC (rev 91588)
+++ grok/trunk/src/grok/ftests/form/editform_applydata_schema.py	2008-09-29 13:21:22 UTC (rev 91589)
@@ -1,93 +0,0 @@
-"""
-A grok.EditForm uses applyData in update mode to save the form data on
-the object.  Update mode means that only those fields are changed on
-the object that need to be changed.
-
-This is essentially the same narrative as 'editform_applydata'. Here
-we test the whole procedure on fields from schemas:
-
-  >>> getRootFolder()["manfred"] = Mammoth('Manfred the Mammoth', 'Really big')
-
-  >>> from zope.testbrowser.testing import Browser
-  >>> browser = Browser()
-  >>> browser.handleErrors = False
-
-If we don't change any of the fields, there will no object modified
-event and applyData will report no changes:
-
-  >>> browser.open("http://localhost/manfred/@@edit")
-  >>> browser.getControl("Apply").click()
-  >>> 'No changes' in browser.contents
-  True
-
-If we change one field, only that attribute will be changed.  The
-object modified event also reflects that:
-
-  >>> browser.getControl(name="form.name").value = "Manfred the Big Mammoth"
-  >>> browser.getControl("Apply").click()
-  The 'name' property is being set.
-  An IObjectModifiedEvent was sent for a mammoth with the following changes:
-  IMammoth: name
-  >>> 'Updated' in browser.contents
-  True
-
-Let's change the other field:
-
-  >>> browser.getControl(name="form.size").value = "Enormously big"
-  >>> browser.getControl("Apply").click()
-  The 'size' property is being set.
-  An IObjectModifiedEvent was sent for a mammoth with the following changes:
-  IMammoth: size
-  >>> 'Updated' in browser.contents
-  True
-
-And finally let's change both fields:
-
-  >>> browser.getControl(name="form.name").value = "Manfred the Mammoth"
-  >>> browser.getControl(name="form.size").value = "Really big"
-  >>> browser.getControl("Apply").click()
-  The 'name' property is being set.
-  The 'size' property is being set.
-  An IObjectModifiedEvent was sent for a mammoth with the following changes:
-  IMammoth: name, size
-  >>> 'Updated' in browser.contents
-  True
-
-"""
-import grok
-from zope import schema, interface
-
-class IMammoth(interface.Interface):
-    name = schema.TextLine(title=u"Name")
-    size = schema.TextLine(title=u"Size")
-
-class Mammoth(grok.Model):
-    grok.implements(IMammoth)
-
-    def __init__(self, name='', size=''):
-        self._name = name
-        self._size = size
-
-    def getName(self):
-        return self._name
-    def setName(self, value):
-        print "The 'name' property is being set."
-        self._name = value
-    name = property(getName, setName)
-
-    def getSize(self):
-        return self._size
-    def setSize(self, value):
-        print "The 'size' property is being set."
-        self._size = value
-    size = property(getSize, setSize)
-
-class Edit(grok.EditForm):
-    form_fields = grok.AutoFields(IMammoth)
-
- at grok.subscribe(Mammoth, grok.IObjectModifiedEvent)
-def notify_change_event(mammoth, event):
-    print ("An IObjectModifiedEvent was sent for a mammoth with the "
-           "following changes:")
-    for descr in event.descriptions:
-        print descr.interface.__name__ + ": " + ", ".join(descr.attributes)

Deleted: grok/trunk/src/grok/ftests/form/editform_applydata_schemafields.py
===================================================================
--- grok/trunk/src/grok/ftests/form/editform_applydata_schemafields.py	2008-09-29 12:39:34 UTC (rev 91588)
+++ grok/trunk/src/grok/ftests/form/editform_applydata_schemafields.py	2008-09-29 13:21:22 UTC (rev 91589)
@@ -1,75 +0,0 @@
-"""
-A grok.EditForm uses applyData in update mode to save the form data on
-the object.  Update mode means that only those fields are changed on
-the object that need to be changed.
-
-This is essentially the same narrative as 'editform_applydata'. Here we
-test the whole procedure on fields on the interface implemented by the
-model class:
-
-  >>> getRootFolder()["manfred"] = mammoth = Mammoth()
-  >>> mammoth.name = 'Manfred the Mammoth'
-  >>> mammoth.size = 'Really big'
-
-  >>> from zope.testbrowser.testing import Browser
-  >>> browser = Browser()
-  >>> browser.handleErrors = False
-
-If we don't change any of the fields, there will no object modified
-event and applyData will report no changes:
-
-  >>> browser.open("http://localhost/manfred/@@edit")
-  >>> browser.getControl("Apply").click()
-  >>> 'No changes' in browser.contents
-  True
-
-If we change one field, only that attribute will be changed.  The
-object modified event also reflects that:
-
-  >>> browser.getControl(name="form.name").value = "Manfred the Big Mammoth"
-  >>> browser.getControl("Apply").click()
-  An IObjectModifiedEvent was sent for a mammoth with the following changes:
-  name
-  >>> 'Updated' in browser.contents
-  True
-
-Let's change the other field:
-
-  >>> browser.getControl(name="form.size").value = "Enormously big"
-  >>> browser.getControl("Apply").click()
-  An IObjectModifiedEvent was sent for a mammoth with the following changes:
-  size
-  >>> 'Updated' in browser.contents
-  True
-
-And finally let's change both fields:
-
-  >>> browser.getControl(name="form.name").value = "Manfred the Mammoth"
-  >>> browser.getControl(name="form.size").value = "Really big"
-  >>> browser.getControl("Apply").click()
-  An IObjectModifiedEvent was sent for a mammoth with the following changes:
-  name, size
-  >>> 'Updated' in browser.contents
-  True
-
-"""
-import grok
-from zope import schema
-from zope.interface import Interface, implements
-
-class IMammoth(Interface):
-    name = schema.TextLine(title=u"Name")
-    size = schema.TextLine(title=u"Size", default=u"Quite normal")
-
-class Mammoth(grok.Model):
-    implements(IMammoth)
-    
-class Edit(grok.EditForm):
-    pass
-
- at grok.subscribe(Mammoth, grok.IObjectModifiedEvent)
-def notify_change_event(mammoth, event):
-    print ("An IObjectModifiedEvent was sent for a mammoth with the "
-           "following changes:")
-    for descr in event.descriptions:
-        print ", ".join(descr.attributes)

Modified: grok/trunk/src/grok/ftests/form/form.py
===================================================================
--- grok/trunk/src/grok/ftests/form/form.py	2008-09-29 12:39:34 UTC (rev 91588)
+++ grok/trunk/src/grok/ftests/form/form.py	2008-09-29 13:21:22 UTC (rev 91589)
@@ -1,49 +1,56 @@
 """
-A grok.EditForm is a special grok.View that renders an edit form.
 
-  >>> getRootFolder()["manfred"] = Mammoth()
+Forms have an application_url() method to easily retrieve the url of the
+application, like views does::
 
+  >>> getRootFolder()['world'] = world = IceWorld()
+  >>> world['arthur'] = Mammoth()
+
+And we can access the display form which display the application URL::
+
   >>> from zope.testbrowser.testing import Browser
   >>> browser = Browser()
   >>> browser.handleErrors = False
-  >>> browser.open("http://localhost/manfred/@@edit")
-  >>> browser.getControl(name="form.name").value = "Manfred the Mammoth"
-  >>> browser.getControl(name="form.size").value = "Really big"
-  >>> browser.getControl("Apply").click()
+  >>> browser.open('http://localhost/world/arthur')
   >>> print browser.contents
-  <html>...
-  ...Manfred the Mammoth...
-  ...Really big...
-  ...
+  <p> Test display: application http://localhost/world </p>
 
-grok.DisplayForm renders a display form:
+Same for the edit form::
 
-  >>> browser.open("http://localhost/manfred/@@display")
+  >>> browser.open('http://localhost/world/arthur/@@edit')
   >>> print browser.contents
-  <html>...
-  ...Manfred the Mammoth...
-  ...Really big...
-  ...
+  <p> Test edit: application http://localhost/world </p>
 
+
 """
 import grok
 from zope import schema
-from zope.interface import Interface, implements
-from zope.schema.fieldproperty import FieldProperty
 
-class IMammoth(Interface):
-    name = schema.TextLine(title=u"Name")
-    size = schema.TextLine(title=u"Size", default=u"Quite normal")
+class IceWorld(grok.Application, grok.Container):
+    pass
 
+
 class Mammoth(grok.Model):
-    implements(IMammoth)
-    
-    name = FieldProperty(IMammoth['name'])    
-    size = FieldProperty(IMammoth['size'])    
+    class fields:
+        name = schema.TextLine(title=u"Name")
+        size = schema.TextLine(title=u"Size", default=u"Quite normal")
 
+
+class Index(grok.DisplayForm):
+
+    grok.context(Mammoth)
+
+index = grok.PageTemplate("""
+<p>
+   Test display: application <tal:replace tal:replace="view/application_url" />
+</p>""")
+
+
 class Edit(grok.EditForm):
-    pass
+    
+    grok.context(Mammoth)
 
-class Display(grok.DisplayForm):
-    pass
-
+edit = grok.PageTemplate("""
+<p>
+   Test edit: application <tal:replace tal:replace="view/application_url" />
+</p>""")

Deleted: grok/trunk/src/grok/ftests/form/templateform.py
===================================================================
--- grok/trunk/src/grok/ftests/form/templateform.py	2008-09-29 12:39:34 UTC (rev 91588)
+++ grok/trunk/src/grok/ftests/form/templateform.py	2008-09-29 13:21:22 UTC (rev 91589)
@@ -1,74 +0,0 @@
-"""
-If a form does not have a template, a simple default template is
-associated with them. Otherwise, the supplied template is used.
-
-  >>> from zope.publisher.browser import TestRequest
-  >>> request = TestRequest()
-  >>> from zope import component
-  
-Default edit template:
-
-  >>> view = component.getMultiAdapter((Mammoth(), request), name='edit')
-  >>> print view()
-  <html>...
-  
-Custom edit template:
-
-  >>> view = component.getMultiAdapter((Mammoth(), request), name='edit2')
-  >>> print view()
-  <p>Test edit</p>
-
-Custom edit template with an explicit template
-
-  >>> view = component.getMultiAdapter((Mammoth(), request), name='edit3')
-  >>> print view()
-  <p>Test edit</p>
-
-Default display template:
-
-  >>> view = component.getMultiAdapter((Mammoth(), request), name='display')
-  >>> print view()
-  <html>...
-  
-Custom display template:
-
-  >>> view = component.getMultiAdapter((Mammoth(), request), name='display2')
-  >>> print view()
-  <p>Test display</p>
-
-Custom display template with an explicit template:
-
-  >>> view = component.getMultiAdapter((Mammoth(), request), name='display3')
-  >>> print view()
-  <p>Test display</p>
-
-"""
-import grok
-from zope import schema
-
-class Mammoth(grok.Model):
-    class fields:
-        name = schema.TextLine(title=u"Name")
-        size = schema.TextLine(title=u"Size", default=u"Quite normal")
-
-class Edit(grok.EditForm):
-    pass
-
-class Edit2(grok.EditForm):
-    pass
-
-edit2 = grok.PageTemplate('<p>Test edit</p>')
-
-class Edit3(grok.EditForm):
-    grok.template('edit2')
-
-class Display(grok.DisplayForm):
-    pass
-
-class Display2(grok.DisplayForm):
-    pass
-
-display2 = grok.PageTemplate('<p>Test display</p>')
-
-class Display3(grok.DisplayForm):
-    grok.template('display2')

Deleted: grok/trunk/src/grok/ftests/form/update.py
===================================================================
--- grok/trunk/src/grok/ftests/form/update.py	2008-09-29 12:39:34 UTC (rev 91588)
+++ grok/trunk/src/grok/ftests/form/update.py	2008-09-29 13:21:22 UTC (rev 91589)
@@ -1,93 +0,0 @@
-"""
-Forms can implement an update() method that will be called before any
-form processing has happened:
-
-  >>> getRootFolder()["manfred"] = Mammoth()
-
-  >>> from zope.testbrowser.testing import Browser
-  >>> browser = Browser()
-  >>> browser.handleErrors = False
-  >>> browser.open("http://localhost/manfred/edit")
-  >>> browser.getControl(name="form.name").value = "Ellie"
-  >>> browser.getControl("Apply").click()
-
-  >>> browser.open("http://localhost/manfred")
-  >>> print browser.contents
-  Ellie, the Mammoth reports: The form's update() was called and my name was Manfred.
-
-A form's update() method can issue a redirect.  In that case, the form
-won't proceed to do any form processing nor rendering:
-
-  >>> browser.open("http://localhost/manfred/editredirect")
-  >>> browser.getControl(name="form.name").value = "Mallie"
-  >>> browser.getControl("Apply").click()
-  >>> print browser.url
-  http://localhost/manfred/index
-
-Because of the redirect, no changes happened to the edited object:
-
-  >>> print browser.contents
-  Ellie, the Mammoth reports: The form's update() was called and my name was Manfred.
-
-A form's update() method may also take arbitrary parameters that will
-be filled with values from the request (such as form values):
-
-  >>> browser.open("http://localhost/manfred/editupdatewitharguments")
-  >>> browser.getControl(name="report").value = "Request argument dispatch to update() works."
-  >>> browser.getControl(name="form.name").value = "Mallie"
-  >>> browser.getControl("Apply").click()
-
-  >>> browser.open("http://localhost/manfred")
-  >>> print browser.contents
-  Mallie, the Mammoth reports: Request argument dispatch to update() works.
-
-"""
-import grok
-from zope import schema
-
-from zope.interface import Interface, implements
-
-class IMammoth(Interface):
-    name = schema.TextLine(title=u"Name")
-
-class Mammoth(grok.Model):
-    implements(IMammoth)
-    
-    name = u'Manfred'
-
-class Index(grok.View):
-
-    def render(self):
-        return "%s, the Mammoth reports: %s" % (self.context.name,
-                                                self.context.report)
-
-class Edit(grok.EditForm):
-
-    def update(self):
-        self.context.report = ("The form's update() was called and my name "
-                               "was %s." % self.context.name)
-
-class EditRedirect(grok.EditForm):
-
-    def update(self):
-        # redirect upon form submit so that no changes are ever saved
-        if 'form.name' in self.request:
-            self.redirect(self.url('index'))
-
-class EditUpdateWithArguments(grok.EditForm):
-
-    def update(self, report=None):
-        if report is not None:
-            self.context.report = report
-
-editupdatewitharguments = grok.PageTemplate("""
-<html>
-<body>
-<form action="" tal:attributes="action request/URL">
-  <input type="text" name="report" />
-  <div tal:repeat="widget view/widgets" tal:content="structure widget" />
-  <div tal:repeat="action view/actions" tal:content="structure action/render" />
-</form>
-</body>
-</html>
-""")

Modified: grok/trunk/src/grok/interfaces.py
===================================================================
--- grok/trunk/src/grok/interfaces.py	2008-09-29 12:39:34 UTC (rev 91588)
+++ grok/trunk/src/grok/interfaces.py	2008-09-29 13:21:22 UTC (rev 91589)
@@ -20,6 +20,7 @@
 from zope.app.container.interfaces import IContainer as IContainerBase
 
 import grokcore.component.interfaces
+import grokcore.formlib.interfaces
 import grokcore.security.interfaces
 import grokcore.view.interfaces
 
@@ -45,10 +46,6 @@
     JSON = interface.Attribute("Base class for JSON methods.")
     REST = interface.Attribute("Base class for REST views.")
     Traverser = interface.Attribute("Base class for custom traversers.")
-    Form = interface.Attribute("Base class for forms.")
-    AddForm = interface.Attribute("Base class for add forms.")
-    EditForm = interface.Attribute("Base class for edit forms.")
-    DisplayForm = interface.Attribute("Base class for display forms.")
     Indexes = interface.Attribute("Base class for catalog index definitions.")
     ViewletManager = interface.Attribute("Base class for viewletmanager.")
     Viewlet = interface.Attribute("Base class for viewlet.")
@@ -104,14 +101,6 @@
         """
 
 
-class IGrokDecorators(grokcore.component.interfaces.IDecorators):
-
-    def action(label, **options):
-        """Decorator that defines an action factory based on a form
-        method. The method receives the form data as keyword
-        parameters."""
-
-
 class IGrokEvents(interface.Interface):
 
     IObjectCreatedEvent = interface.Attribute("")
@@ -145,7 +134,8 @@
 
 class IGrokAPI(grokcore.security.interfaces.IGrokcoreSecurityAPI,
                grokcore.view.interfaces.IGrokcoreViewAPI,
-               IGrokBaseClasses, IGrokDirectives, IGrokDecorators,
+               grokcore.formlib.interfaces.IGrokcoreFormlibAPI,
+               IGrokBaseClasses, IGrokDirectives, 
                IGrokEvents, IGrokErrors):
 
     # BBB this is deprecated
@@ -183,18 +173,7 @@
     def getSite():
         """Get the current site."""
 
-    def Fields(*args, **kw):
-        """Return a list of formlib fields based on interfaces and/or schema
-        fields."""
 
-    def AutoFields(context):
-        """Return a list of fields for context autogenerated by grok.
-        """
-
-    def action(label, actions=None, **options):
-        """grok-specific action decorator.
-        """
-
     IRESTSkinType = interface.Attribute('The REST skin type')
 
 
@@ -211,105 +190,10 @@
         """Send a short message to the user."""
 
 
-class IGrokForm(IGrokView):
-    """Grok form API, inspired by zope.formlib's IFormBaseCustomization.
+class IGrokForm(grokcore.formlib.interfaces.IGrokForm, IGrokView):
+    """All Grok forms provides this interface."""
 
-    We explicitly don't inherit from IFormBaseCustomization because
-    that would imply ISubPage with another definition of update() and
-    render() than IGrokView has.
-    """
 
-    prefix = schema.ASCII(
-        constraint=reConstraint(
-            '[a-zA-Z][a-zA-Z0-9_]*([.][a-zA-Z][a-zA-Z0-9_]*)*',
-            "Must be a sequence of not-separated identifiers"),
-        description=u"""Page-element prefix
-
-        All named or identified page elements in a subpage should have
-        names and identifiers that begin with a subpage prefix
-        followed by a dot.
-        """,
-        readonly=True,
-        )
-
-    def setPrefix(prefix):
-        """Update the subpage prefix
-        """
-
-    label = interface.Attribute("A label to display at the top of a form")
-
-    status = interface.Attribute(
-        """An update status message
-
-        This is normally generated by success or failure handlers.
-        """)
-
-    errors = interface.Attribute(
-        """Sequence of errors encountered during validation
-        """)
-
-    form_result = interface.Attribute(
-        """Return from action result method
-        """)
-
-    form_reset = interface.Attribute(
-        """Boolean indicating whether the form needs to be reset
-        """)
-
-    form_fields = interface.Attribute(
-        """The form's form field definitions
-
-        This attribute is used by many of the default methods.
-        """)
-
-    widgets = interface.Attribute(
-        """The form's widgets
-
-        - set by setUpWidgets
-
-        - used by validate
-        """)
-
-    def setUpWidgets(ignore_request=False):
-        """Set up the form's widgets.
-
-        The default implementation uses the form definitions in the
-        form_fields attribute and setUpInputWidgets.
-
-        The function should set the widgets attribute.
-        """
-
-    def validate(action, data):
-        """The default form validator
-
-        If an action is submitted and the action doesn't have it's own
-        validator then this function will be called.
-        """
-
-    template = interface.Attribute(
-        """Template used to display the form
-        """)
-
-    def resetForm():
-        """Reset any cached data because underlying content may have changed
-        """
-
-    def error_views():
-        """Return views of any errors.
-
-        The errors are returned as an iterable.
-        """
-
-    def applyData(obj, **data):
-        """Save form data to an object.
-
-        This returns a dictionary with interfaces as keys and lists of
-        field names as values to indicate which fields in which
-        schemas had to be changed in order to save the data.  In case
-        the method works in update mode (e.g. on EditForms) and
-        doesn't have to update an object, the dictionary is empty.
-        """
-
 class IREST(interface.Interface):
     context = interface.Attribute("Object that the REST handler presents.")
 

Modified: grok/trunk/src/grok/meta.py
===================================================================
--- grok/trunk/src/grok/meta.py	2008-09-29 12:39:34 UTC (rev 91588)
+++ grok/trunk/src/grok/meta.py	2008-09-29 13:21:22 UTC (rev 91589)
@@ -44,7 +44,7 @@
 from martian import util
 
 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
@@ -139,25 +139,6 @@
         return True
 
 
-class FormGrokker(martian.ClassGrokker):
-    martian.component(components.GrokForm)
-    martian.directive(grok.context)
-
-    def execute(self, factory, config, context, **kw):
-        # Set up form_fields from context class if they haven't been
-        # configured manually already.
-        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)
-        return True
-
-
 class JSONGrokker(martian.MethodGrokker):
     martian.component(grok.JSON)
     martian.directive(grok.context)

Modified: grok/trunk/src/grok/meta.zcml
===================================================================
--- grok/trunk/src/grok/meta.zcml	2008-09-29 12:39:34 UTC (rev 91588)
+++ grok/trunk/src/grok/meta.zcml	2008-09-29 13:21:22 UTC (rev 91589)
@@ -7,6 +7,7 @@
 
   <!-- Load the grokkers -->
   <include package="grokcore.component" file="meta.zcml" />
+  <include package="grokcore.formlib" file="meta.zcml" />
   <include package="grokcore.security" file="meta.zcml" />
   <include package="grokcore.view" file="meta.zcml" />
   <grok:grok package=".meta" />

Modified: grok/trunk/src/grok/testing.py
===================================================================
--- grok/trunk/src/grok/testing.py	2008-09-29 12:39:34 UTC (rev 91588)
+++ grok/trunk/src/grok/testing.py	2008-09-29 13:21:22 UTC (rev 91589)
@@ -45,6 +45,7 @@
     zcml.do_grok('grokcore.security.meta', config)
     zcml.do_grok('grokcore.view.meta', config)
     zcml.do_grok('grokcore.view.templatereg', config)
+    zcml.do_grok('grokcore.formlib.meta', config)
     zcml.do_grok('grok.meta', config)
     zcml.do_grok(module_name, config)
     config.execute_actions()

Modified: grok/trunk/src/grok/tests/test_grok.py
===================================================================
--- grok/trunk/src/grok/tests/test_grok.py	2008-09-29 12:39:34 UTC (rev 91588)
+++ grok/trunk/src/grok/tests/test_grok.py	2008-09-29 13:21:22 UTC (rev 91589)
@@ -44,7 +44,7 @@
     suite = unittest.TestSuite()
     for name in ['adapter', 'error', 'event', 'security', 'catalog',
                  'zcml', 'utility', 'xmlrpc', 'json', 'container',
-                 'traversal', 'form', 'grokker', 'directive',
+                 'traversal', 'grokker', 'directive',
                  'baseclass', 'annotation', 'application',
                  'viewlet', 'testsetup', 'conflict', 'order']:
         suite.addTest(suiteFromPackage(name))

Modified: grok/trunk/versions.cfg
===================================================================
--- grok/trunk/versions.cfg	2008-09-29 12:39:34 UTC (rev 91588)
+++ grok/trunk/versions.cfg	2008-09-29 13:21:22 UTC (rev 91589)
@@ -6,8 +6,9 @@
 ZODB3 = 3.8
 docutils = 0.4
 grokcore.component = 1.5.1
+grokcore.formlib = 1.0
 grokcore.security = 1.0
-grokcore.view = 1.0
+grokcore.view = 1.1
 martian = 0.10
 mechanize = 0.1.7b
 pytz = 2007k



More information about the Checkins mailing list