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

Jim Fulton jim@zope.com
Thu, 5 Jun 2003 16:13:39 -0400


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

Modified Files:
	utility.py 
Log Message:
Changed the way widgets are created and stored in forms.
Widgets (views on fields) were stored in attributes with the same
names as the fields. This led to conflicts with other view attribute
names in some cases. Now widgets are stored in attributes with names
equal to the field name with an added suffix of '_widget'. For
example, the widget for a title field is named "title_widget".


=== Zope3/src/zope/app/form/utility.py 1.19 => 1.20 ===
--- Zope3/src/zope/app/form/utility.py:1.19	Wed May 21 12:10:07 2003
+++ Zope3/src/zope/app/form/utility.py	Thu Jun  5 16:13:09 2003
@@ -34,6 +34,7 @@
 """
 __metaclass__ = type
 
+from warnings import warn
 from zope.component import getView, getDefaultViewName
 from zope.schema import getFieldsInOrder
 from zope.schema.interfaces import ValidationError
@@ -49,6 +50,44 @@
         fields = [ (name, schema[name]) for name in names ]
     return fields
 
+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
@@ -61,7 +100,28 @@
     widget will be created and assigned to the attribute.
     """
     # Has a (custom) widget already been defined?
-    widget = getattr(view, name, None)
+
+    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
@@ -72,7 +132,9 @@
         if vname is None:
             vname = getDefaultViewName(field, view.request)
         widget = getView(field, vname, view.request)
-        setattr(view, name, widget)
+        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
@@ -83,7 +145,9 @@
             widget = widget(field, view.request)
             if IWidget.isImplementedBy(widget):
                 # Yee ha! We have a widget now, save it
-                setattr(view, name, widget)
+                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(
@@ -91,6 +155,9 @@
                 "but isn't."
                 % (view.__class__.__name__, name))
 
+        if not hasattr(view, wname):
+            setattr(view, wname, widget)
+
     if prefix:
         widget.setPrefix(prefix)
 
@@ -106,7 +173,7 @@
     # opposite meaning.
     if value is not None and (force or not widget.haveData()):
         widget.setData(value)
-
+            
 
 def setUpWidgets(view, schema, prefix=None, force=False,
                  initial={}, names=None, context=None):
@@ -181,7 +248,7 @@
     that was entered by the user.
     """
     for name, field in _fieldlist(names, schema):
-        if  getattr(view, name).haveData():
+        if  getattr(view, name+'_widget').haveData():
             return True
 
     return False
@@ -224,7 +291,7 @@
     errors = []
 
     for name, field in _fieldlist(names, schema):
-        widget = getattr(view, name)
+        widget = getattr(view, name+'_widget')
         if exclude_readonly and widget.context.readonly:
             continue
         if widget.haveData():