[Checkins] SVN: five.grok/trunk/ Correct form AutoFields to be usuable.
Sylvain Viollon
sylvain at infrae.com
Sat Nov 22 19:11:05 EST 2008
Log message for revision 93265:
Correct form AutoFields to be usuable.
Changed:
U five.grok/trunk/docs/HISTORY.txt
U five.grok/trunk/src/five/grok/__init__.py
U five.grok/trunk/src/five/grok/components.py
A five.grok/trunk/src/five/grok/formlib.py
A five.grok/trunk/src/five/grok/ftests/form/autofields.py
A five.grok/trunk/src/five/grok/ftests/form/autofields2.py
U five.grok/trunk/src/five/grok/ftests/test_grok_functional.py
U five.grok/trunk/src/five/grok/meta.py
-=-
Modified: five.grok/trunk/docs/HISTORY.txt
===================================================================
--- five.grok/trunk/docs/HISTORY.txt 2008-11-23 00:05:33 UTC (rev 93264)
+++ five.grok/trunk/docs/HISTORY.txt 2008-11-23 00:11:04 UTC (rev 93265)
@@ -7,15 +7,24 @@
* Added support for viewlets with `grokcore.viewlet`_.
[thefunny42]
+* Added support for the DirectoryResource component (new in
+ `grokcore.view`_ 1.2).
+ [thefunny42]
+
* Added support for using Zope 2 templates by default when doing ``from
five import grok`` and using grok.PageTemplateFile (being consistent
with grok.PageTemplate).
[thefunny42]
-* Added support for the DirectoryResource component (new in
- `grokcore.view`_ 1.2).
+* Added a convenient grok.Container.
[thefunny42]
+* Fix AutoFields (and form grokker) not to include OFS Zope 2 defined
+ fields by default. This use to add a lot of buggy and wanted
+ fields.
+ [thefunny42]
+
+
five.grok - 1.0a1 (2008-10-22)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Modified: five.grok/trunk/src/five/grok/__init__.py
===================================================================
--- five.grok/trunk/src/five/grok/__init__.py 2008-11-23 00:05:33 UTC (rev 93264)
+++ five.grok/trunk/src/five/grok/__init__.py 2008-11-23 00:11:04 UTC (rev 93265)
@@ -18,9 +18,11 @@
from grokcore.viewlet import *
from grokcore.formlib import *
-from five.grok.components import View, Model, Form, AddForm
+from five.grok.components import Model, Container
+from five.grok.components import View, Form, AddForm
from five.grok.components import EditForm, DisplayForm
from five.grok.components import ViewletManager, Viewlet
+from five.grok.formlib import AutoFields
# Temporary import explicitly path from grokcore.view (it was missing
# in its API interface)
Modified: five.grok/trunk/src/five/grok/components.py
===================================================================
--- five.grok/trunk/src/five/grok/components.py 2008-11-23 00:05:33 UTC (rev 93264)
+++ five.grok/trunk/src/five/grok/components.py 2008-11-23 00:11:04 UTC (rev 93265)
@@ -24,7 +24,8 @@
from grokcore.component.interfaces import IContext
from grokcore.formlib.components import GrokForm as BaseGrokForm
-from grokcore.formlib.components import default_display_template, default_form_template
+from grokcore.formlib.components import default_display_template, \
+ default_form_template
from grokcore.view.components import PageTemplate
from grokcore.viewlet.components import Viewlet as BaseViewlet
from grokcore.viewlet.components import ViewletManager as BaseViewletManager
@@ -41,17 +42,19 @@
from Products.PageTemplates.Expressions import SecureModuleImporter
from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate
from OFS.SimpleItem import SimpleItem
+from OFS.Folder import Folder
import Acquisition
class Model(SimpleItem):
- # XXX Inheritance order is important here. If we reverse this,
- # then containers can't be models anymore because no unambigous MRO
- # can be established.
interface.implements(IAttributeAnnotatable, IContext)
+class Container(Folder):
+ interface.implements(IAttributeAnnotatable, IContext)
+
+
class View(grokcore.view.View, Acquisition.Explicit):
def __init__(self, *args):
Added: five.grok/trunk/src/five/grok/formlib.py
===================================================================
--- five.grok/trunk/src/five/grok/formlib.py (rev 0)
+++ five.grok/trunk/src/five/grok/formlib.py 2008-11-23 00:11:04 UTC (rev 93265)
@@ -0,0 +1,71 @@
+#############################################################################
+#
+# Copyright (c) 2008 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+
+from zope import interface
+from zope.interface.interfaces import IInterface
+from zope.formlib import form
+from grokcore.formlib.formlib import interface_seen
+
+
+FORBIDDEN_PACKAGES = ['OFS.interfaces', 'webdav.interfaces',]
+
+
+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.
+
+ Don't return any interface from OFS.interfaces, since they
+ contains form fields that we don't want.
+ """
+ declaration = interface.implementedBy(context)
+ seen = []
+ for iface in declaration.flattened():
+ if interface_is_forbidden(iface):
+ continue
+ if interface_seen(seen, iface):
+ continue
+ seen.append(iface)
+ return seen
+
+
+def interface_is_forbidden(iface):
+ """Return true if the interface is coming from a Zope 2 one,
+ defining bad form fields.
+ """
+ for bad_name in FORBIDDEN_PACKAGES:
+ if iface.__identifier__.startswith(bad_name):
+ return True
+ return False
+
Added: five.grok/trunk/src/five/grok/ftests/form/autofields.py
===================================================================
--- five.grok/trunk/src/five/grok/ftests/form/autofields.py (rev 0)
+++ five.grok/trunk/src/five/grok/ftests/form/autofields.py 2008-11-23 00:11:04 UTC (rev 93265)
@@ -0,0 +1,66 @@
+"""
+ >>> from five.grok.ftests.form.autofields import *
+ >>> id = getRootFolder()._setObject("manfred", Mammoth(id='manfred'))
+
+ >>> from Products.Five.testbrowser import Browser
+ >>> browser = Browser()
+ >>> browser.handleErrors = False
+
+ We can test the display form as default view:
+
+ >>> browser.open("http://localhost/manfred")
+ >>> print browser.contents
+ <html>...
+ ... Name ...
+ ... Age ...
+ </html>
+
+ But we have an edition form:
+
+ >>> browser.open("http://localhost/manfred/edit")
+ >>> browser.getControl('Name').value = 'Arthur'
+ >>> browser.getControl('Age').value = '325'
+ >>> browser.getControl('Apply').click()
+ >>> 'Updated' in browser.contents
+ True
+
+ And if we look back to the display form, we will see new values:
+
+ >>> browser.open("http://localhost/manfred")
+ >>> print browser.contents
+ <html>...
+ ... Name ...
+ ... Arthur ...
+ ... Age ...
+ ... 325 ...
+ </html>
+
+"""
+
+from five import grok
+from zope import interface, schema
+from zope.schema.fieldproperty import FieldProperty
+
+
+class IMammoth(interface.Interface):
+
+ name = schema.TextLine(title=u"Name")
+ age = schema.Int(title=u"Age")
+
+
+class Mammoth(grok.Model):
+
+ grok.implements(IMammoth)
+
+ name = FieldProperty(IMammoth['name'])
+ age = FieldProperty(IMammoth['age'])
+
+
+class Edit(grok.EditForm):
+ grok.context(Mammoth)
+
+
+class Index(grok.DisplayForm):
+ pass
+
+
Added: five.grok/trunk/src/five/grok/ftests/form/autofields2.py
===================================================================
--- five.grok/trunk/src/five/grok/ftests/form/autofields2.py (rev 0)
+++ five.grok/trunk/src/five/grok/ftests/form/autofields2.py 2008-11-23 00:11:04 UTC (rev 93265)
@@ -0,0 +1,67 @@
+"""
+ >>> from five.grok.ftests.form.autofields2 import *
+ >>> id = getRootFolder()._setObject("montparnasse", House(id='montparnasse'))
+
+ >>> from Products.Five.testbrowser import Browser
+ >>> browser = Browser()
+ >>> browser.handleErrors = False
+
+ We can test the display form as default view:
+
+ >>> browser.open("http://localhost/montparnasse")
+ >>> print browser.contents
+ <html>...
+ ... Name of the building ...
+ ... Number of floors ...
+ </html>
+
+ But we have an edition form:
+
+ >>> browser.open("http://localhost/montparnasse/edit")
+ >>> browser.getControl('Name of the building').value = 'Tour Montparnasse'
+ >>> browser.getControl('Number of floors').value = '56'
+ >>> browser.getControl('Apply').click()
+ >>> 'Updated' in browser.contents
+ True
+
+ And if we look back to the display form, we will see new values:
+
+ >>> browser.open("http://localhost/montparnasse")
+ >>> print browser.contents
+ <html>...
+ ... Name of the building ...
+ ... Tour Montparnasse ...
+ ... Number of floors ...
+ ... 56 ...
+ </html>
+
+"""
+
+from five import grok
+from zope import interface, schema
+from zope.schema.fieldproperty import FieldProperty
+
+
+class IHouse(interface.Interface):
+
+ name = schema.TextLine(title=u"Name of the building")
+ height = schema.Int(title=u"Number of floors")
+
+
+class House(grok.Container):
+
+ grok.implements(IHouse)
+
+ name = FieldProperty(IHouse['name'])
+ height = FieldProperty(IHouse['height'])
+
+
+class Edit(grok.EditForm):
+
+ form_fields = grok.AutoFields(House)
+
+
+class Index(grok.DisplayForm):
+ pass
+
+
Modified: five.grok/trunk/src/five/grok/ftests/test_grok_functional.py
===================================================================
--- five.grok/trunk/src/five/grok/ftests/test_grok_functional.py 2008-11-23 00:05:33 UTC (rev 93264)
+++ five.grok/trunk/src/five/grok/ftests/test_grok_functional.py 2008-11-23 00:11:04 UTC (rev 93265)
@@ -39,6 +39,10 @@
continue
if filename == '__init__.py':
continue
+ if filename[0] in ('.', '#'):
+ # Some editor create temporary files which can be
+ # annoying.
+ continue
dottedname = 'five.grok.ftests.%s.%s' % (name, filename[:-3])
test = FunctionalDocTestSuite(
Modified: five.grok/trunk/src/five/grok/meta.py
===================================================================
--- five.grok/trunk/src/five/grok/meta.py 2008-11-23 00:05:33 UTC (rev 93264)
+++ five.grok/trunk/src/five/grok/meta.py 2008-11-23 00:11:04 UTC (rev 93265)
@@ -20,7 +20,7 @@
from zope import interface, component
from zope.publisher.interfaces.browser import IDefaultBrowserLayer
-from five.grok import components
+from five.grok import components, formlib
from grokcore.view.meta.directoryresource import _get_resource_path
from martian.error import GrokError
@@ -29,6 +29,21 @@
import os.path
+
+class FormGrokker(martian.ClassGrokker):
+
+ martian.component(components.GrokForm)
+ martian.directive(grokcore.component.context)
+ martian.priority(800) # Must be run before real formlib grokker.
+
+ def execute(self, factory, config, context, **kw):
+ # Set up form_fields from context class if they haven't been
+ # configured manually already using our version of get_auto_fields
+ if getattr(factory, 'form_fields', None) is None:
+ factory.form_fields = formlib.get_auto_fields(context)
+ return True
+
+
class ViewSecurityGrokker(martian.ClassGrokker):
martian.component(five.grok.View)
martian.directive(grokcore.security.require, name='permission')
More information about the Checkins
mailing list