[Erp5-report] r30048 - in /erp5/trunk/utils/erp5diff: ERP5Diff.py README

nobody at svn.erp5.org nobody at svn.erp5.org
Tue Oct 27 18:32:14 CET 2009


Author: nicolas
Date: Tue Oct 27 18:32:11 2009
New Revision: 30048

URL: http://svn.erp5.org?rev=30048&view=rev
Log:
- Change output of xupdate:append by adding Implied attribute child
- Calculate position of node regarding his parent not by counting his position in child_list
- All equals nodes (c14n) are not compared anymore
- Fix last tested bugs


Modified:
    erp5/trunk/utils/erp5diff/ERP5Diff.py
    erp5/trunk/utils/erp5diff/README

Modified: erp5/trunk/utils/erp5diff/ERP5Diff.py
URL: http://svn.erp5.org/erp5/trunk/utils/erp5diff/ERP5Diff.py?rev=30048&r1=30047&r2=30048&view=diff
==============================================================================
--- erp5/trunk/utils/erp5diff/ERP5Diff.py [utf8] (original)
+++ erp5/trunk/utils/erp5diff/ERP5Diff.py [utf8] Tue Oct 27 18:32:11 2009
@@ -52,7 +52,7 @@
   # Declarative interfaces
   zope.interface.implements(IERP5Diff,)
 
-  __version__ = 0.3
+  __version__ = 0.4
 
   def __init__(self):
     """
@@ -177,53 +177,52 @@
     remove_element.attrib['select'] = path
     root.append(remove_element)
 
-  def _xupdateInsertBefore(self, element_list, path):
-    """
-      Insert elements before the element at 'path'.
-    """
-    root = self._getResultRoot()
-    insert_element = etree.Element('{%s}insert-before' % self._ns, nsmap=root.nsmap)
-    insert_element.attrib['select'] = path
+  def _xupdateAppendElements(self, element_list, path):
+    """
+      Append elements to the element at 'path'.
+      xupdate:append
+      xupdate:insert-before
+    """
+    root = self._getResultRoot()
+    if not element_list:
+      return
+    parent_element = element_list[0].getparent()
+    len_total_child_list = len(parent_element)
+    last_element = None
     for element in element_list:
-      child_element = etree.Element('{%s}element' % self._ns, nsmap=root.nsmap)
+      if parent_element.index(element) == 0:
+        append_element = etree.SubElement(root, '{%s}append' % self._ns, nsmap=root.nsmap)
+        append_element.attrib.update({'select': path,
+                                      'child': 'first()'})
+      elif parent_element.index(element) == (len_total_child_list -1):
+        append_element = etree.SubElement(root, '{%s}append' % self._ns, nsmap=root.nsmap)
+        append_element.attrib.update({'select': path,
+                                      'child': 'last()'})
+      elif element.getprevious() in element_list:
+        #reuse same container as preceding
+        append_element = last_append_element
+      elif element.getnext() not in element_list:
+        append_element = etree.SubElement(root, '{%s}insert-before' % self._ns, nsmap=root.nsmap)
+        path_list = self._makeRelativePathList([element.getnext()])
+        next_sibling_path = self._concatPath(path, path_list[0])
+        append_element.attrib['select'] = next_sibling_path
+      else:
+        raise NotImplementedError
+      child_element = etree.SubElement(append_element, '{%s}element' % self._ns, nsmap=root.nsmap)
       child_element.attrib['name'] = element.tag
       attr_map = element.attrib
       for name, value in attr_map.items():
-        attr_element = etree.Element('{%s}attribute' % self._ns, nsmap=root.nsmap)
+        attr_element = etree.SubElement(child_element, '{%s}attribute' % self._ns, nsmap=root.nsmap)
         attr_element.attrib['name'] = name
         attr_element.text = value
-        child_element.append(attr_element)
       for child in element:
         clone_node = deepcopy(child)
         child_element.append(clone_node)
       if self._hasChildren(child_element):
         child_element[-1].tail = element.text
-      insert_element.append(child_element)
-    root.append(insert_element)
-
-  def _xupdateAppendElements(self, element_list, path):
-    """
-      Append elements to the element at 'path'.
-    """
-    root = self._getResultRoot()
-    append_element = etree.Element('{%s}append' % self._ns, nsmap=root.nsmap)
-    append_element.attrib['select'] = path
-    for element in element_list:
-      child_element = etree.Element('{%s}element' % self._ns, nsmap=root.nsmap)
-      child_element.attrib['name'] = element.tag
-      attr_map = element.attrib
-      for name, value in attr_map.items():
-        attr_element = etree.Element('{%s}attribute' % self._ns, nsmap=root.nsmap)
-        attr_element.attrib['name'] = name
-        attr_element.text = value
-        child_element.append(attr_element)
-      for child in element:
-        clone_node = deepcopy(child)
-        child_element.append(clone_node)
-      if self._hasChildren(child_element):
-        child_element[-1].tail = element.text
-      append_element.append(child_element)
-    root.append(append_element)
+      else:
+        child_element.text = element.text
+      last_append_element = append_element
 
   def _testElements(self, element1, element2):
     """
@@ -304,14 +303,6 @@
     """
       Make a list of relative paths from a list of elements.
     """
-    num_map = {}
-    count_map = {}
-    for element in element_list:
-      if element.tag in num_map:
-        num_map[element.tag] += 1
-      else:
-        num_map[element.tag] = 1
-        count_map[element.tag] = 1
 
     path_list = []
     for element in element_list:
@@ -328,17 +319,18 @@
         position_predicate = ''
         len_all_similar_sibling = len(element.xpath('../*[@id = "%s"]' % id_val))
         if len_all_similar_sibling > 1:
-          position = len_all_similar_sibling - element.xpath('count(following-sibling::%s[@id = "%s"])' % (element.tag, id_val) ) 
+          position = len_all_similar_sibling - element.xpath('count(following-sibling::%s[@id = "%s"])' % (element.tag, id_val))
           position_predicate = '[%i]' % position
         path_list.append("%s[@id='%s']%s" % (element.tag, id_val, position_predicate,))
         # Increase the count, for a case where other elements with the same tag name do not have
         # 'id' attrib.
-        count_map[element.tag] += 1
-      elif num_map[element.tag] > 1:
-        path_list.append('%s[%d]' % (element.tag, count_map[element.tag]))
-        count_map[element.tag] += 1
-      else:
-        path_list.append(element.tag)
+      else:
+        len_all_similar_sibling = len(element.findall('../%s' % element.tag))
+        if len_all_similar_sibling > 1:
+          position = len_all_similar_sibling - len(list(element.itersiblings(tag=element.tag)))
+          path_list.append('%s[%d]' % (element.tag, position))
+        else:
+          path_list.append(element.tag)
 
     return path_list
 
@@ -363,6 +355,33 @@
       if type(child) == etree._Element:
         text += child.text
     return text
+
+    def _removeStrictEqualsSubNodeList(self, old_list, new_list):
+    """Remove inside list all elements which are similar
+    by using c14n serialisation
+    """
+    old_candidate_list = old_list[:]
+    new_candidate_list = new_list[:]
+    for old_element in old_list:
+      old_tree = etree.fromstring(etree.tostring(old_element)).getroottree()
+      f = StringIO()
+      old_tree.write_c14n(f)
+      old_C14n = f.getvalue()
+      for new_element in new_list:
+        if new_element not in new_candidate_list:
+          continue 
+        new_tree = etree.fromstring(etree.tostring(new_element)).getroottree()
+        f = StringIO()
+        new_tree.write_c14n(f)
+        new_C14n = f.getvalue()
+        if old_C14n == new_C14n:
+          if new_element in new_candidate_list:
+            new_candidate_list.remove(new_element)
+          if old_element in old_candidate_list:
+            old_candidate_list.remove(old_element)
+          break
+    return old_candidate_list, new_candidate_list
+
 
   def _compareChildNodes(self, old_element, new_element, path):
     """
@@ -404,8 +423,9 @@
         # The contents are elements.
         self._p("Both have elements.")
         old_list = self._aggregateElements(old_element)
+        new_list = self._aggregateElements(new_element)
+        old_list, new_list = self._removeStrictEqualsSubNodeList(old_list, new_list)
         path_list = self._makeRelativePathList(old_list)
-        new_list = self._aggregateElements(new_element)
         new_start = 0
         new_len = len(new_list)
         for old_node, node_path in zip(old_list, path_list):
@@ -415,9 +435,6 @@
             if self._testElements(old_node, new_node):
               self._testAttributes(old_node, new_node, child_path)
               self._compareChildNodes(old_node, new_node, child_path)
-              if new_current > new_start:
-                # There are skipped nodes in the new children.
-                self._xupdateInsertBefore(new_list[new_start:new_current], child_path)
               new_start = new_current + 1
               break
           else:

Modified: erp5/trunk/utils/erp5diff/README
URL: http://svn.erp5.org/erp5/trunk/utils/erp5diff/README?rev=30048&r1=30047&r2=30048&view=diff
==============================================================================
--- erp5/trunk/utils/erp5diff/README [utf8] (original)
+++ erp5/trunk/utils/erp5diff/README [utf8] Tue Oct 27 18:32:11 2009
@@ -219,6 +219,8 @@
   ...   <object portal_type="Person" id="313731">
   ...     <local_role type="tokens" id="tk">&lt;?xml version="1.0"?&gt;&lt;marshal&gt;&lt;tuple&gt;&lt;string&gt;Manager&lt;/string&gt;&lt;string&gt;Owner&lt;/string&gt;&lt;/tuple&gt;&lt;/marshal&gt;</local_role>
   ...     <local_permission type="tokens" id="Access contents information">&lt;?xml version="1.0"?&gt;</local_permission>
+  ...     <local_permission type="tokens" id="Add portal content">&lt;?xml version="1.0"?&gt;</local_permission>
+  ...     <local_permission type="tokens" id="View">&lt;?xml version="1.0"?&gt;</local_permission>
   ...   </object>
   ... </erp5>
   ... """
@@ -226,7 +228,11 @@
   ... <erp5>
   ...   <object portal_type="Person" id="313731">
   ...     <local_role type="tokens" id="tatuya">&lt;?xml version="1.0"?&gt;&lt;marshal&gt;&lt;tuple&gt;&lt;string&gt;Owner&lt;/string&gt;&lt;/tuple&gt;&lt;/marshal&gt;</local_role>
+  ...     <JohnDoe>Go to the beach</JohnDoe>
   ...     <local_permission type="tokens" id="Access contents information">&lt;?xml version="1.0"?&gt;</local_permission>
+  ...     <local_permission type="tokens" id="Add portal content">&lt;?xml version="1.0"?&gt;</local_permission>
+  ...     <local_permission type="tokens" id="Manage portal content">&lt;?xml version="1.0"?&gt;</local_permission>
+  ...     <local_permission type="tokens" id="View">&lt;?xml version="1.0"?&gt;</local_permission>
   ...   </object>
   ... </erp5>
   ... """
@@ -234,8 +240,12 @@
   >>> erp5diff.output()
   <xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0">
     <xupdate:remove select="/object[@id='313731']/local_role[@id='tk']"/>
-    <xupdate:insert-before select="/object[@id='313731']/local_permission[@id='Access contents information']">
-      <xupdate:element name="local_role"><xupdate:attribute name="type">tokens</xupdate:attribute><xupdate:attribute name="id">tatuya</xupdate:attribute>&lt;?xml version="1.0"?&gt;&lt;marshal&gt;&lt;tuple&gt;&lt;string&gt;Owner&lt;/string&gt;&lt;/tuple&gt;&lt;/marshal&gt;</xupdate:element>
+    <xupdate:append select="/object[@id='313731']" child="first()">
+        <xupdate:element name="local_role"><xupdate:attribute name="type">tokens</xupdate:attribute><xupdate:attribute name="id">tatuya</xupdate:attribute>&lt;?xml version="1.0"?&gt;&lt;marshal&gt;&lt;tuple&gt;&lt;string&gt;Owner&lt;/string&gt;&lt;/tuple&gt;&lt;/marshal&gt;</xupdate:element>                                                  
+        <xupdate:element name="JohnDoe">Go to the beach</xupdate:element>
+    </xupdate:append>
+    <xupdate:insert-before select="/object[@id='313731']/local_permission[@id='View']">
+      <xupdate:element name="local_permission"><xupdate:attribute name="type">tokens</xupdate:attribute><xupdate:attribute name="id">Manage portal content</xupdate:attribute>&lt;?xml version="1.0"?&gt;</xupdate:element>
     </xupdate:insert-before>
   </xupdate:modifications>
 
@@ -284,8 +294,10 @@
   <xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0">
     <xupdate:remove select="/object[@id='313730']/first_name"/>
     <xupdate:remove select="/object[@id='313730']/last_name"/>
-    <xupdate:append select="/object[@id='313730']">
+    <xupdate:append select="/object[@id='313730']" child="first()">
       <xupdate:element name="given_name"><xupdate:attribute name="type">string</xupdate:attribute>Tatuya</xupdate:element>
+    </xupdate:append>
+    <xupdate:append select="/object[@id='313730']" child="last()">
       <xupdate:element name="family_name"><xupdate:attribute name="type">string</xupdate:attribute>Kamada</xupdate:element>
     </xupdate:append>
   </xupdate:modifications>
@@ -589,9 +601,9 @@
   >>> erp5diff.compare(old_xml, new_xml)
   >>> erp5diff.output()
   <xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0">
-    <xupdate:remove select="/object[@id='313730']/workflow_action[2]"/>
-    <xupdate:remove select="/object[@id='313730']/workflow_action[3]"/>
-    <xupdate:remove select="/object[@id='313730']/workflow_action[4]"/>
+    <xupdate:remove select="/object[@id='313730']/workflow_action[@id='edit_workflow'][2]"/>
+    <xupdate:remove select="/object[@id='313730']/workflow_action[@id='edit_workflow'][3]"/>
+    <xupdate:remove select="/object[@id='313730']/workflow_action[@id='edit_workflow'][4]"/>
   </xupdate:modifications>
 
 21. Modify two elements that have same id




More information about the Erp5-report mailing list