[Zope3-checkins] SVN: zope.formlib/trunk/ `checkInvariants` now takes the context of the form into account when checking interface invariants.
Michael Howitz
cvs-admin at zope.org
Thu Mar 15 07:59:30 UTC 2012
Log message for revision 124594:
`checkInvariants` now takes the context of the form into account when checking interface invariants.
Changed:
U zope.formlib/trunk/CHANGES.txt
U zope.formlib/trunk/setup.py
U zope.formlib/trunk/src/zope/formlib/form.py
U zope.formlib/trunk/src/zope/formlib/form.txt
U zope.formlib/trunk/src/zope/formlib/tests/test_formlib.py
-=-
Modified: zope.formlib/trunk/CHANGES.txt
===================================================================
--- zope.formlib/trunk/CHANGES.txt 2012-03-13 19:15:31 UTC (rev 124593)
+++ zope.formlib/trunk/CHANGES.txt 2012-03-15 07:59:25 UTC (rev 124594)
@@ -2,10 +2,13 @@
Changes
=======
-4.0.7 (unreleased)
+4.1.0 (unreleased)
==================
+- `checkInvariants` now takes the context of the form into account when
+ checking interface invariants.
+
4.0.6 (2011-08-20)
==================
Modified: zope.formlib/trunk/setup.py
===================================================================
--- zope.formlib/trunk/setup.py 2012-03-13 19:15:31 UTC (rev 124593)
+++ zope.formlib/trunk/setup.py 2012-03-15 07:59:25 UTC (rev 124594)
@@ -24,7 +24,7 @@
def read(*rnames):
return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
-version = '4.0.7dev'
+version = '4.1.0dev'
setup(name='zope.formlib',
version=version,
Modified: zope.formlib/trunk/src/zope/formlib/form.py
===================================================================
--- zope.formlib/trunk/src/zope/formlib/form.py 2012-03-13 19:15:31 UTC (rev 124593)
+++ zope.formlib/trunk/src/zope/formlib/form.py 2012-03-15 07:59:25 UTC (rev 124594)
@@ -459,13 +459,15 @@
class FormData:
- def __init__(self, schema, data):
+ def __init__(self, schema, data, context):
self._FormData_data___ = data
self._FormData_schema___ = schema
+ self._FormData_context___ = context
def __getattr__(self, name):
schema = self._FormData_schema___
data = self._FormData_data___
+ context = self._FormData_context___
try:
field = schema[name]
except KeyError:
@@ -473,7 +475,21 @@
else:
value = data.get(name, data)
if value is data:
- raise NoInputData(name)
+ if context is None:
+ raise NoInputData(name)
+ # The value is not in the form look it up on the context:
+ field = schema[name]
+ adapted_context = schema(context)
+ if IField.providedBy(field):
+ value = field.get(adapted_context)
+ elif (zope.interface.interfaces.IAttribute.providedBy(field)
+ and
+ not zope.interface.interfaces.IMethod.providedBy(field)):
+ # Fallback for non-field schema contents:
+ value = getattr(adapted_context, name)
+ else:
+ # Don't know how to extract value
+ raise NoInputData(name)
if zope.interface.interfaces.IMethod.providedBy(field):
if not IField.providedBy(field):
raise RuntimeError(
@@ -486,7 +502,7 @@
raise AttributeError(name)
-def checkInvariants(form_fields, form_data):
+def checkInvariants(form_fields, form_data, context):
# First, collect the data for the various schemas
schema_data = {}
@@ -506,7 +522,7 @@
errors = []
for schema, data in schema_data.items():
try:
- schema.validateInvariants(FormData(schema, data), errors)
+ schema.validateInvariants(FormData(schema, data, context), errors)
except interface.Invalid:
pass # Just collect the errors
@@ -740,7 +756,7 @@
def validate(self, action, data):
return (getWidgetsData(self.widgets, self.prefix, data)
- + checkInvariants(self.form_fields, data))
+ + checkInvariants(self.form_fields, data, self.context))
template = namedtemplate.NamedTemplate('default')
Modified: zope.formlib/trunk/src/zope/formlib/form.txt
===================================================================
--- zope.formlib/trunk/src/zope/formlib/form.txt 2012-03-13 19:15:31 UTC (rev 124593)
+++ zope.formlib/trunk/src/zope/formlib/form.txt 2012-03-15 07:59:25 UTC (rev 124594)
@@ -227,7 +227,7 @@
<input class="textType" id="form.max_size" name="form.max_size" size="10"
type="text" value="" />
<span class="error">Required input is missing.</span>
- <input class="textType" id="form.color" name="form.color" size="20"
+ <input class="textType" id="form.color" name="form.color" size="20"
type="text" value="" />
{'name': u'bob'}
@@ -288,8 +288,8 @@
... if 'submit' in self.request:
... data = {}
... errors = form.getWidgetsData(widgets, 'form', data)
- ... invariant_errors = form.checkInvariants(self.form_fields,
- ... data)
+ ... invariant_errors = form.checkInvariants(
+ ... self.form_fields, data, self.context)
... if errors:
... print 'There were field errors:'
... for error in errors:
@@ -504,8 +504,8 @@
... if 'submit' in self.request:
... data = {}
... errors = form.getWidgetsData(widgets, 'form', data)
- ... invariant_errors = form.checkInvariants(self.form_fields,
- ... data)
+ ... invariant_errors = form.checkInvariants(
+ ... self.form_fields, data, self.context)
... if errors:
... print 'There were field errors:'
... for error in errors:
@@ -698,7 +698,8 @@
...
... def validate(self, action, data):
... return (form.getWidgetsData(self.widgets, self.prefix, data) +
- ... form.checkInvariants(self.form_fields, data))
+ ... form.checkInvariants(
+ ... self.form_fields, data, self.context))
...
... def handle_edit_action(self, action, data):
... if form.applyChanges(self.context, self.form_fields, data):
@@ -1566,15 +1567,15 @@
... super(MyAddForm, self).setUpWidgets(ignore_request)
>>> print MyAddForm(None, request)() # doctest: +NORMALIZE_WHITESPACE
- <input class="textType" id="form.identifier" name="form.identifier"
+ <input class="textType" id="form.identifier" name="form.identifier"
size="10" type="text" value="" />
- <input class="textType" id="form.name" name="form.name" size="20"
+ <input class="textType" id="form.name" name="form.name" size="20"
type="text" value="" />
- <input class="textType" id="form.min_size" name="form.min_size"
+ <input class="textType" id="form.min_size" name="form.min_size"
size="10" type="text" value="" />
- <input class="textType" id="form.max_size" name="form.max_size"
+ <input class="textType" id="form.max_size" name="form.max_size"
size="10" type="text" value="" />
- <input class="textType" id="form.now" name="form.now" size="20"
+ <input class="textType" id="form.now" name="form.now" size="20"
type="text" value="2002-12-02 12:30:00" />
Note that a EditForm can't make use of a get_rendered method. The get_rendered
@@ -1801,7 +1802,7 @@
<input class="textType" id="form.title" name="form.title"
size="20" type="text" value="" />
- >>> form.checkInvariants(form_fields, {'title': 'new'})
+ >>> form.checkInvariants(form_fields, {'title': 'new'}, blah)
[]
>>> form.applyChanges(blah, form_fields, {'title': 'new'})
Modified: zope.formlib/trunk/src/zope/formlib/tests/test_formlib.py
===================================================================
--- zope.formlib/trunk/src/zope/formlib/tests/test_formlib.py 2012-03-13 19:15:31 UTC (rev 124593)
+++ zope.formlib/trunk/src/zope/formlib/tests/test_formlib.py 2012-03-15 07:59:25 UTC (rev 124594)
@@ -630,6 +630,87 @@
"""
+def checkInvariants_falls_back_to_context_if_value_not_in_form():
+ """
+`checkInvariants` is able to access the values from the form and the context to
+make sure invariants are not violated:
+
+ >>> class IFlexMaximum(zope.interface.Interface):
+ ... max = zope.schema.Int(title=u"Maximum")
+ ... value = zope.schema.Int(title=u"Value")
+ ...
+ ... @zope.interface.invariant
+ ... def value_not_bigger_than_max(data):
+ ... if data.value > data.max:
+ ... raise zope.interface.Invalid('value bigger than max')
+
+ >>> class Content(object):
+ ... zope.interface.implements(IFlexMaximum)
+ ... max = 10
+ ... value = 7
+
+ >>> class ValueEditForm(zope.formlib.form.EditForm):
+ ... form_fields = zope.formlib.form.FormFields(
+ ... IFlexMaximum).omit('max')
+
+If the value entered in the example form is bigger than the maximum the
+interface invariant triggers an error:
+
+ >>> from zope.publisher.browser import TestRequest
+ >>> request = TestRequest(
+ ... form={'form.value': 42, 'form.actions.apply': '1'})
+ >>> form = ValueEditForm(Content(), request)
+ >>> form.update()
+ >>> form.errors
+ (Invalid('value bigger than max',),)
+
+If the value is below the maximum no error occures:
+
+ >>> request = TestRequest(
+ ... form={'form.value': 8, 'form.actions.apply': '1'})
+ >>> form = ValueEditForm(Content(), request)
+ >>> form.update()
+ >>> form.errors
+ ()
+"""
+
+
+def FormData___getattr___handles_zope_interrface_attributes_correctly():
+ """
+`FormData.__getattr__` reads objects defined as zope.interface.Attribute in
+interface correctly from context:
+
+ >>> class IStaticMaximum(zope.interface.Interface):
+ ... max = zope.interface.Attribute("Predefined maximum")
+
+ >>> class Content(object):
+ ... zope.interface.implements(IStaticMaximum)
+ ... max = 10
+
+ >>> formdata = zope.formlib.form.FormData(IStaticMaximum, {}, Content())
+ >>> formdata.max
+ 10
+"""
+
+
+def FormData___getattr___raises_exception_if_unknown_how_to_access_value():
+ """
+`FormData.__getattr__` raises an exception if it cannot determine how to
+read the object from context:
+
+ >>> class IStaticMaximum(zope.interface.Interface):
+ ... def max(): pass
+
+ >>> class Content(object):
+ ... zope.interface.implements(IStaticMaximum)
+
+ >>> formdata = zope.formlib.form.FormData(IStaticMaximum, {}, Content())
+ >>> formdata.max
+ Traceback (most recent call last):
+ NoInputData: max
+"""
+
+
def test_suite():
import doctest
checker = zope.testing.renormalizing.RENormalizing([
More information about the Zope3-Checkins
mailing list