[Zope3-checkins] SVN: zope.formlib/branches/faassen-zaf/ zope.app.form.interfaces -> zope.formlib.interfaces

Martijn Faassen faassen at startifact.com
Wed Dec 30 13:41:16 EST 2009


Log message for revision 107372:
  zope.app.form.interfaces -> zope.formlib.interfaces
  

Changed:
  U   zope.formlib/branches/faassen-zaf/buildout.cfg
  U   zope.formlib/branches/faassen-zaf/src/zope/formlib/errors.txt
  U   zope.formlib/branches/faassen-zaf/src/zope/formlib/form.py
  U   zope.formlib/branches/faassen-zaf/src/zope/formlib/form.txt
  U   zope.formlib/branches/faassen-zaf/src/zope/formlib/interfaces.py
  U   zope.formlib/branches/faassen-zaf/src/zope/formlib/tests.py

-=-
Modified: zope.formlib/branches/faassen-zaf/buildout.cfg
===================================================================
--- zope.formlib/branches/faassen-zaf/buildout.cfg	2009-12-30 18:36:02 UTC (rev 107371)
+++ zope.formlib/branches/faassen-zaf/buildout.cfg	2009-12-30 18:41:15 UTC (rev 107372)
@@ -1,5 +1,5 @@
 [buildout]
-develop = .
+develop = . ../zope.app.form
 parts = test python
 
 [test]

Modified: zope.formlib/branches/faassen-zaf/src/zope/formlib/errors.txt
===================================================================
--- zope.formlib/branches/faassen-zaf/src/zope/formlib/errors.txt	2009-12-30 18:36:02 UTC (rev 107371)
+++ zope.formlib/branches/faassen-zaf/src/zope/formlib/errors.txt	2009-12-30 18:41:15 UTC (rev 107372)
@@ -59,7 +59,7 @@
 
 WidgetInputError exceptions also work with i18n messages:
 
-    >>> from zope.app.form.interfaces import WidgetInputError
+    >>> from zope.formlib.interfaces import WidgetInputError
     >>> myError = WidgetInputError(
     ...     field_name='summary',
     ...     widget_title=_(u'Summary'),

Modified: zope.formlib/branches/faassen-zaf/src/zope/formlib/form.py
===================================================================
--- zope.formlib/branches/faassen-zaf/src/zope/formlib/form.py	2009-12-30 18:36:02 UTC (rev 107371)
+++ zope.formlib/branches/faassen-zaf/src/zope/formlib/form.py	2009-12-30 18:41:15 UTC (rev 107372)
@@ -39,9 +39,9 @@
 from zope.browserpage import namedtemplate
 
 import zope.app.form.browser.interfaces
-from zope.app.form.interfaces import IInputWidget, IDisplayWidget
-from zope.app.form.interfaces import WidgetsError, MissingInputError
-from zope.app.form.interfaces import InputErrors, WidgetInputError
+from zope.formlib.interfaces import IInputWidget, IDisplayWidget
+from zope.formlib.interfaces import WidgetsError, MissingInputError
+from zope.formlib.interfaces import InputErrors, WidgetInputError
 
 from zope.formlib import interfaces
 from zope.i18nmessageid import MessageFactory

Modified: zope.formlib/branches/faassen-zaf/src/zope/formlib/form.txt
===================================================================
--- zope.formlib/branches/faassen-zaf/src/zope/formlib/form.txt	2009-12-30 18:36:02 UTC (rev 107371)
+++ zope.formlib/branches/faassen-zaf/src/zope/formlib/form.txt	2009-12-30 18:41:15 UTC (rev 107372)
@@ -1630,7 +1630,7 @@
 Even though the form machinery only has a single errors attribute, if designers
 wish to render widget errors differently than invariant errors, they can be
 separated reasonably easily.  The separation takes advantage of the fact that
-all widget errors should implement zope.app.form.interfaces.IWidgetInputError,
+all widget errors should implement zope.formlib.interfaces.IWidgetInputError,
 and invariant errors shouldn't, because they don't come from a widget.
 Therefore, a simple division such as the following should suffice.
 

Modified: zope.formlib/branches/faassen-zaf/src/zope/formlib/interfaces.py
===================================================================
--- zope.formlib/branches/faassen-zaf/src/zope/formlib/interfaces.py	2009-12-30 18:36:02 UTC (rev 107371)
+++ zope.formlib/branches/faassen-zaf/src/zope/formlib/interfaces.py	2009-12-30 18:41:15 UTC (rev 107372)
@@ -15,10 +15,235 @@
 $Id$
 """
 import re
-from zope import interface, schema
+from zope import schema
 from zope.publisher.interfaces.browser import IBrowserPage
+from zope.schema.interfaces import ValidationError
+from zope.publisher.interfaces import IView
+from zope.interface import Attribute, Interface, implements
+from zope.schema import Bool
+from zope.exceptions.interfaces import UserError
 
+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."""
+
+    implements(IWidgetInputError)
+
+    def __init__(self, field_name, widget_title, errors=None):
+        """Initialize Error
+
+        `errors` is a ``ValidationError`` or a list of ValidationError objects
+        """
+        UserError.__init__(self, field_name, widget_title, errors)
+        self.field_name = field_name
+        self.widget_title = widget_title
+        self.errors = errors
+
+    def doc(self):
+        # TODO this duck typing is to get the code working.  See
+        # collector issue 372
+        if isinstance(self.errors, basestring):
+            return self.errors
+        elif getattr(self.errors, 'doc', None) is not None:
+            return self.errors.doc()
+        return ''
+
+
+class MissingInputError(WidgetInputError):
+    """Required data was not supplied."""
+
+
+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
+
+    def doc(self):
+        return self.error_name
+
+InputErrors = WidgetInputError, ValidationError, ConversionError
+
+
+class ErrorContainer(Exception):
+    """A base error class for collecting multiple errors."""
+
+    def append(self, error):
+        self.args += (error, )
+
+    def __len__(self):
+        return len(self.args)
+
+    def __iter__(self):
+        return iter(self.args)
+
+    def __getitem__(self, i):
+        return self.args[i]
+
+    def __str__(self):
+        return "\n".join(
+            ["%s: %s" % (error.__class__.__name__, error)
+             for error in self.args]
+            )
+
+    __repr__ = __str__
+
+class WidgetsError(ErrorContainer):
+    """A collection of errors from widget processing.
+
+    widgetValues is a map containing the list of values that were obtained
+    from the widgets, keyed by field name.
+    """
+
+    def __init__(self, errors, widgetsData={}):
+        ErrorContainer.__init__(self, *errors)
+        self.widgetsData = widgetsData
+
+class IWidget(IView):
+    """Generically describes the behavior of a widget.
+
+    Note that this level must be still presentation independent.
+    """
+
+    name = Attribute(
+        """The unique widget name
+
+        This must be unique within a set of widgets.""")
+
+    label = Attribute(
+        """The widget label.
+
+        Label may be translated for the request.
+
+        The attribute may be implemented as either a read-write or read-only
+        property, depending on the requirements for a specific implementation.
+
+        """)
+
+    hint = Attribute(
+        """A hint regarding the use of the widget.
+
+        Hints are traditionally rendered using tooltips in GUIs, but may be
+        rendered differently depending on the UI implementation.
+
+        Hint may be translated for the request.
+
+        The attribute may be implemented as either a read-write or read-only
+        property, depending on the requirements for a specific implementation.
+
+        """)
+
+    visible = Attribute(
+        """A flag indicating whether or not the widget is visible.""")
+
+    def setRenderedValue(value):
+        """Set the value to be rendered by the widget.
+
+        Calling this method will override any values provided by the user.
+
+        For input widgets (`IInputWidget` implementations), calling
+        this sets the value that will be rendered even if there is
+        already user input.
+
+        """
+
+    def setPrefix(prefix):
+        """Set the name prefix used for the widget
+
+        The widget name is used to identify the widget's data within
+        input data.  For example, for HTTP forms, the widget name is
+        used for the form key.
+
+        It is acceptable to *reset* the prefix: set it once to read
+        values from the request, and again to redraw with a different
+        prefix but maintained state.
+
+        """
+
+class IInputWidget(IWidget):
+    """A widget for editing a field value."""
+
+    required = Bool(
+        title=u"Required",
+        description=u"""If True, widget should be displayed as requiring input.
+
+        By default, this value is the field's 'required' attribute. This
+        field can be set to False for widgets that always provide input (e.g.
+        a checkbox) to avoid unnecessary 'required' UI notations.
+        """)
+
+    def getInputValue():
+        """Return value suitable for the widget's field.
+
+        The widget must return a value that can be legally assigned to
+        its bound field or otherwise raise ``WidgetInputError``.
+
+        The return value is not affected by `setRenderedValue()`.
+        """
+
+    def applyChanges(content):
+        """Validate the user input data and apply it to the content.
+
+        Return a boolean indicating whether a change was actually applied.
+
+        This raises an error if there is no user input.
+        """
+
+    def hasInput():
+        """Returns ``True`` if the widget has input.
+
+        Input is used by the widget to calculate an 'input value', which is
+        a value that can be legally assigned to a field.
+
+        Note that the widget may return ``True``, indicating it has input, but
+        still be unable to return a value from `getInputValue`. Use
+        `hasValidInput` to determine whether or not `getInputValue` will return
+        a valid value.
+
+        A widget that does not have input should generally not be used
+        to update its bound field.  Values set using
+        `setRenderedValue()` do not count as user input.
+
+        A widget that has been rendered into a form which has been
+        submitted must report that it has input.  If the form
+        containing the widget has not been submitted, the widget
+        shall report that it has no input.
+
+        """
+
+    def hasValidInput():
+        """Returns ``True`` is the widget has valid input.
+
+        This method is similar to `hasInput` but it also confirms that the
+        input provided by the user can be converted to a valid field value
+        based on the field constraints.
+        """
+
+class IDisplayWidget(IWidget):
+    """A widget for displaying a field value."""
+
+    required = Bool(
+        title=u"Required",
+        description=u"""If True, widget should be displayed as requiring input.
+
+        Display widgets should never be required.
+        """)
+
+class IWidgetFactory(Interface):
+    """A factory that creates the widget"""
+    
+    def __call__(context, request):
+        """Return a widget"""
+
 class FormError(Exception):
     """There was an error in managing the form
     """
@@ -31,7 +256,7 @@
             return True
         raise interface.Invalid(value, explanation)
 
-class ISubPage(interface.Interface):
+class ISubPage(Interface):
     """A component that computes part of a page
     """
 
@@ -61,7 +286,7 @@
         """
 
 
-class IFormAPI(interface.Interface):
+class IFormAPI(Interface):
     """API to facilitate creating forms, provided by zope.formlib.form
     """
 
@@ -365,7 +590,7 @@
 
         """
 
-    FormBase = interface.Attribute("""Base class for creating forms
+    FormBase = Attribute("""Base class for creating forms
 
     The FormBase class provides reuasable implementation for creating
     forms.  It implements ISubPage, IBrowserPage, and IFormBaseCustomization.
@@ -384,33 +609,33 @@
 
     """
 
-    label = interface.Attribute("A label to display at the top of a form")
+    label = Attribute("A label to display at the top of a form")
 
-    status = interface.Attribute(
+    status = Attribute(
         """An update status message
 
         This is normally generated by success or failure handlers.
         """)
 
-    errors = interface.Attribute(
+    errors = Attribute(
         """Sequence of errors encountered during validation
         """)
 
-    form_result = interface.Attribute(
+    form_result = Attribute(
         """Return from action result method
         """)
 
-    form_reset = interface.Attribute(
+    form_reset = Attribute(
         """Boolean indicating whether the form needs to be reset
         """)
 
-    form_fields = interface.Attribute(
+    form_fields = Attribute(
         """The form's form field definitions
 
         This attribute is used by many of the default methods.
         """)
 
-    widgets = interface.Attribute(
+    widgets = Attribute(
         """The form's widgets
 
         - set by setUpWidgets
@@ -434,7 +659,7 @@
         validator then this function will be called.
         """
 
-    template = interface.Attribute(
+    template = Attribute(
         """Template used to display the form
 
         This can be overridden in 2 ways:
@@ -458,7 +683,7 @@
 
 
 
-class IFormFields(interface.Interface):
+class IFormFields(Interface):
     """A colection of form fields (IFormField objects)
     """
 
@@ -511,7 +736,7 @@
 SKIP_UNAUTHORIZED = 2
 DISPLAY_UNWRITEABLE = 4
 
-class IFormField(interface.Interface):
+class IFormField(Interface):
     """Definition of a field to be included in a form
 
     This should not be confused with a schema field.
@@ -527,7 +752,7 @@
         """
         )
 
-    field = interface.Attribute(
+    field = Attribute(
         """Schema field that defines the data of the form field
         """
         )
@@ -560,7 +785,7 @@
         """
         )
 
-    custom_widget = interface.Attribute(
+    custom_widget = Attribute(
         """Factory to use for widget construction.
 
         If not set, normal view lookup will be used.
@@ -606,7 +831,7 @@
         missing_value=False,
         )
 
-    get_rendered = interface.Attribute(
+    get_rendered = Attribute(
         """Object to call to get a rendered value
 
         This attribute may be set to a callable object or to
@@ -622,7 +847,7 @@
         """
         )
 
-class IWidgets(interface.Interface):
+class IWidgets(Interface):
     """A widget collection
 
     IWidgets provide ordered collections of widgets that also support:
@@ -666,7 +891,7 @@
 
         """
 
-class IForm(interface.Interface):
+class IForm(Interface):
     """Base type for forms
 
     This exists primarily to provide something for which to register
@@ -697,7 +922,7 @@
 
     data = schema.Dict(title=u"Application data")
 
-    condition = interface.Attribute(
+    condition = Attribute(
         """Action condition
 
         This is a callable object that will be passed a form and an
@@ -706,7 +931,7 @@
 
         """)
 
-    validator = interface.Attribute(
+    validator = Attribute(
         """Action validator
 
         This is a callable object that will be passed a form and an
@@ -754,7 +979,7 @@
         valid only after the action has been bound to a form.
         """
 
-class IActions(interface.Interface):
+class IActions(Interface):
     """An action collection
 
     IActions provide ordered collections of actions that also support
@@ -789,7 +1014,7 @@
     """An action that has been bound to a form
     """
 
-    form = interface.Attribute("The form to which the action is bound")
+    form = Attribute("The form to which the action is bound")
 
 
 class IAddFormCustomization(IFormBaseCustomization):

Modified: zope.formlib/branches/faassen-zaf/src/zope/formlib/tests.py
===================================================================
--- zope.formlib/branches/faassen-zaf/src/zope/formlib/tests.py	2009-12-30 18:36:02 UTC (rev 107371)
+++ zope.formlib/branches/faassen-zaf/src/zope/formlib/tests.py	2009-12-30 18:41:15 UTC (rev 107372)
@@ -35,7 +35,7 @@
 import zope.app.form.browser
 import zope.app.form.browser.exception
 import zope.app.form.browser.interfaces
-import zope.app.form.interfaces
+import zope.formlib.interfaces
 
 import zope.formlib
 import zope.formlib.form
@@ -93,60 +93,60 @@
         [zope.schema.interfaces.ITextLine,
          zope.publisher.interfaces.browser.IBrowserRequest,
          ],
-        zope.app.form.interfaces.IInputWidget,
+        zope.formlib.interfaces.IInputWidget,
         )
     provideAdapter(
         zope.app.form.browser.FloatWidget,
         [zope.schema.interfaces.IFloat,
          zope.publisher.interfaces.browser.IBrowserRequest,
          ],
-        zope.app.form.interfaces.IInputWidget,
+        zope.formlib.interfaces.IInputWidget,
         )
     provideAdapter(
         zope.app.form.browser.UnicodeDisplayWidget,
         [zope.schema.interfaces.IInt,
          zope.publisher.interfaces.browser.IBrowserRequest,
          ],
-        zope.app.form.interfaces.IDisplayWidget,
+        zope.formlib.interfaces.IDisplayWidget,
         )
     provideAdapter(
         zope.app.form.browser.IntWidget,
         [zope.schema.interfaces.IInt,
          zope.publisher.interfaces.browser.IBrowserRequest,
          ],
-        zope.app.form.interfaces.IInputWidget,
+        zope.formlib.interfaces.IInputWidget,
         )
     provideAdapter(
         zope.app.form.browser.UnicodeDisplayWidget,
         [zope.schema.interfaces.IFloat,
          zope.publisher.interfaces.browser.IBrowserRequest,
          ],
-        zope.app.form.interfaces.IDisplayWidget,
+        zope.formlib.interfaces.IDisplayWidget,
         )
     provideAdapter(
         zope.app.form.browser.UnicodeDisplayWidget,
         [zope.schema.interfaces.ITextLine,
          zope.publisher.interfaces.browser.IBrowserRequest,
          ],
-        zope.app.form.interfaces.IDisplayWidget,
+        zope.formlib.interfaces.IDisplayWidget,
         )
     provideAdapter(
         zope.app.form.browser.DatetimeDisplayWidget,
         [zope.schema.interfaces.IDatetime,
          zope.publisher.interfaces.browser.IBrowserRequest,
          ],
-        zope.app.form.interfaces.IDisplayWidget,
+        zope.formlib.interfaces.IDisplayWidget,
         )
     provideAdapter(
         zope.app.form.browser.DatetimeWidget,
         [zope.schema.interfaces.IDatetime,
          zope.publisher.interfaces.browser.IBrowserRequest,
          ],
-        zope.app.form.interfaces.IInputWidget,
+        zope.formlib.interfaces.IInputWidget,
         )
     provideAdapter(
         zope.app.form.browser.exception.WidgetInputErrorView,
-        [zope.app.form.interfaces.IWidgetInputError,
+        [zope.formlib.interfaces.IWidgetInputError,
          zope.publisher.interfaces.browser.IBrowserRequest,
          ],
         zope.app.form.browser.interfaces.IWidgetInputErrorView,
@@ -297,16 +297,16 @@
 Let's test the getWidgetsData method which is responsible for handling widget
 erros raised by the widgets getInputValue method.
 
-    >>> import zope.app.form.interfaces
+    >>> import zope.formlib.interfaces
     >>> class Widget(object):
-    ...     zope.interface.implements(zope.app.form.interfaces.IInputWidget)
+    ...     zope.interface.implements(zope.formlib.interfaces.IInputWidget)
     ...     def __init__(self):
     ...         self.name = 'form.summary'
     ...         self.label = 'Summary'
     ...     def hasInput(self):
     ...         return True
     ...     def getInputValue(self):
-    ...         raise zope.app.form.interfaces.WidgetInputError(
+    ...         raise zope.formlib.interfaces.WidgetInputError(
     ...         field_name='summary',
     ...         widget_title=u'Summary')
     >>> widget = Widget()
@@ -314,7 +314,7 @@
     >>> widgets = zope.formlib.form.Widgets(inputs, 5)
     >>> errors = zope.formlib.form.getWidgetsData(widgets, 'form', {'summary':'value'})
     >>> errors #doctest: +ELLIPSIS
-    [<zope.app.form.interfaces.WidgetInputError instance at ...>]
+    [<zope.formlib.interfaces.WidgetInputError instance at ...>]
 
 Let's see what happens if a widget doesn't convert a ValidationError
 raised by a field to a WidgetInputError. This should not happen if a widget
@@ -323,7 +323,7 @@
 in the formlib as a fallback if some widget doen't handle errors correct. (ri)
 
     >>> class Widget(object):
-    ...     zope.interface.implements(zope.app.form.interfaces.IInputWidget)
+    ...     zope.interface.implements(zope.formlib.interfaces.IInputWidget)
     ...     def __init__(self):
     ...         self.name = 'form.summary'
     ...         self.label = 'summary'
@@ -336,7 +336,7 @@
     >>> widgets = zope.formlib.form.Widgets(inputs, 5)
     >>> errors = zope.formlib.form.getWidgetsData(widgets, 'form', {'summary':'value'})
     >>> errors #doctest: +ELLIPSIS
-    [<zope.app.form.interfaces.WidgetInputError instance at ...>]
+    [<zope.formlib.interfaces.WidgetInputError instance at ...>]
 
 """
 
@@ -535,9 +535,9 @@
     from zope.testing import doctest
     checker = zope.testing.renormalizing.RENormalizing([
       (re.compile(r"\[WidgetInputError\('form.summary', 'summary', ValidationError\('A error message'\)\)\]"),
-                  r"[<zope.app.form.interfaces.WidgetInputError instance at ...>]"),
+                  r"[<zope.formlib.interfaces.WidgetInputError instance at ...>]"),
       (re.compile(r"\[WidgetInputError\('summary', u'Summary', None\)\]"),
-                  r"[<zope.app.form.interfaces.WidgetInputError instance at ...>]"),
+                  r"[<zope.formlib.interfaces.WidgetInputError instance at ...>]"),
       (re.compile(r" ValueError\('invalid literal for float\(\): (bob'|10,0'),\)"),
                   r"\n <exceptions.ValueError instance at ...>"),
     ])



More information about the Zope3-Checkins mailing list