[Testbot] Plone 4.3 - Python 2.7 - Build # 2898 - Regression! - 1 failure(s)

jenkins at plone.org jenkins at plone.org
Thu Feb 12 00:50:21 UTC 2015


-------------------------------------------------------------------------------
Plone 4.3 - Python 2.7 - Build # 2898 - Failure!
-------------------------------------------------------------------------------

http://jenkins.plone.org/job/plone-4.3-python-2.7/2898/


-------------------------------------------------------------------------------
CHANGES
-------------------------------------------------------------------------------

Repository: plone.app.portlets
Branch: refs/heads/2.5.x
Date: 2015-02-08T16:37:52Z
Author: Matthew Wilkes (MatthewWilkes) <git at matthewwilkes.name>
Commit: https://github.com/plone/plone.app.portlets/commit/3454d481e0ce57bc1c26e1583bdd9fd295a7290b

Split import and export value logic into functions that can be called recursively. This allows support for complex type data, such as a List<Object<Text,Choice>>, for example

Files changed:
M plone/app/portlets/exportimport/portlets.py

diff --git a/plone/app/portlets/exportimport/portlets.py b/plone/app/portlets/exportimport/portlets.py
index ced3e5e..913bda5 100644
--- a/plone/app/portlets/exportimport/portlets.py
+++ b/plone/app/portlets/exportimport/portlets.py
@@ -45,7 +45,9 @@
 from zope.component.interfaces import IComponentRegistry
 
 from zope.schema.interfaces import IField
+from zope.schema.interfaces import IChoice
 from zope.schema.interfaces import ICollection
+from zope.schema.interfaces import IObject
 from zope.schema.interfaces import IFromUnicode
 
 from zope.container.interfaces import INameChooser
@@ -140,8 +142,22 @@ def import_node(self, interface, child):
             return
 
         field = field.bind(self.assignment)
-        value = None
 
+        value = self.import_node_for_field(field, child)
+        
+        if field.getName() == 'root' and value in ['', '/']:
+            # these valid values don't pass validation of SearchableTextSourceBinder
+            field.set(self.assignment, value)
+        else:
+            try:
+                field.validate(value)
+            except:
+                import pdb; pdb.set_trace( )
+            field.set(self.assignment, value)
+
+    def import_node_for_field(self, field, child):
+        value = None
+        
         # If we have a collection, we need to look at the value_type.
         # We look for <element>value</element> child nodes and get the
         # value from there
@@ -151,22 +167,28 @@ def import_node(self, interface, child):
             for element in child.childNodes:
                 if element.nodeName != 'element':
                     continue
-                element_value = self.extract_text(element)
-                value.append(self.from_unicode(value_type, element_value))
-            value = self.field_typecast(field, value)
-
-        # Otherwise, just get the value of the <property /> node
+                value.append(self.import_node_for_field(value_type, element))
+        elif IObject.providedBy(field):
+            value = {}
+            for element in child.childNodes:
+                if element.nodeName != 'property':
+                    continue
+                property_key = self.extract_text(element.attributes['name'])
+                property_value = self.import_node_for_field(field.schema[property_key], element)
+                value[property_key] = property_value
+        elif IChoice.providedBy(field):
+            # Choice fields can be optional, so treat an empty contents as None
+            value = self.extract_text(child)
+            if not value:
+                value = None
+            else:
+                value = self.from_unicode(field, value)
         else:
+            # Otherwise, just get the value of the <property /> node
             value = self.extract_text(child)
             if not (field.getName() == 'root' and value in ['', '/']):
                 value = self.from_unicode(field, value)
-
-        if field.getName() == 'root' and value in ['', '/']:
-            # these valid values don't pass validation of SearchableTextSourceBinder
-            field.set(self.assignment, value)
-        else:
-            field.validate(value)
-            field.set(self.assignment, value)
+        return value
 
     def export_field(self, doc, field):
         """Turn a zope.schema field into a node and return it
@@ -178,15 +200,30 @@ def export_field(self, doc, field):
         child.setAttribute('name', field.__name__)
 
         if value is not None:
+            self.export_sub_field(doc, child, field, value)
+
+        return child
+    
+    def export_sub_field(self, doc, parent, field, value):
+        """Turn a zope.schema field into a node and return it
+        """
+        if value is not None:
             if ICollection.providedBy(field):
                 for e in value:
                     list_element = doc.createElement('element')
-                    list_element.appendChild(doc.createTextNode(str(e)))
-                    child.appendChild(list_element)
+                    self.export_sub_field(doc, list_element, field.value_type, e)
+                    parent.appendChild(list_element)
+            elif IObject.providedBy(field):
+                for name, sub_field in field.schema.namesAndDescriptions():
+                    sub_value = value.get(name)
+                    list_element = doc.createElement('property')
+                    list_element.setAttribute('name', name)
+                    self.export_sub_field(doc, list_element, sub_field, sub_value)
+                    parent.appendChild(list_element)
             else:
-                child.appendChild(doc.createTextNode(unicode(value)))
+                parent.appendChild(doc.createTextNode(unicode(value)))
 
-        return child
+        return parent
 
     def extract_text(self, node):
         node.normalize()


Repository: plone.app.portlets
Branch: refs/heads/2.5.x
Date: 2015-02-08T16:37:52Z
Author: Matthew Wilkes (MatthewWilkes) <git at matthewwilkes.name>
Commit: https://github.com/plone/plone.app.portlets/commit/9296a5bab3a69b97a82ce7ab144abc53c74e9c3a

Update changelog

Files changed:
M CHANGES.rst

diff --git a/CHANGES.rst b/CHANGES.rst
index b70dd58..d19d611 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -4,7 +4,8 @@ Changelog
 2.5.3 (unreleased)
 ------------------
 
-- Nothing changed yet.
+- Change the logic for retrieving and storing values of portlets in the assignment exportimport handler to allow for non-trivial data structures.
+  [MatthewWilkes]
 
 
 2.5.2 (2014-09-07)


Repository: plone.app.portlets
Branch: refs/heads/2.5.x
Date: 2015-02-12T00:17:47Z
Author: Matthew Wilkes (MatthewWilkes) <git at matthewwilkes.name>
Commit: https://github.com/plone/plone.app.portlets/commit/0ce798b378d6dfbc7ef4e60e3bcd4905c47972b3

Merge pull request #47 from MatthewWilkes/2.5.x

Make exporting field definitions in assignments recursive, to handle complex data structures

Files changed:
M CHANGES.rst
M plone/app/portlets/exportimport/portlets.py

diff --git a/CHANGES.rst b/CHANGES.rst
index b70dd58..d19d611 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -4,7 +4,8 @@ Changelog
 2.5.3 (unreleased)
 ------------------
 
-- Nothing changed yet.
+- Change the logic for retrieving and storing values of portlets in the assignment exportimport handler to allow for non-trivial data structures.
+  [MatthewWilkes]
 
 
 2.5.2 (2014-09-07)
diff --git a/plone/app/portlets/exportimport/portlets.py b/plone/app/portlets/exportimport/portlets.py
index ced3e5e..913bda5 100644
--- a/plone/app/portlets/exportimport/portlets.py
+++ b/plone/app/portlets/exportimport/portlets.py
@@ -45,7 +45,9 @@
 from zope.component.interfaces import IComponentRegistry
 
 from zope.schema.interfaces import IField
+from zope.schema.interfaces import IChoice
 from zope.schema.interfaces import ICollection
+from zope.schema.interfaces import IObject
 from zope.schema.interfaces import IFromUnicode
 
 from zope.container.interfaces import INameChooser
@@ -140,8 +142,22 @@ def import_node(self, interface, child):
             return
 
         field = field.bind(self.assignment)
-        value = None
 
+        value = self.import_node_for_field(field, child)
+        
+        if field.getName() == 'root' and value in ['', '/']:
+            # these valid values don't pass validation of SearchableTextSourceBinder
+            field.set(self.assignment, value)
+        else:
+            try:
+                field.validate(value)
+            except:
+                import pdb; pdb.set_trace( )
+            field.set(self.assignment, value)
+
+    def import_node_for_field(self, field, child):
+        value = None
+        
         # If we have a collection, we need to look at the value_type.
         # We look for <element>value</element> child nodes and get the
         # value from there
@@ -151,22 +167,28 @@ def import_node(self, interface, child):
             for element in child.childNodes:
                 if element.nodeName != 'element':
                     continue
-                element_value = self.extract_text(element)
-                value.append(self.from_unicode(value_type, element_value))
-            value = self.field_typecast(field, value)
-
-        # Otherwise, just get the value of the <property /> node
+                value.append(self.import_node_for_field(value_type, element))
+        elif IObject.providedBy(field):
+            value = {}
+            for element in child.childNodes:
+                if element.nodeName != 'property':
+                    continue
+                property_key = self.extract_text(element.attributes['name'])
+                property_value = self.import_node_for_field(field.schema[property_key], element)
+                value[property_key] = property_value
+        elif IChoice.providedBy(field):
+            # Choice fields can be optional, so treat an empty contents as None
+            value = self.extract_text(child)
+            if not value:
+                value = None
+            else:
+                value = self.from_unicode(field, value)
         else:
+            # Otherwise, just get the value of the <property /> node
             value = self.extract_text(child)
             if not (field.getName() == 'root' and value in ['', '/']):
                 value = self.from_unicode(field, value)
-
-        if field.getName() == 'root' and value in ['', '/']:
-            # these valid values don't pass validation of SearchableTextSourceBinder
-            field.set(self.assignment, value)
-        else:
-            field.validate(value)
-            field.set(self.assignment, value)
+        return value
 
     def export_field(self, doc, field):
         """Turn a zope.schema field into a node and return it
@@ -178,15 +200,30 @@ def export_field(self, doc, field):
         child.setAttribute('name', field.__name__)
 
         if value is not None:
+            self.export_sub_field(doc, child, field, value)
+
+        return child
+    
+    def export_sub_field(self, doc, parent, field, value):
+        """Turn a zope.schema field into a node and return it
+        """
+        if value is not None:
             if ICollection.providedBy(field):
                 for e in value:
                     list_element = doc.createElement('element')
-                    list_element.appendChild(doc.createTextNode(str(e)))
-                    child.appendChild(list_element)
+                    self.export_sub_field(doc, list_element, field.value_type, e)
+                    parent.appendChild(list_element)
+            elif IObject.providedBy(field):
+                for name, sub_field in field.schema.namesAndDescriptions():
+                    sub_value = value.get(name)
+                    list_element = doc.createElement('property')
+                    list_element.setAttribute('name', name)
+                    self.export_sub_field(doc, list_element, sub_field, sub_value)
+                    parent.appendChild(list_element)
             else:
-                child.appendChild(doc.createTextNode(unicode(value)))
+                parent.appendChild(doc.createTextNode(unicode(value)))
 
-        return child
+        return parent
 
     def extract_text(self, node):
         node.normalize()




-------------------------------------------------------------------------------
-------------- next part --------------
A non-text attachment was scrubbed...
Name: CHANGES.log
Type: application/octet-stream
Size: 11849 bytes
Desc: not available
URL: <http://lists.plone.org/pipermail/plone-testbot/attachments/20150212/fd285199/attachment-0002.obj>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: build.log
Type: application/octet-stream
Size: 94135 bytes
Desc: not available
URL: <http://lists.plone.org/pipermail/plone-testbot/attachments/20150212/fd285199/attachment-0003.obj>


More information about the Testbot mailing list