[Zope3-checkins] SVN: Zope3/trunk/src/zope/formlib/ Fixed a
critical issue in the formlib. Adaptation of the context to the
Stephan Richter
srichter at cosmos.phy.tufts.edu
Wed Aug 23 17:21:05 EDT 2006
Log message for revision 69738:
Fixed a critical issue in the formlib. Adaptation of the context to the
field interface did not happen as expected. See my mail on zope3-dev as
well.
I think this could also be ported to the 3.3 branch, but I am not sure.
Anyone?
Changed:
U Zope3/trunk/src/zope/formlib/form.py
U Zope3/trunk/src/zope/formlib/form.txt
U Zope3/trunk/src/zope/formlib/tests.py
-=-
Modified: Zope3/trunk/src/zope/formlib/form.py
===================================================================
--- Zope3/trunk/src/zope/formlib/form.py 2006-08-23 20:38:14 UTC (rev 69737)
+++ Zope3/trunk/src/zope/formlib/form.py 2006-08-23 21:21:05 UTC (rev 69738)
@@ -56,7 +56,7 @@
def __init__(self, field, name=None, prefix='',
for_display=None, for_input=None, custom_widget=None,
- render_context=False, get_rendered=None,
+ render_context=False, get_rendered=None, interface=None
):
self.field = field
if name is None:
@@ -66,6 +66,9 @@
name = prefix + '.' + name
self.__name__ = name
self.prefix = prefix
+ if interface is None:
+ interface = field.interface
+ self.interface = interface
self.for_display = for_display
self.for_input = for_input
self.custom_widget = custom_widget
@@ -88,33 +91,34 @@
for arg in args:
if isinstance(arg, InterfaceClass):
for name, field in schema.getFieldsInOrder(arg):
- fields.append((name, field))
+ fields.append((name, field, arg))
elif IField.providedBy(arg):
name = arg.__name__
if not name:
raise ValueError(
"Field has no name")
- fields.append((name, arg))
+ fields.append((name, arg, arg.interface))
elif isinstance(arg, FormFields):
for form_field in arg:
- fields.append((form_field.__name__, form_field))
+ fields.append(
+ (form_field.__name__, form_field, form_field.interface))
elif isinstance(arg, FormField):
- fields.append((arg.__name__, arg))
+ fields.append((arg.__name__, arg, arg.interface))
else:
raise TypeError("Unrecognized argument type", arg)
seq = []
byname = {}
- for name, field in fields:
+ for name, field, iface in fields:
if isinstance(field, FormField):
form_field = field
else:
if field.readonly:
if omit_readonly and (name not in keep_readonly):
continue
- form_field = FormField(field, **defaults)
+ form_field = FormField(field, interface=iface, **defaults)
name = form_field.__name__
if name in byname:
@@ -224,7 +228,7 @@
adapters = {}
# Adapt context, if necessary
- interface = field.interface
+ interface = form_field.interface
adapter = adapters.get(interface)
if adapter is None:
if interface is None:
@@ -347,7 +351,7 @@
for form_field in form_fields:
field = form_field.field
# Adapt context, if necessary
- interface = field.interface
+ interface = form_field.interface
adapter = adapters.get(interface)
if adapter is None:
if interface is None:
@@ -463,7 +467,7 @@
# First, collect the data for the various schemas
schema_data = {}
for form_field in form_fields:
- schema = form_field.field.interface
+ schema = form_field.interface
if schema is None:
continue
@@ -493,7 +497,7 @@
for form_field in form_fields:
field = form_field.field
# Adapt context, if necessary
- interface = field.interface
+ interface = form_field.interface
adapter = adapters.get(interface)
if adapter is None:
if interface is None:
@@ -663,7 +667,7 @@
for action in actions:
if action.submitted():
errors = action.validate(data)
- if errors is None:
+ if errors is None and default_validate is not None:
errors = default_validate(action, data)
return errors, action
Modified: Zope3/trunk/src/zope/formlib/form.txt
===================================================================
--- Zope3/trunk/src/zope/formlib/form.txt 2006-08-23 20:38:14 UTC (rev 69737)
+++ Zope3/trunk/src/zope/formlib/form.txt 2006-08-23 21:21:05 UTC (rev 69738)
@@ -1620,3 +1620,69 @@
Therefore, a simple division such as the following should suffice.
# TODO
+
+Additional Cases
+================
+
+
+Automatic Context Adaptation
+----------------------------
+
+As you may know already, the formlib will automatically adapt the context to
+find a widget and data for a particular field. In an early version of
+``zope.formlib``, it simply used ``field.interface`` to get the interface to
+adapt to. Unfortunately, this call returns the interface the field has been
+defined in and not the interface you got the field from. The following lines
+demonstrate the correct behavior:
+
+ >>> import zope.interface
+ >>> import zope.schema
+
+ >>> class IFoo(zope.interface.Interface):
+ ... title = zope.schema.TextLine()
+
+ >>> class IFooBar(IFoo):
+ ... pass
+
+Here is the unexpected behavior that caused formlib to do the wrong thing:
+
+ >>> IFooBar['title'].interface
+ <InterfaceClass __builtin__.IFoo>
+
+Note: If this behavior ever changes, the formlib can be simplified again.
+
+ >>> class FooBar(object):
+ ... zope.interface.implements(IFooBar)
+ ... title = u'initial'
+ >>> foobar = FooBar()
+
+ >>> class Blah(object):
+ ... def __conform__(self, iface):
+ ... if iface is IFooBar:
+ ... return foobar
+ >>> blah = Blah()
+
+Let's now generate the form fields and instantiate the widgets:
+
+ >>> from zope.formlib import form
+
+ >>> form_fields = form.FormFields(IFooBar)
+
+ >>> request = TestRequest()
+ >>> widgets = form.setUpEditWidgets(form_fields, 'form', blah, request)
+ >>> print widgets.get('title')()
+ <input class="textType" id="form.title" name="form.title"
+ size="20" type="text" value="initial" />
+
+Here are some more places where the behavior was incorrect:
+
+ >>> widgets = form.setUpWidgets(form_fields, 'form', blah, request)
+ >>> print widgets.get('title')()
+ <input class="textType" id="form.title" name="form.title"
+ size="20" type="text" value="" />
+
+ >>> form.checkInvariants(form_fields, {'title': 'new'})
+ []
+
+ >>> form.applyChanges(blah, form_fields, {'title': 'new'})
+ True
Modified: Zope3/trunk/src/zope/formlib/tests.py
===================================================================
--- Zope3/trunk/src/zope/formlib/tests.py 2006-08-23 20:38:14 UTC (rev 69737)
+++ Zope3/trunk/src/zope/formlib/tests.py 2006-08-23 21:21:05 UTC (rev 69738)
@@ -546,6 +546,7 @@
doctest.DocFileSuite(
'form.txt',
setUp=formSetUp, tearDown=zope.component.testing.tearDown,
+ optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
),
doctest.DocTestSuite(
setUp=formSetUp, tearDown=zope.component.testing.tearDown,
More information about the Zope3-Checkins
mailing list