[Zope3-checkins] CVS: Zope3/src/zope/app/form - utility.py:1.25.4.2

Garrett Smith garrett at mojave-corp.com
Sun Feb 8 23:31:46 EST 2004


Update of /cvs-repository/Zope3/src/zope/app/form
In directory cvs.zope.org:/tmp/cvs-serv11138/src/zope/app/form

Modified Files:
      Tag: ozzope-widgets-branch
	utility.py 
Log Message:

Continued refactoring of widgets. Now using view types to lookup widgets
when constructing forms instead of magic names. Next steps include
integration tests for registered widgets, fix existing tests, update
documentation, and fix vocab widgets.


=== Zope3/src/zope/app/form/utility.py 1.25.4.1 => 1.25.4.2 ===
--- Zope3/src/zope/app/form/utility.py:1.25.4.1	Sun Feb  8 18:54:23 2004
+++ Zope3/src/zope/app/form/utility.py	Sun Feb  8 23:31:46 2004
@@ -41,6 +41,7 @@
 from zope.app.interfaces.form import IWidget
 from zope.app.interfaces.form import WidgetsError, MissingInputError
 from zope.app.interfaces.form import InputErrors
+from zope.app.interfaces.form import IEditWidget, IDisplayWidget
 from zope.component.interfaces import IViewFactory
 
 def _fieldlist(names, schema):
@@ -49,48 +50,21 @@
     else:
         fields = [ (name, schema[name]) for name in names ]
     return fields
+    
+    
+def _createWidget(context, field, viewType, request):
+    """Creates a widget given a context, field, and viewType.
+    
+    Uses zapi.getViewProviding to lookup a view for the field and the
+    viewType.
+    """    
+    field = field.bind(context)
+    return zapi.getViewProviding(field, viewType, request)        
+
 
-def _whine(view, name):
-    url = view.request.URL
-    vname = view.__class__.__name__
-    warn(
-        "View (%s) saved a widget (%s) without a '_widget' suffix.\n"
-        "Url: %s"
-        % (vname, name, url),
-        DeprecationWarning, stacklevel=4,
-        )
-
-class WhiningWidget:
-
-    def __init__(self, view, name, widget):
-        self.__widget = widget
-        self.__whineargs = view, name
-
-    def __whine(self):
-        whineargs = self.__whineargs
-        if whineargs:
-            _whine(*whineargs)
-            self.__whineargs = ()
-
-    def __call__(self, *args, **kw):
-        self.__whine()
-        return self.__widget(*args, **kw)
-
-    def __repr__(self):
-        self.__whine()
-        return `self.__widget`
-
-    def __str__(self):
-        self.__whine()
-        return str(self.__widget)
-
-    def __getattr__(self, name):
-        self.__whine()
-        return getattr(self.__widget, name)
-
-def setUpWidget(view, name, field, value=None, prefix=None,
-                force=False, vname=None, context=None):
-    """Set up a single view widget
+def setUpWidget(view, name, field, viewType, value=None, prefix=None,
+                force=False, context=None):
+    """Sets up a single view widget.
 
     The widget will be an attribute of the view. If there is already
     an attribute of the given name, it must be a widget and it will be
@@ -99,116 +73,89 @@
     If there isn't already a view attribute of the given name, then a
     widget will be created and assigned to the attribute.
     """
-    # Has a (custom) widget already been defined?
-
-    wname = name+'_widget'
-
-    widget = getattr(view, wname, None)
-    installold = False
-    if widget is None:
-        widget = getattr(view, name, None)
-        if widget is not None:
-            if IViewFactory.isImplementedBy(widget):
-                # Old custom widget definition.
-                # We'll accept it, but we'll whine
-                _whine(view, name)
-
-                # we also need to remember to install the widget
-                installold = True
-            elif IWidget.isImplementedBy(widget):
-                # Old widget definition. We'll accept it, but we'll whine
-                _whine(view, name)
-            else:
-                # we found something else, which is innocent.
-                widget = None
-                installold = True
-
     if context is None:
         context = view.context
-
+    widgetName = name + '_widget'
+    
+    # check if widget already exists
+    widget = getattr(view, widgetName, None)
     if widget is None:
-        # There isn't already a widget, create one
-        field = field.bind(context)
-        widget = zapi.getViewProviding(field, viewType, view.request)
-        setattr(view, wname, widget)
-        if not hasattr(view, name):
-            setattr(view, name, WhiningWidget(view, name, widget))
-
-    else:
-        # We have an attribute of the right name, is it really a widget
-        if IViewFactory.isImplementedBy(widget):
-            # This is a view factory, probably a custom widget.
-            # Try to make it into a widget.
-            field = field.bind(context)
-            widget = widget(field, view.request)
-            if IWidget.isImplementedBy(widget):
-                # Yee ha! We have a widget now, save it
-                setattr(view, wname, widget)
-                if installold or not hasattr(view, name):
-                    setattr(view, name, WhiningWidget(view, name, widget))
-
-        if not IWidget.isImplementedBy(widget):
-            raise TypeError(
-                "The %s view attribute named, %s, should be a widget, "
-                "but isn't."
-                % (view.__class__.__name__, name))
-
-        if not hasattr(view, wname):
-            setattr(view, wname, widget)
-
+        # does not exist - create it
+        widget = _createWidget(context, field, viewType, view.request)
+    elif IViewFactory.isImplementedBy(widget):
+        # exists, but is actually a factory - use it to create the widget
+        widget = widget(field.bind(context), view.request)
+        
+    # widget must implement IWidget
+    if not IWidget.isImplementedBy(widget):
+        raise TypeError(
+            "Invalid attribute %s in view %s - expected an object that "
+            "implements IWidget, got %r" 
+            % (widgetName, view.__class__.__name__, widget))
+    
+    # ensure the widget is an attribute of the view
+    if not hasattr(view, widgetName):
+        setattr(view, widgetName, widget)
+    
     if prefix:
         widget.setPrefix(prefix)
-
-    if force or not widget.hasInput() and value is not None:
-        # XXX: The doc string sez value should not be None; maybe it should not 
-        # be field.missing_value instead?
+        
+    if not widget.hasInput() or force:
         widget.setRenderedValue(value)
 
 
-def setUpWidgets(view, schema, prefix=None, force=False,
+def setUpWidgets(view, schema, viewType, prefix=None, force=False,
                  initial={}, names=None, context=None):
-    """Set up widgets for the fields defined by a schema
-
+    """Sets up widgets for the fields defined by a schema.
+    
+    view is the view to which the widgets will be added. 
+    
+    If view has an attribute named <field_name>_widget, where field_name is
+    the name of a schema field, that attribute must either be a widget
+    (IWidget) or a view factory (IViewFactory) that creates a widget. If the 
+    attribute value is a widget, it is used as is. If the attribute value
+    is a view factory, it is used to create a widget, which is set as the 
+    new view attribute.
+    
+    schema is an interface that contains the fields for which widget are
+    setup.
+    
+    prefix is a string that is appended to the widget names in the generated
+    HTML. This can be used to differentiate widgets for different schemas.
+    
+    force - XXX OZ rename?
+    
+    initial - XXX OZ initial values to use
+    
+    names - XXX OZ the field names?
+    
+    context - the context, or view's context by default?
     """
     for (name, field) in _fieldlist(names, schema):
-        setUpWidget(view, name, field, initial.get(name),
+        setUpWidget(view, name, field, viewType, value=initial.get(name),
                     prefix=prefix, force=force, context=context)
 
-
 def setUpEditWidgets(view, schema, content=None, prefix=None, force=False,
                      names=None, context=None):
-    """Set up widgets for the fields defined by a schema
-
-    Initial data is provided by content object attributes.
-    No initial data is provided if the content lacks a named
-    attribute, or if the named attribute value is None.
+    """Sets up widgets for an edit form.
+    
+    See setUpWidgets for details on this method's arguments.
     """
     _setUpWidgets(view, schema, content, prefix, force,
-                  names, context, 'display', 'edit')
+                  names, context, IDisplayWidget, IEditWidget)
 
 def setUpDisplayWidgets(view, schema, content=None, prefix=None, force=False,
                         names=None, context=None):
-    """Set up widgets for the fields defined by a schema
-
-    Initial data is provided by content object attributes.
-    No initial data is provided if the content lacks a named
-    attribute, or if the named attribute value is None.
+    """Sets up widgets for a display (read-only) form.
+    
+    See setUpWidgets for details on this method's arguments.
     """
     _setUpWidgets(view, schema, content, prefix, force,
-                  names, context, 'display', 'display')
+                  names, context, IDisplayWidget, IDisplayWidget)
 
 def _setUpWidgets(view, schema, content, prefix, force,
-                  names, context, displayname, editname):
-    # Set up widgets for the fields defined by a schema.
-    #
-    # displayname is the name of the view used for a field that is
-    # marked read-only; editname is the name of the view used for a
-    # field that is editable.
-    #
-    # Initial data is provided by content object attributes.
-    # No initial data is provided if the content lacks a named
-    # attribute, or if the named attribute value is None.
-    #
+                  names, context, displayType, editType):
+    """A helper function used by setUpDisplayWidget and setUpEditWidget."""    
     if content is None:
         if context is None:
             content = view.context
@@ -217,9 +164,9 @@
 
     for name, field in _fieldlist(names, schema):
         if field.readonly:
-            vname = displayname
+            viewType = displayType
         else:
-            vname = editname
+            viewType = editType
 
         try:
             value = field.get(content)
@@ -228,8 +175,7 @@
                 raise
             value = None
 
-        setUpWidget(view, name, field, value,
-                    prefix=prefix, force=force, vname=vname, context=context)
+        setUpWidget(view, name, field, viewType, value, prefix, force, context)
 
 def viewHasInput(view, schema, names=None):
     """Check if we have any user-entered data defined by a schema.
@@ -238,7 +184,7 @@
     the user.
     """
     for name, field in _fieldlist(names, schema):
-        if  getattr(view, name+'_widget').hasInput():
+        if  getattr(view, name + '_widget').hasInput():
             return True
     return False
 
@@ -252,7 +198,7 @@
     errors = []
     changed = False
     for name, field in _fieldlist(names, schema):
-        widget = getattr(view, name+'_widget')
+        widget = getattr(view, name + '_widget')
         if exclude_readonly and field.readonly:
             continue
         if widget.hasInput():
@@ -304,7 +250,7 @@
     errors = []
 
     for name, field in _fieldlist(names, schema):
-        widget = getattr(view, name+'_widget')
+        widget = getattr(view, name + '_widget')
         if exclude_readonly and widget.context.readonly:
             continue
         if widget.hasInput():




More information about the Zope3-Checkins mailing list