[Zope3-checkins] SVN: Zope3/trunk/src/zope/app/form/ Conversion errors were not treated correctly as widget input errors.

Stephan Richter srichter at cosmos.phy.tufts.edu
Wed Jul 7 12:50:18 EDT 2004


Log message for revision 26163:
Conversion errors were not treated correctly as widget input errors.
Also, the view for widget input errors expected much more than the
interface was promising. All this is fixed now.

This resolves bug 231.




-=-
Modified: Zope3/trunk/src/zope/app/form/__init__.py
===================================================================
--- Zope3/trunk/src/zope/app/form/__init__.py	2004-07-07 16:46:57 UTC (rev 26162)
+++ Zope3/trunk/src/zope/app/form/__init__.py	2004-07-07 16:50:18 UTC (rev 26163)
@@ -14,7 +14,7 @@
 """
 $Id$
 """
-from zope.app.form.interfaces import IWidget, WidgetInputError
+from zope.app.form.interfaces import IWidget, InputErrors
 from zope.component.interfaces import IViewFactory
 from zope.interface import implements
 from zope.i18n import translate
@@ -69,7 +69,7 @@
         try:
             self.validate()
             return True
-        except WidgetInputError:
+        except InputErrors:
             return False
 
     def validate(self):

Modified: Zope3/trunk/src/zope/app/form/browser/exception.py
===================================================================
--- Zope3/trunk/src/zope/app/form/browser/exception.py	2004-07-07 16:46:57 UTC (rev 26162)
+++ Zope3/trunk/src/zope/app/form/browser/exception.py	2004-07-07 16:50:18 UTC (rev 26163)
@@ -41,7 +41,17 @@
         >>> err = WidgetInputError("foo", "Foo", TooSmallError())
         >>> view = WidgetInputErrorView(err, None)
         >>> view.snippet()
-        '<span class="error">Foo input &lt; 1</span>'
+        u'<span class="error">Foo input &lt; 1</span>'
+
+        The only method that IWidgetInputError promises to implement is
+        `doc()`. Therefore, other implementations of the interface should also
+        work.
+
+        >>> from zope.app.form.interfaces import ConversionError
+        >>> err = ConversionError('Could not convert to float.')
+        >>> view = WidgetInputErrorView(err, None)
+        >>> view.snippet()
+        u'<span class="error">Could not convert to float.</span>'
         """
-        return '<span class="error">%s</span>' %(
-            escape(self.context.errors.doc()))
+        return u'<span class="error">%s</span>' %(
+            escape(self.context.doc()))

Modified: Zope3/trunk/src/zope/app/form/browser/widget.py
===================================================================
--- Zope3/trunk/src/zope/app/form/browser/widget.py	2004-07-07 16:46:57 UTC (rev 26162)
+++ Zope3/trunk/src/zope/app/form/browser/widget.py	2004-07-07 16:50:18 UTC (rev 26163)
@@ -26,6 +26,8 @@
 from zope.app import zapi
 from zope.app.tests import ztapi
 from zope.app.form import Widget, InputWidget
+from zope.app.form.interfaces import ConversionError
+from zope.app.form.interfaces import InputErrors
 from zope.app.form.interfaces import WidgetInputError, MissingInputError
 from zope.app.form.browser.interfaces import IBrowserWidget
 from zope.app.form.browser.interfaces import ISimpleInputWidget
@@ -173,7 +175,7 @@
     to its field:
 
         >>> import re
-        >>> field.constraint = re.compile(".*hello.*").match
+        >>> field.constraint = re.compile('.*hello.*').match
 
     Because we modified the widget's name, the widget will now read different
     different form input:
@@ -226,6 +228,34 @@
         >>> widget.getInputValue() is field.missing_value
         True
 
+    Another type of exception is a conversion error. It is raised when a value
+    cannot be converted to the desired Python object. Here is an example of a
+    floating point.
+
+        >>> from zope.schema import Float
+        >>> field = Float(__name__='price', title=u'Price')
+
+        >>> from zope.app.form.interfaces import ConversionError
+        >>> class FloatWidget(SimpleInputWidget):
+        ...     def _toFieldValue(self, input):
+        ...         try:
+        ...             return float(input)
+        ...         except ValueError, v:
+        ...             raise ConversionError('Invalid floating point data', v)
+        
+        >>> request = TestRequest(form={'field.price': u'32.0'})
+        >>> widget = FloatWidget(field, request)
+        >>> widget.getInputValue()
+        32.0
+
+        >>> request = TestRequest(form={'field.price': u'foo'})
+        >>> widget = FloatWidget(field, request)
+        >>> try:
+        ...     widget.getInputValue()
+        ... except ConversionError, error:
+        ...     print error.doc()
+        Invalid floating point data
+
     >>> tearDown()
     """
 
@@ -259,7 +289,12 @@
             raise MissingInputError(self.name, self.label, None)
 
         # convert input to suitable value - may raise conversion error
-        value = self._toFieldValue(self._getFormInput())
+        try:
+            value = self._toFieldValue(self._getFormInput())
+        except ConversionError, error:
+            # ConversionError is already a WidgetInputError
+            self._error = error
+            raise self._error            
 
         # allow missing values only for non-required fields
         if value == field.missing_value and not field.required:
@@ -330,7 +365,7 @@
             if self.hasInput():
                 try:
                     value = self.getInputValue()
-                except WidgetInputError:
+                except InputErrors:
                     return self.request.form.get(self.name, self._missing)
             else:
                 value = self._getDefault()

Modified: Zope3/trunk/src/zope/app/form/interfaces.py
===================================================================
--- Zope3/trunk/src/zope/app/form/interfaces.py	2004-07-07 16:46:57 UTC (rev 26162)
+++ Zope3/trunk/src/zope/app/form/interfaces.py	2004-07-07 16:50:18 UTC (rev 26163)
@@ -24,6 +24,9 @@
 class IWidgetInputError(Interface):
     """Placeholder for a snippet View"""
 
+    def doc():
+        """Returns a string that represents the error message."""
+
 class WidgetInputError(UserError):
     """One or more user input errors occurred."""
     
@@ -39,20 +42,30 @@
         self.widget_title = widget_title
         self.errors = errors
 
+    def doc(self):
+        return self.errors.doc()
+
+
 class MissingInputError(WidgetInputError):
     """Required data was not supplied."""
 
-class ConversionError(WidgetInputError):
+
+class ConversionError(Exception):
     """A conversion error occurred."""
 
+    implements(IWidgetInputError)
+
     def __init__(self, error_name, original_exception=None):
         Exception.__init__(self, error_name, original_exception)
         self.error_name = error_name
         self.original_exception = original_exception
 
-InputErrors = WidgetInputError, ValidationError
+    def doc(self):
+        return self.error_name
 
+InputErrors = WidgetInputError, ValidationError, ConversionError
 
+
 class ErrorContainer(Exception):
     """A base error class for collecting multiple errors."""
 



More information about the Zope3-Checkins mailing list