[Zope3-checkins] CVS: Zope3/src/zope/app/browser/component - interfacewidget.py:1.5

Steve Alexander steve@cat-box.net
Mon, 6 Jan 2003 13:40:01 -0500


Update of /cvs-repository/Zope3/src/zope/app/browser/component
In directory cvs.zope.org:/tmp/cvs-serv30732/src/zope/app/browser/component

Modified Files:
	interfacewidget.py 
Log Message:
Gave the interface and interfaces fields a basetype that can be None.
Made widgets display the interface name "Anything" for the catch-all
interface None.
Updated adapter and view configuration schemas to use None as the 
basetype for for_interface


=== Zope3/src/zope/app/browser/component/interfacewidget.py 1.4 => 1.5 ===
--- Zope3/src/zope/app/browser/component/interfacewidget.py:1.4	Mon Jan  6 09:49:12 2003
+++ Zope3/src/zope/app/browser/component/interfacewidget.py	Mon Jan  6 13:39:28 2003
@@ -21,41 +21,113 @@
 from zope.app.interfaces.forms import WidgetInputError
 from zope.app.form.widget import Widget
 from zope.publisher.browser import BrowserView
-from zope.app.browser.form.widget import BrowserWidget, DisplayWidget
 from zope.component import getService
-from zope.exceptions import NotFoundError
 from zope.schema.interfaces import ValidationError
 from zope.component.exceptions import ComponentLookupError
 
-class BaseSingleWidget:
 
-    def _convert(self, name):
-        return nameToInterface(self.context.context, name)
+class InterfaceWidget(Widget, BrowserView):
+    __implements__ = IBrowserWidget
 
-    def _unconvert(self, interface):
-        return interfaceToName(interface)
+    def haveData(self):
+        if self.name in self.request.form:
+            v = self.request.form[self.name]
+            return v and nameToInterface(self.context, v)
+        return False
+   
+    def getData(self, optional=0):
+        field = self.context
+        value = self.request.form.get(self.name, self) # self used as marker
+        if value is self:
+            # No user input
+            if field.required and not optional:
+                raise MissingInputError(field.__name__, field.title,
+                                        'the field is required')
+            return field.default
 
-class InterfaceWidget(BaseSingleWidget, BrowserWidget):
+        if value == 'None':
+            value = None
+        else:
+            try:
+                value = nameToInterface(field, value)
+            except ComponentLookupError:
+                # Convert to conversion error
+                exc = ConversionError(sys.exc_info()[1])
+                raise ConversionError, exc, sys.exc_info()[2]
 
+        if not optional:
+            try:
+                field.validate(value)
+            except ValidationError, v:
+                raise WidgetInputError(self.context.__name__,
+                                       self.title, str(v))
+
+        return value
+        
     def __call__(self):
         name = self.name
         search_name = name + ".search"
         search_string = self.request.form.get(search_name, '')
 
+        value = self.request.form.get(self.name, self) # self used as marker
+        
         field = self.context
         service = getService(field.context, "Interfaces")
-        base = field.type
+        base = field.basetype
+        include_none = base is None
         if base == Interface:
             base = None
         interfaces = list(service.searchInterface(search_string, base=base))
         interfaces.sort()
-        interfaces = map(self._unconvert, interfaces)
+        interfaces = map(interfaceToName, interfaces)
+        if include_none:
+            interfaces = ['None'] + interfaces
+
+        if self._data is None:
+            selected = self.getData(1)
+        else:
+            selected = self._data
 
-        selected = self._showData()
+        # if nothing selected in the form...
+        if value is self:
+            selected = None
+        else:
+            selected = interfaceToName(selected)
 
         return renderInterfaceSelect(
                 interfaces, selected, search_name, search_string, name)
 
+    def hidden(self):
+        'See IBrowserWidget'
+        if self._data is None:
+            data = self.getData(1)
+        else:
+            data = self._data
+        if data is None:
+            data = 'None'
+        return ('<input type="hidden" name="%s" value="%s" />'
+                        % (self.name, interfaceToName(data))
+                        )
+       
+    def label(self):
+        return '<label for="%s">%s</label>' % (
+            self.name,
+            self.title,
+            )
+
+    def row(self):
+        return "<td>%s</td><td>%s</td>" % (self.label(), self())
+
+    # --- deprecated methods of IBrowserWidget
+
+    def renderHidden(self, value):
+        'See IBrowserWidget'
+        raise NotImplementedError
+
+    def render(self, value):
+        'See IBrowserWidget'
+        raise NotImplementedError
+
 
 class MultiInterfaceWidget(Widget, BrowserView):
 
@@ -68,9 +140,11 @@
     #  
     def haveData(self):
         name_i = self.name+'.i'
+        field = self.context
         for k,v in self.request.form.iteritems():
             if k.startswith(name_i):
-                if nameToInterface(v) is not None:
+                # XXX write test for this code path
+                if v and nameToInterface(field, v):
                     return True
         return False
 
@@ -114,7 +188,8 @@
         name_search_i = name+'.search.i'
         
         service = getService(field.context, "Interfaces")
-        base = field.value_type
+        base = field.basetype
+        include_none = base is None
         if base == Interface:
             base = None
 
@@ -185,6 +260,8 @@
             interfaces = list(service.searchInterface(search, base=base))
             interfaces.sort()
             interfaces = map(interfaceToName, interfaces)
+            if include_none:
+                interfaces = ['None'] + interfaces
             search_name = '%s.search.i%s' % (name, count)
             rendered_selections.append(
                 renderInterfaceSelect(interfaces, value, search_name,
@@ -228,8 +305,13 @@
         raise NotImplementedError
 
             
-class InterfaceDisplayWidget(BaseSingleWidget, DisplayWidget):
-    pass
+class InterfaceDisplayWidget(InterfaceWidget):
+    def __call__(self):
+        if self._data is None:
+            data = self.getData(1)
+        else:
+            data = self._data
+        return interfaceToName(data)
 
 class MultiInterfaceDisplayWidget(MultiInterfaceWidget):
     def __call__(self):
@@ -241,13 +323,19 @@
 
 def renderInterfaceSelect(
         interfaces, selected, search_name, search_string, select_name):
+    """all of the args are strings"""
     options = ['<option value="">---select interface---</option>']
     for interface in interfaces:
-        options.append('<option value="%s"%s>%s</option>'
-                       % (interface,
-                          interface == selected and ' selected' or '',
-                          interface)
-                       )
+        if interface == 'None':
+            options.append('<option value="None"%s>Anything</option>'
+                           % (interface == selected and ' selected' or '')
+                           )
+        else:
+            options.append('<option value="%s"%s>%s</option>'
+                           % (interface,
+                              interface == selected and ' selected' or '',
+                              interface)
+                           )
 
     search_field = '<input type="text" name="%s" value="%s">' % (
         search_name, search_string)
@@ -258,12 +346,12 @@
     return HTML
 
 def nameToInterface(context, name):
-    if not name:
+    if name is 'None':
         return None
     service = getService(context, "Interfaces")
     return service.getInterface(name)
 
 def interfaceToName(interface):
     if interface is None:
-        return None
+        return 'None'
     return interface.__module__ + '.' + interface.__name__