[Checkins] SVN: z3c.form/trunk/ Reporting invariant invalid errors
was not working. Here is what was
Stephan Richter
srichter at cosmos.phy.tufts.edu
Tue Aug 7 23:21:33 EDT 2007
Log message for revision 78679:
Reporting invariant invalid errors was not working. Here is what was
needed:
- Feature: A new ``InvalidErrorViewSnippet`` class provides an error view
snippet for ``zope.interface.Invalid`` exceptions, which are frequently used
for invariants.
- Bug: When extracting and validating data in the widget manager, invariant
errors were not converted to error view snippets.
- Bug: When error view snippets were not widget-specific -- in other words,
the ``widget`` attribute was ``None`` -- rendering the template would fail.
Changed:
U z3c.form/trunk/CHANGES.txt
U z3c.form/trunk/src/z3c/form/configure.zcml
U z3c.form/trunk/src/z3c/form/error.py
U z3c.form/trunk/src/z3c/form/error.txt
U z3c.form/trunk/src/z3c/form/field.py
U z3c.form/trunk/src/z3c/form/field.txt
U z3c.form/trunk/src/z3c/form/form.txt
U z3c.form/trunk/src/z3c/form/testing.py
U z3c.form/trunk/src/z3c/form/tests/simple_caredit.pt
U z3c.form/trunk/src/z3c/form/tests/simple_edit.pt
U z3c.form/trunk/src/z3c/form/tests/simple_groupedit.pt
U z3c.form/trunk/src/z3c/form/tests/simple_owneredit.pt
U z3c.form/trunk/src/z3c/form/tests/simple_subedit.pt
U z3c.form/trunk/src/z3c/form/validator.txt
-=-
Modified: z3c.form/trunk/CHANGES.txt
===================================================================
--- z3c.form/trunk/CHANGES.txt 2007-08-07 21:07:40 UTC (rev 78678)
+++ z3c.form/trunk/CHANGES.txt 2007-08-08 03:21:31 UTC (rev 78679)
@@ -5,6 +5,10 @@
Version 1.6.0 (?/??/2007)
-------------------------
+- Feature: A new ``InvalidErrorViewSnippet`` class provides an error view
+ snippet for ``zope.interface.Invalid`` exceptions, which are frequently used
+ for invariants.
+
- Feature: When a widget is required, HTML-based widgets now declare a
"required" class.
@@ -38,7 +42,13 @@
- Documentation: While reviewing the ``form.txt`` with some people, several
unclear and incomplete statements were discovered and fixed.
+- Bug: When extracting and validating data in the widget manager, invariant
+ errors were not converted to error view snippets.
+- Bug: When error view snippets were not widget-specific -- in other words,
+ the ``widget`` attribute was ``None`` -- rendering the template would fail.
+
+
Version 1.5.0 (7/18/2007)
-------------------------
Modified: z3c.form/trunk/src/z3c/form/configure.zcml
===================================================================
--- z3c.form/trunk/src/z3c/form/configure.zcml 2007-08-07 21:07:40 UTC (rev 78678)
+++ z3c.form/trunk/src/z3c/form/configure.zcml 2007-08-08 03:21:31 UTC (rev 78679)
@@ -97,6 +97,11 @@
permission="zope.Public"
/>
<adapter
+ factory=".error.InvalidErrorViewSnippet"
+ trusted="True"
+ permission="zope.Public"
+ />
+ <adapter
factory=".error.ValueErrorViewSnippet"
trusted="True"
permission="zope.Public"
Modified: z3c.form/trunk/src/z3c/form/error.py
===================================================================
--- z3c.form/trunk/src/z3c/form/error.py 2007-08-07 21:07:40 UTC (rev 78678)
+++ z3c.form/trunk/src/z3c/form/error.py 2007-08-08 03:21:31 UTC (rev 78679)
@@ -58,6 +58,9 @@
self.form = form
self.content = content
+ def createMessage(self):
+ return self.error.doc()
+
def update(self):
value = zope.component.queryMultiAdapter(
(self.context, self.request, self.widget,
@@ -66,7 +69,7 @@
if value is not None:
self.message = value.get()
else:
- self.message = self.error.doc()
+ self.message = self.createMessage()
def render(self):
template = zope.component.getMultiAdapter(
@@ -83,17 +86,21 @@
zope.component.adapts(
ValueError, None, None, None, None, None)
- message = _('The system could not process the given value.')
+ defaultMessage = _('The system could not process the given value.')
- def update(self):
- value = zope.component.queryMultiAdapter(
- (self.context, self.request, self.widget,
- self.field, self.form, self),
- interfaces.IValue, name='message')
- if value is not None:
- self.message = value.get()
+ def createMessage(self):
+ return self.defaultMessage
+class InvalidErrorViewSnippet(ErrorViewSnippet):
+ """Error view snippet."""
+ zope.component.adapts(
+ zope.interface.Invalid, None, None, None, None, None)
+
+ def createMessage(self):
+ return self.error.args[0]
+
+
class ErrorViewTemplateFactory(object):
"""Error view template factory."""
Modified: z3c.form/trunk/src/z3c/form/error.txt
===================================================================
--- z3c.form/trunk/src/z3c/form/error.txt 2007-08-07 21:07:40 UTC (rev 78678)
+++ z3c.form/trunk/src/z3c/form/error.txt 2007-08-08 03:21:31 UTC (rev 78679)
@@ -166,3 +166,25 @@
>>> errorView.update()
>>> print errorView.render()
<div class="error">The entered value is not valid.</div>
+
+
+Invalid Error View Snippets
+---------------------------
+
+When invariants are used, commonly the ``Invalid`` exception (from the
+``zope.interface`` package) is raised from within the invariant, if the
+invariant finds a problem. We need a special error view snippet for this class
+of errors:
+
+ >>> invalidError = zope.interface.Invalid(u'The data was invalid.')
+ >>> errorView = error.InvalidErrorViewSnippet(
+ ... invalidError, TestRequest(), None, None, None, None)
+
+Since the same template as before is used, the error simply renders:
+
+ >>> errorView.update()
+ >>> print errorView.render()
+ <div class="error">The data was invalid.</div>
+
+As you can see, the first argument to the exception is used as the explanatory
+message of the error.
Modified: z3c.form/trunk/src/z3c/form/field.py
===================================================================
--- z3c.form/trunk/src/z3c/form/field.py 2007-08-07 21:07:40 UTC (rev 78678)
+++ z3c.form/trunk/src/z3c/form/field.py 2007-08-08 03:21:31 UTC (rev 78679)
@@ -290,5 +290,10 @@
else:
name = widget.__name__
data[name] = value
- self.errors += self.validate(data)
+ for error in self.validate(data):
+ view = zope.component.getMultiAdapter(
+ (error, self.request, None, None, self.form, self.content),
+ interfaces.IErrorViewSnippet)
+ view.update()
+ self.errors += (view,)
return data, self.errors
Modified: z3c.form/trunk/src/z3c/form/field.txt
===================================================================
--- z3c.form/trunk/src/z3c/form/field.txt 2007-08-07 21:07:40 UTC (rev 78678)
+++ z3c.form/trunk/src/z3c/form/field.txt 2007-08-08 03:21:31 UTC (rev 78679)
@@ -675,10 +675,12 @@
>>> manager.ignoreContext = True
>>> manager.update()
>>> data, errors = manager.extract()
- >>> errors[0].doc()
+ >>> errors[0].error.doc()
'The last name is too short.'
-And that's all.
+Note that the errors coming from invariants are all error view snippets as
+well, just as it is the case for field-specific validation errors. And that's
+really all there is!
Fields -- Custom Widget Factories
Modified: z3c.form/trunk/src/z3c/form/form.txt
===================================================================
--- z3c.form/trunk/src/z3c/form/form.txt 2007-08-07 21:07:40 UTC (rev 78678)
+++ z3c.form/trunk/src/z3c/form/form.txt 2007-08-08 03:21:31 UTC (rev 78679)
@@ -42,6 +42,12 @@
... min=0,
... default=20,
... required=False)
+ ...
+ ... @zope.interface.invariant
+ ... def ensureIdAndNameNotEuqal(person):
+ ... if person.id == person.name:
+ ... raise zope.interface.Invalid(
+ ... "The id and name cannot be the same.")
>>> from zope.schema.fieldproperty import FieldProperty
>>> class Person(object):
@@ -445,6 +451,37 @@
Note that the values of the field are now extracted from the request.
+Another way to receive an error is by not fulfilling the invariants of the
+schema. In our case, the id and name cannot be the same. So let's provoke the
+error now, ...
+
+ >>> request = TestRequest(form={
+ ... 'form.widgets.id': u'Stephan',
+ ... 'form.widgets.name': u'Stephan',
+ ... 'form.widgets.gender': ['male'],
+ ... 'form.widgets.age': u'23',
+ ... 'form.buttons.add': u'Add'}
+ ... )
+
+ >>> addForm = PersonAddForm(root, request)
+ >>> addTemplate(addForm)
+ >>> addForm.update()
+
+and see how the form looks like:
+
+ >>> print addForm.render()
+ <html>
+ <body>
+ <i>There were some errors.</i>
+ <ul>
+ <li>
+ <div class="error">The id and name cannot be the same.</div>
+ </li>
+ </ul>
+ ...
+ </body>
+ </html>
+
Let's now also provide a negative age, which is not possible either:
>>> request = TestRequest(form={
Modified: z3c.form/trunk/src/z3c/form/testing.py
===================================================================
--- z3c.form/trunk/src/z3c/form/testing.py 2007-08-07 21:07:40 UTC (rev 78678)
+++ z3c.form/trunk/src/z3c/form/testing.py 2007-08-08 03:21:31 UTC (rev 78679)
@@ -145,6 +145,7 @@
zope.component.provideAdapter(button.ButtonActionHandler)
# Error View(s)
zope.component.provideAdapter(error.ErrorViewSnippet)
+ zope.component.provideAdapter(error.InvalidErrorViewSnippet)
zope.component.provideAdapter(error.StandardErrorViewTemplate)
def tearDown(test):
Modified: z3c.form/trunk/src/z3c/form/tests/simple_caredit.pt
===================================================================
--- z3c.form/trunk/src/z3c/form/tests/simple_caredit.pt 2007-08-07 21:07:40 UTC (rev 78678)
+++ z3c.form/trunk/src/z3c/form/tests/simple_caredit.pt 2007-08-08 03:21:31 UTC (rev 78679)
@@ -3,8 +3,10 @@
<i tal:condition="view/status" tal:content="view/status" />
<ul tal:condition="view/widgets/errors">
<li tal:repeat="error view/widgets/errors">
- <tal:block replace="error/widget/label"
- />: <tal:block replace="structure error/render" />
+ <tal:block condition="error/widget">
+ <tal:block replace="error/widget/label" />:
+ </tal:block>
+ <tal:block replace="structure error/render" />
</li>
</ul>
<form action=".">
Modified: z3c.form/trunk/src/z3c/form/tests/simple_edit.pt
===================================================================
--- z3c.form/trunk/src/z3c/form/tests/simple_edit.pt 2007-08-07 21:07:40 UTC (rev 78678)
+++ z3c.form/trunk/src/z3c/form/tests/simple_edit.pt 2007-08-08 03:21:31 UTC (rev 78679)
@@ -3,8 +3,10 @@
<i tal:condition="view/status" tal:content="view/status" />
<ul tal:condition="view/widgets/errors">
<li tal:repeat="error view/widgets/errors">
- <tal:block replace="error/widget/label"
- />: <tal:block replace="structure error/render" />
+ <tal:block condition="error/widget">
+ <tal:block replace="error/widget/label" />:
+ </tal:block>
+ <tal:block replace="structure error/render" />
</li>
</ul>
<form action=".">
Modified: z3c.form/trunk/src/z3c/form/tests/simple_groupedit.pt
===================================================================
--- z3c.form/trunk/src/z3c/form/tests/simple_groupedit.pt 2007-08-07 21:07:40 UTC (rev 78678)
+++ z3c.form/trunk/src/z3c/form/tests/simple_groupedit.pt 2007-08-08 03:21:31 UTC (rev 78679)
@@ -4,8 +4,10 @@
<ul tal:condition="view/widgets/errors"
metal:define-macro="errors">
<li tal:repeat="error view/widgets/errors">
- <tal:block replace="error/widget/label"
- />: <tal:block replace="structure error/render" />
+ <tal:block condition="error/widget">
+ <tal:block replace="error/widget/label" />:
+ </tal:block>
+ <tal:block replace="structure error/render" />
</li>
</ul>
<form action=".">
Modified: z3c.form/trunk/src/z3c/form/tests/simple_owneredit.pt
===================================================================
--- z3c.form/trunk/src/z3c/form/tests/simple_owneredit.pt 2007-08-07 21:07:40 UTC (rev 78678)
+++ z3c.form/trunk/src/z3c/form/tests/simple_owneredit.pt 2007-08-08 03:21:31 UTC (rev 78679)
@@ -1,8 +1,10 @@
<i tal:condition="view/status" tal:content="view/status" />
<ul tal:condition="view/widgets/errors">
<li tal:repeat="error view/widgets/errors">
- <tal:block replace="error/widget/label"
- />: <tal:block replace="structure error/render" />
+ <tal:block condition="error/widget">
+ <tal:block replace="error/widget/label" />:
+ </tal:block>
+ <tal:block replace="structure error/render" />
</li>
</ul>
<div class="row" tal:repeat="widget view/widgets/values">
Modified: z3c.form/trunk/src/z3c/form/tests/simple_subedit.pt
===================================================================
--- z3c.form/trunk/src/z3c/form/tests/simple_subedit.pt 2007-08-07 21:07:40 UTC (rev 78678)
+++ z3c.form/trunk/src/z3c/form/tests/simple_subedit.pt 2007-08-08 03:21:31 UTC (rev 78679)
@@ -1,8 +1,10 @@
<i tal:condition="view/status" tal:content="view/status" />
<ul tal:condition="view/widgets/errors">
<li tal:repeat="error view/widgets/errors">
- <tal:block replace="error/widget/label"
- />: <tal:block replace="structure error/render" />
+ <tal:block condition="error/widget">
+ <tal:block replace="error/widget/label" />:
+ </tal:block>
+ <tal:block replace="structure error/render" />
</li>
</ul>
<div class="row" tal:repeat="widget view/widgets/values">
Modified: z3c.form/trunk/src/z3c/form/validator.txt
===================================================================
--- z3c.form/trunk/src/z3c/form/validator.txt 2007-08-07 21:07:40 UTC (rev 78678)
+++ z3c.form/trunk/src/z3c/form/validator.txt 2007-08-08 03:21:31 UTC (rev 78679)
@@ -257,7 +257,7 @@
... CustomValidator, schema=util.getSpecification(IPerson, force=True))
Note: Of course we could have used the ``zope.component.adapts()`` function
- from within the class, but I think it is too tediuos, since you have to
+ from within the class, but I think it is too tedious, since you have to
specify all discriminators and not only the specific ones you are
interested in.
More information about the Checkins
mailing list