[Checkins] SVN: z3c.form/branches/adamg-missing-terms/src/z3c/form/ next stab on accepting missing vocabulary terms

Adam Groszer cvs-admin at zope.org
Fri Sep 7 08:31:35 UTC 2012


Log message for revision 127760:
  next stab on accepting missing vocabulary terms

Changed:
  U   z3c.form/branches/adamg-missing-terms/src/z3c/form/configure.zcml
  U   z3c.form/branches/adamg-missing-terms/src/z3c/form/form.py
  U   z3c.form/branches/adamg-missing-terms/src/z3c/form/interfaces.py
  U   z3c.form/branches/adamg-missing-terms/src/z3c/form/term.py
  U   z3c.form/branches/adamg-missing-terms/src/z3c/form/util.py
  U   z3c.form/branches/adamg-missing-terms/src/z3c/form/util.txt
  U   z3c.form/branches/adamg-missing-terms/src/z3c/form/validator.py

-=-
Modified: z3c.form/branches/adamg-missing-terms/src/z3c/form/configure.zcml
===================================================================
--- z3c.form/branches/adamg-missing-terms/src/z3c/form/configure.zcml	2012-09-07 06:57:57 UTC (rev 127759)
+++ z3c.form/branches/adamg-missing-terms/src/z3c/form/configure.zcml	2012-09-07 08:31:30 UTC (rev 127760)
@@ -83,9 +83,9 @@
   <adapter
       factory=".term.ChoiceTerms"
       />
-  <adapter
+  <!--<adapter
       factory=".term.ChoiceTermsVocabulary"
-      />
+      />-->
   <adapter
       factory=".term.MissingChoiceTermsVocabulary"
       />

Modified: z3c.form/branches/adamg-missing-terms/src/z3c/form/form.py
===================================================================
--- z3c.form/branches/adamg-missing-terms/src/z3c/form/form.py	2012-09-07 06:57:57 UTC (rev 127759)
+++ z3c.form/branches/adamg-missing-terms/src/z3c/form/form.py	2012-09-07 08:31:30 UTC (rev 127760)
@@ -34,22 +34,19 @@
     changes = {}
     for name, field in form.fields.items():
         # If the field is not in the data, then go on to the next one
-        if name not in data:
+        try:
+            newValue = data[name]
+        except KeyError:
             continue
         # If the value is NOT_CHANGED, ignore it, since the widget/converter
         # sent a strong message not to do so.
-        if data[name] is interfaces.NOT_CHANGED:
+        if newValue is interfaces.NOT_CHANGED:
             continue
-        # Get the datamanager and get the original value
-        dm = zope.component.getMultiAdapter(
-            (content, field.field), interfaces.IDataManager)
-        # Only update the data, if it is different
-        # Or we can not get the original value, in which case we can not check
-        # Or it is an Object, in case we'll never know
-        if (not dm.canAccess() or
-            dm.query() != data[name] or
-            zope.schema.interfaces.IObject.providedBy(field.field)):
-            dm.set(data[name])
+        if util.changedField(field.field, newValue, context=content):
+            # Only update the data, if it is different
+            dm = zope.component.getMultiAdapter(
+                (content, field.field), interfaces.IDataManager)
+            dm.set(newValue)
             # Record the change using information required later
             changes.setdefault(dm.field.interface, []).append(name)
     return changes

Modified: z3c.form/branches/adamg-missing-terms/src/z3c/form/interfaces.py
===================================================================
--- z3c.form/branches/adamg-missing-terms/src/z3c/form/interfaces.py	2012-09-07 06:57:57 UTC (rev 127759)
+++ z3c.form/branches/adamg-missing-terms/src/z3c/form/interfaces.py	2012-09-07 08:31:30 UTC (rev 127760)
@@ -1111,18 +1111,3 @@
 class IAfterWidgetUpdateEvent(IWidgetEvent):
     """An event sent out after the widget was updated."""
 
-
-
-
-class IForgivingChoice(zope.schema.interfaces.IChoice):
-    pass
-
-class ForgivingChoice(zope.schema.Choice):
-    zope.interface.implements(IForgivingChoice)
-
-    def _validate(self, value):
-        if self.context is not None:
-            if self.query(self.context) == value:
-                return
-
-        super(ForgivingChoice, self)._validate(value)

Modified: z3c.form/branches/adamg-missing-terms/src/z3c/form/term.py
===================================================================
--- z3c.form/branches/adamg-missing-terms/src/z3c/form/term.py	2012-09-07 06:57:57 UTC (rev 127759)
+++ z3c.form/branches/adamg-missing-terms/src/z3c/form/term.py	2012-09-07 08:31:30 UTC (rev 127760)
@@ -22,6 +22,7 @@
 from zope.schema import vocabulary
 
 from z3c.form import interfaces
+from z3c.form import util
 from z3c.form.i18n import MessageFactory as _
 
 
@@ -135,14 +136,13 @@
             return self.makeMissingTerm(value)
 
     def makeToken(self, value):
-        return unicode(value).encode('utf8').encode('base64').strip()
+        # create a unique valid ASCII token
+        return util.createCSSId(unicode(value))
 
-    def makeMissingTerm(self, value, token=None):
+    def makeMissingTerm(self, value):
         """Return a term that should be displayed for the missing token or
         raise LookupError if it's really invalid"""
-        if token is None:
-            token = self.makeToken(value)
-        return vocabulary.SimpleTerm(value, token,
+        return vocabulary.SimpleTerm(value, self.makeToken(value),
             title=_(u'Missing: ${value}', mapping=dict(value=unicode(value))))
 
     def getTermByToken(self, token):
@@ -154,7 +154,12 @@
                 value = zope.component.getMultiAdapter(
                     (self.widget.context, self.widget.field),
                     interfaces.IDataManager).query()
-                return self.makeMissingTerm(value, token=token)
+                term = self.makeMissingTerm(value)
+                if term.token == token:
+                    # check if the given token matches the value, if not
+                    # fall back on LookupError, otherwise we might accept
+                    # any crap coming from the request
+                    return term
 
             raise LookupError(token)
 
@@ -163,15 +168,7 @@
     """ITerms adapter for zope.schema.IChoice based implementations using
     vocabulary with missing terms support"""
 
-    zope.component.adapts(
-        zope.interface.Interface,
-        interfaces.IFormLayer,
-        zope.interface.Interface,
-        interfaces.IForgivingChoice,
-        zope.schema.interfaces.IBaseVocabulary,
-        interfaces.IWidget)
 
-
 class ChoiceTermsSource(SourceTerms):
     "ITerms adapter for zope.schema.IChoice based implementations using source."
 

Modified: z3c.form/branches/adamg-missing-terms/src/z3c/form/util.py
===================================================================
--- z3c.form/branches/adamg-missing-terms/src/z3c/form/util.py	2012-09-07 06:57:57 UTC (rev 127759)
+++ z3c.form/branches/adamg-missing-terms/src/z3c/form/util.py	2012-09-07 08:31:30 UTC (rev 127760)
@@ -21,6 +21,7 @@
 import string
 import zope.interface
 import zope.contenttype
+import zope.schema
 
 from z3c.form import interfaces
 from z3c.form.i18n import MessageFactory as _
@@ -28,12 +29,16 @@
 
 _identifier = re.compile('[A-Za-z][a-zA-Z0-9_]*$')
 
+
 def createId(name):
     if _identifier.match(name):
         return str(name).lower()
     return name.encode('utf-8').encode('hex')
 
+
 _acceptableChars = string.letters + string.digits + '_-'
+
+
 def createCSSId(name):
     return str(''.join([((char in _acceptableChars and char) or
                          char.encode('utf-8').encode('hex'))
@@ -41,6 +46,7 @@
 
 classTypes = type, types.ClassType
 
+
 def getSpecification(spec, force=False):
     """Get the specification of the given object.
 
@@ -128,6 +134,41 @@
     return widget.filename
 
 
+def changedField(field, value, context=None):
+    """Figure if a field's value changed
+
+    Comparing the value of the context attribute and the given value"""
+    if context is None:
+        context = field.context
+
+    # Get the datamanager and get the original value
+    dm = zope.component.getMultiAdapter(
+        (context, field), interfaces.IDataManager)
+    # now figure value chaged status
+    # Or we can not get the original value, in which case we can not check
+    # Or it is an Object, in case we'll never know
+    if (not dm.canAccess() or
+        dm.query() != value or
+        zope.schema.interfaces.IObject.providedBy(field)):
+        return True
+    else:
+        return False
+
+
+def changedWidget(widget, value, field=None):
+    """figure if a widget's value changed
+
+    Comparing the value of the widget context attribute and the given value"""
+    if (interfaces.IContextAware.providedBy(widget)
+        and not widget.ignoreContext):
+        # if the widget is context aware, figure if it's field changed
+        if field is None:
+            field = widget.field
+        return changedField(field, value)
+    # otherwise we cannot, return 'always changed'
+    return True
+
+
 class UniqueOrderedKeys(object):
     """Ensures that we only use unique keys in a list.
 

Modified: z3c.form/branches/adamg-missing-terms/src/z3c/form/util.txt
===================================================================
--- z3c.form/branches/adamg-missing-terms/src/z3c/form/util.txt	2012-09-07 06:57:57 UTC (rev 127759)
+++ z3c.form/branches/adamg-missing-terms/src/z3c/form/util.txt	2012-09-07 08:31:30 UTC (rev 127760)
@@ -46,7 +46,10 @@
   >>> util.createCSSId(u'This has spaces')
   'This20has20spaces'
 
+  >>> util.createCSSId(unicode(dict({1:'x', 'foobar': 42})))
+  '7b13a2027x272c2027foobar273a20427d'
 
+
 ``getWidgetById(form, id)`` Function
 ------------------------------------
 

Modified: z3c.form/branches/adamg-missing-terms/src/z3c/form/validator.py
===================================================================
--- z3c.form/branches/adamg-missing-terms/src/z3c/form/validator.py	2012-09-07 06:57:57 UTC (rev 127759)
+++ z3c.form/branches/adamg-missing-terms/src/z3c/form/validator.py	2012-09-07 08:31:30 UTC (rev 127760)
@@ -45,6 +45,10 @@
 
     def validate(self, value):
         """See interfaces.IValidator"""
+        if value is interfaces.NOT_CHANGED:
+            # no need to validate unchanged values
+            return True
+
         context = self.context
         field = self.field
         widget = self.widget
@@ -54,23 +58,10 @@
             field.required = False
         if context is not None:
             field = field.bind(context)
-        if value is interfaces.NOT_CHANGED:
-            if (interfaces.IContextAware.providedBy(widget) and
-                not widget.ignoreContext):
-                # get value from context
-                value = zope.component.getMultiAdapter(
-                    (context, field),
-                    interfaces.IDataManager).query()
-            else:
-                value = interfaces.NO_VALUE
-            if value is interfaces.NO_VALUE:
-                # look up default value
-                value = field.default
-                adapter = zope.component.queryMultiAdapter(
-                    (context, self.request, self.view, field, widget),
-                    interfaces.IValue, name='default')
-                if adapter:
-                    value = adapter.get()
+
+        if widget and not util.changedWidget(widget, value, field=field):
+            # if new value == old value, no need to validate
+            return True
         return field.validate(value)
 
     def __repr__(self):



More information about the checkins mailing list