Hi

A small introduction, as I believe this is my first post to this list. My name is Jacob, and I am the CTO of a small danish software company named Improva. We have been selling Zope2 based solutions since somewhere around version 2.5.1, and we started using Zope3 when ZopeX3 came out. Among other things we are VARs for Zope Corporation, and have sprinted a bit with some of you there. I have also been lurking on this list almost from the beginning, so I feel like I know most of you even though you don't know me.

Now for the reason I'm delurking...

Using an empty prefix with zope.formlib and the standard widgets from zope.app.form cause the generated HTML widgets to have "name" and "id" attributes starting with a period.

I have two problems with this: 1) It is not valid XHTML, as ids must start with a letter. 2) I need to generate a form that is posted to a different server whose software I do not control, and it is currently not possible to get the name attributes correct without writing my own complete widget set from scratch.

Would it be OK to change the handling of empty prefixes in zope.formlib and zope.app.form to *not* add that leading period in case of an empty prefix? The current behavior is undocumented and could be considered a bug (if not in the code then in the documentation and tests).

I have attached a small patch against the current trunk that does what I want. All current tests pass, but no tests for the new behavior has been added (yet). The patch is minimal in the sense that no API is changed, only the behavior related to empty prefix strings. Specifically it does not change the constructor of the (internal?) class zope.formlib.form.Widgets to take the actual prefix instead of just its length. Doing this would simplify the code and allow some sanity checks, but could cause breakage if the class is used anywhere else.

Comments?

Jacob

--
Jacob Holm
CTO
Improva ApS

Index: src/zope/app/form/__init__.py
===================================================================
--- src/zope/app/form/__init__.py       (revision 70426)
+++ src/zope/app/form/__init__.py       (working copy)
@@ -56,7 +56,7 @@
         return self._data is not self._data_marker
 
     def setPrefix(self, prefix):
-        if not prefix.endswith("."):
+        if prefix and not prefix.endswith("."):
             prefix += '.'
         self._prefix = prefix
         self.name = prefix + self.context.__name__
Index: src/zope/formlib/form.py
===================================================================
--- src/zope/formlib/form.py    (revision 70426)
+++ src/zope/formlib/form.py    (working copy)
@@ -208,6 +208,14 @@
         return zope.security.canAccess(context, writer.__name__)
     return zope.security.canWrite(context, field.__name__)
 
+def prefixjoin(*args):
+    return '.'.join(filter(None,args))
+
+def prefixlen(prefix):
+    if not prefix:
+        return 0
+    return len(prefix)+1
+
 def setUpWidgets(form_fields,
                  form_prefix=None, context=None, request=None, form=None,
                  data=(), adapters=None, ignore_request=False):
@@ -259,9 +267,7 @@
                 widget = component.getMultiAdapter((field, request),
                                                    IInputWidget)
 
-        prefix = form_prefix
-        if form_field.prefix:
-            prefix += '.' + form_field.prefix
+        prefix = prefixjoin(form_prefix, form_field.prefix)
 
         widget.setPrefix(prefix)
 
@@ -278,7 +284,7 @@
 
         widgets.append((not readonly, widget))
 
-    return Widgets(widgets, len(form_prefix)+1)
+    return Widgets(widgets, prefixlen(form_prefix))
 
 def setUpInputWidgets(form_fields, form_prefix, context, request,
                       form=None, ignore_request=False):
@@ -287,9 +293,7 @@
         field = form_field.field.bind(context)
         widget = _createWidget(form_field, field, request, IInputWidget)
 
-        prefix = form_prefix
-        if form_field.prefix:
-            prefix += '.' + form_field.prefix
+        prefix = prefixjoin(form_prefix, form_field.prefix)
 
         widget.setPrefix(prefix)
 
@@ -301,7 +305,7 @@
             widget.setRenderedValue(value)
 
         widgets.append((True, widget))
-    return Widgets(widgets, len(form_prefix)+1)
+    return Widgets(widgets, prefixlen(form_prefix))
 
 
 def _createWidget(form_field, field, request, iface):
@@ -313,7 +317,8 @@
 
 def getWidgetsData(widgets, form_prefix, data):
     errors = []
-    form_prefix += '.'
+    if form_prefix:
+        form_prefix += '.'
 
     for input, widget in widgets.__iter_input_and_widget__():
         if input and IInputWidget.providedBy(widget):
@@ -378,9 +383,7 @@
             iface = IInputWidget
         widget = _createWidget(form_field, field, request, iface)
 
-        prefix = form_prefix
-        if form_field.prefix:
-            prefix += '.' + form_field.prefix
+        prefix = prefixjoin(form_prefix, form_field.prefix)
 
         widget.setPrefix(prefix)
 
@@ -391,7 +394,7 @@
 
         widgets.append((not readonly, widget))
 
-    return Widgets(widgets, len(form_prefix)+1)
+    return Widgets(widgets, prefixlen(form_prefix))
 
 def setUpDataWidgets(form_fields, form_prefix, context, request, data=(),
                      for_display=False, ignore_request=False):
@@ -405,9 +408,8 @@
             iface = IInputWidget
         widget = _createWidget(form_field, field, request, iface)
 
-        prefix = form_prefix
-        if form_field.prefix:
-            prefix += '.' + form_field.prefix
+        prefix = prefixjoin(form_prefix, form_field.prefix)
+
         widget.setPrefix(prefix)
 
         if ((form_field.__name__ in data)
@@ -417,7 +419,7 @@
 
         widgets.append((not readonly, widget))
 
-    return Widgets(widgets, len(form_prefix)+1)
+    return Widgets(widgets, prefixlen(form_prefix))
 
 
 class NoInputData(interface.Invalid):
@@ -550,7 +552,7 @@
             else:
                 name = label.encode('hex')
 
-        self.__name__ = prefix + '.' + name
+        self.__name__ = prefixjoin(prefix, name)
 
         if data is None:
             data = {}
@@ -562,7 +564,7 @@
         result = self.__class__.__new__(self.__class__)
         result.__dict__.update(self.__dict__)
         result.form = form
-        result.__name__ = form.prefix + '.' + result.__name__
+        result.__name__ = prefixjoin(form.prefix, result.__name__)
         interface.alsoProvides(result, interfaces.IBoundAction)
         return result
 
@@ -570,13 +572,6 @@
         condition = self.condition
         return (condition is None) or condition(self.form, self)
 
-    def submitted(self):
-        if not self.available():
-            return False
-        form = self.form
-        name = "%s.%s" % (form.prefix, self.__name__)
-        return name in form.request.form
-
     def validate(self, data):
         if self.validator is not None:
             return self.validator(self.form, self, data)
_______________________________________________
Zope3-dev mailing list
Zope3-dev@zope.org
Unsub: http://mail.zope.org/mailman/options/zope3-dev/archive%40mail-archive.com

Reply via email to