[Erp5-report] r42652 nicolas - in /erp5/trunk/utils/erp5diff: ./ interfaces/ src/ src/inter...
nobody at svn.erp5.org
nobody at svn.erp5.org
Tue Jan 25 14:17:13 CET 2011
Author: nicolas
Date: Tue Jan 25 14:17:13 2011
New Revision: 42652
URL: http://svn.erp5.org?rev=42652&view=rev
Log:
Update folder structure of egg
Remove zope.interface dependency
Use regular unittest
No change in API, no bug fix
Added:
erp5/trunk/utils/erp5diff/src/ERP5Diff.py
- copied unchanged from r36986, erp5/trunk/utils/erp5diff/ERP5Diff.py
erp5/trunk/utils/erp5diff/src/erp5diff.1
- copied unchanged from r36986, erp5/trunk/utils/erp5diff/erp5diff.1
erp5/trunk/utils/erp5diff/src/interfaces/
- copied from r36986, erp5/trunk/utils/erp5diff/interfaces/
Removed:
erp5/trunk/utils/erp5diff/ERP5Diff.py
erp5/trunk/utils/erp5diff/erp5diff
erp5/trunk/utils/erp5diff/erp5diff.1
erp5/trunk/utils/erp5diff/interfaces/
erp5/trunk/utils/erp5diff/tests.py
Modified:
erp5/trunk/utils/erp5diff/README
erp5/trunk/utils/erp5diff/setup.py
Removed: erp5/trunk/utils/erp5diff/ERP5Diff.py
URL: http://svn.erp5.org/erp5/trunk/utils/erp5diff/ERP5Diff.py?rev=42651&view=auto
==============================================================================
--- erp5/trunk/utils/erp5diff/ERP5Diff.py [utf8] (original)
+++ erp5/trunk/utils/erp5diff/ERP5Diff.py (removed)
@@ -1,742 +0,0 @@
-# -*- coding: utf-8 -*-
-##############################################################################
-#
-# Yoshinori OKUJI <yo at nexedi.com>
-#
-# Copyright (C) 2003 Nexedi SARL
-#
-# This program is Free Software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ?See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA ?02111-1307, USA.
-#
-##############################################################################
-
-from lxml import etree
-parser = etree.XMLParser(remove_blank_text=True)
-
-import sys
-import getopt
-import os
-try:
- from cStringIO import StringIO
-except ImportError:
- from StringIO import StringIO
-import re
-import codecs
-from copy import deepcopy
-from interfaces.erp5diff import IERP5Diff
-import zope.interface
-
-def isNodeEquals(old, new):
- if old.tag != new.tag or old.attrib != new.attrib:
- return False
- if old.text != new.text or old.tail != new.tail:
- return False
- if len(old) != len(new):
- return False
- for old_child, new_child in zip(old, new):
- if not isNodeEquals(old_child, new_child):
- return False
- return True
-
-class ERP5Diff:
- """
- Make a difference between two XML documents using XUpdate.
- Use some assumptions in ERP5's data representation.
-
- The strategy is:
- 1. Find a matching element among elements of the other XML document at the same depth.
- 2. Use the first matching element, even if there can be other better elements.
- 3. Assume that two elements are matching, if the tag names are identical. If either of
- them has an attribute 'id', the values of the attributes 'id' also must be identical.
- 4. Don't use xupdate:rename for elements. It should be quite rare to rename tag names
- in ERP5, and it is too complicated to support this renaming.
- 5. Ignore some types of nodes, such as EntityReference and Comment, because they are not
- used in ERP5 XML documents.
- """
-
- # Declarative interfaces
- zope.interface.implements(IERP5Diff,)
-
- __version__ = '0.8.1'
-
- def __init__(self):
- """
- Initialize itself.
- """
- self._verbose = 0
- self._result = None
- self._ns = 'http://www.xmldb.org/xupdate'
-
- def setVerbosity(self, verbose):
- """
- Set the verbosity.
- """
- self._verbose = verbose
-
- def _p(self, msg):
- """
- Print a message only if being verbose.
- """
- if self._verbose:
- sys.stderr.write(str(msg) + os.linesep)
-
- def _makeDocList(self, *args):
- """
- Make a list of Document objects.
- """
- doc_list = []
- for a in args:
- if isinstance(a, str):
- doc_list.append(etree.fromstring(a, parser))
- else:
- element_tree = etree.parse(a, parser)
- doc_list.append(element_tree.getroot())
- return doc_list
-
- def _concatPath(self, p1, p2, separator='/'):
- """
- Concatenate 'p1' and 'p2'. Add a separator between them,
- only if 'p1' does not end with a separator.
- """
- if p1.endswith(separator):
- return p1 + p2
- return p1 + separator + p2
-
- def _getResultRoot(self):
- """
- Return the root element of the result document.
- """
- return self._result
- #return self._result.getroottree()
-
- def _hasChildren(self, element):
- """
- Check whether the element has any children
- """
- return bool(len(element))
-
- def _getQName(self, element, attr_name):
- """Return qualified name compatible with xpath
- """
- if '{' == attr_name[0]:
- #This is a Qualified attribute
- index = attr_name.index('}')
- local_name = attr_name[index+1:]
- namespace_uri = attr_name[1:index]
- if namespace_uri == 'http://www.w3.org/XML/1998/namespace':
- prefix = 'xml'
- else:
- prefix = [t[0] for t in element.nsmap.iteritems() if t[1] == namespace_uri][0]
- return '%s:%s' % (prefix, local_name,), namespace_uri
- else:
- return attr_name, None
-
- def _xupdateAppendAttributes(self, attr_dict, path, nsmap=None):
- """
- Append attrib to the element at 'path'.
- """
- root = self._getResultRoot()
- append_element = etree.Element('{%s}append' % self._ns, nsmap=root.nsmap)
- append_element.attrib['select'] = path
- key_list = attr_dict.keys()
- key_list.sort()
- for name in key_list:
- val = attr_dict[name]
- attr_element = etree.Element('{%s}attribute' % self._ns, nsmap=nsmap)
- name, namespace_uri = name
- attr_element.attrib['name'] = name
- if namespace_uri:
- attr_element.attrib['namespace'] = namespace_uri
- attr_element.text = val
- append_element.append(attr_element)
- root.append(append_element)
-
- def _xupdateRemoveAttribute(self, name, path, nsmap=None):
- """
- Remove an attribute from the element at 'path'.
- """
- root = self._getResultRoot()
- remove_element = etree.Element('{%s}remove' % self._ns, nsmap=nsmap)
- remove_element.attrib['select'] = self._concatPath(path, 'attribute::' + name[0])
- root.append(remove_element)
-
- def _xupdateUpdateAttribute(self, name, val, path, nsmap=None):
- """
- Update the value of an attribute of the element at 'path'.
- """
- root = self._getResultRoot()
- update_element = etree.Element('{%s}update' % self._ns, nsmap=nsmap)
- update_element.attrib['select'] = self._concatPath(path, 'attribute::' + name[0])
- update_element.text = val
- root.append(update_element)
-
- def _xupdateRenameElement(self, name, path, nsmap=None):
- """
- Rename an existing element at 'path'.
- """
- root = self._getResultRoot()
- rename_element = etree.Element('{%s}rename' % self._ns, nsmap=nsmap)
- rename_element.attrib['select'] = path
- rename_element.text = name
- root.append(rename_element)
-
- def _xupdateUpdateElement(self, element, path, nsmap=None):
- """
- Update the contents of an element at 'path' to that of 'element'.
- """
- root = self._getResultRoot()
- update_element = etree.Element('{%s}update' % self._ns, nsmap=nsmap)
- update_element.attrib['select'] = path
- if self._hasChildren(element):
- for child in element:
- clone_node = deepcopy(child)
- update_element.append(clone_node)
- else:
- update_element.text = element.text
- root.append(update_element)
-
- def _xupdateRemoveElement(self, path, nsmap=None):
- """
- Remove an element at 'path'.
- """
- root = self._getResultRoot()
- remove_element = etree.Element('{%s}remove' % self._ns, nsmap=nsmap)
- remove_element.attrib['select'] = path
- root.append(remove_element)
-
- def _xupdateAppendElements(self, element_list, path):
- """
- Append elements to the element at 'path'.
- xupdate:append
- xupdate:insert-before
- xupdate:insert-after
- """
- root = self._getResultRoot()
- if not element_list:
- return
- parent_element = element_list[0].getparent()
- len_total_child_list = len(parent_element)
- last_append_element = None
- for element in element_list:
- # get only elements not something else (PI and comments are ignored)
- # XXX May be support of PI and Comments should be added
- # in this case fallback to previous code
- # relative_next = element.getnext()
- relative_next_list = element.xpath('following-sibling::*[1]')
- if relative_next_list:
- relative_next = relative_next_list[0]
- else:
- relative_next = None
- relative_previous_list = element.xpath('preceding-sibling::*[1]')
- if relative_previous_list:
- relative_previous = relative_previous_list[0]
- else:
- relative_previous = None
- if relative_previous in element_list:
- #reuse same container as preceding
- append_element = last_append_element
- elif relative_next is not None and relative_next not in element_list:
- append_element = etree.SubElement(root, '{%s}insert-before' % self._ns, nsmap=element.nsmap)
- path_list = self._makeRelativePathList([relative_next], before=1)
- next_sibling_path = self._concatPath(path, path_list[0])
- append_element.attrib['select'] = next_sibling_path
- elif relative_previous is not None and relative_previous not in element_list:
- append_element = etree.SubElement(root, '{%s}insert-after' % self._ns, nsmap=element.nsmap)
- path_list = self._makeRelativePathList([relative_previous])
- preceding_sibling_path = self._concatPath(path, path_list[0])
- append_element.attrib['select'] = preceding_sibling_path
- else:
- #xupdate:append by default
- append_element = etree.SubElement(root, '{%s}append' % self._ns, nsmap=element.nsmap)
- if parent_element.index(element) == 0:
- child = 'first()'
- elif parent_element.index(element) == (len_total_child_list -1):
- child = 'last()'
- else:
- child = '%d' % (len_total_child_list - parent_element.index(element) + 1)
- append_element.attrib.update({'select': path,
- 'child': child})
- child_element = etree.SubElement(append_element, '{%s}element' % self._ns, nsmap=root.nsmap)
- child_element.attrib['name'] = element.xpath('name()')
- namespace_uri = element.xpath('namespace-uri()')
- if namespace_uri:
- child_element.attrib['namespace'] = namespace_uri
- attr_map = element.attrib
- for name, value in attr_map.items():
- attr_element = etree.SubElement(child_element, '{%s}attribute' % self._ns, nsmap=child_element.nsmap)
- name, namespace_uri = self._getQName(element, name)
- attr_element.attrib['name'] = name
- if namespace_uri:
- attr_element.attrib['namespace'] = namespace_uri
- attr_element.text = value
- for child in element:
- clone_node = deepcopy(child)
- child_element.append(clone_node)
- if self._hasChildren(child_element) and element.text is not None:
- child_element[-1].tail = element.text
- else:
- child_element.text = element.text
- last_append_element = append_element
-
- def _xupdateMoveElements(self, misplaced_node_dict, path, nsmap=None):
- """
- """
- root = self._getResultRoot()
- to_remove_node_list = []
- for element_list in misplaced_node_dict.values():
- for element_tuple in element_list:
- to_remove_node_list.append(element_tuple[0])
- child_path_list = self._makeRelativePathList(to_remove_node_list)
- for child_path in child_path_list:
- to_remove_path = self._concatPath(path, child_path)
- self._xupdateRemoveElement(to_remove_path)
- for previous, element_tuple_list in misplaced_node_dict.items():
- if previous is None:
- append_element = etree.SubElement(root, '{%s}append' % self._ns, nsmap=nsmap)
- append_element.attrib['child'] = 'first()'
- else:
- append_element = etree.SubElement(root, '{%s}insert-after' % self._ns, nsmap=nsmap)
- path_list = self._makeRelativePathList([previous])
- preceding_sibling_path = self._concatPath(path, path_list[0])
- append_element.attrib['select'] = preceding_sibling_path
- for element_tuple in element_tuple_list:
- element = element_tuple[1]
- child_element = etree.SubElement(append_element, '{%s}element' % self._ns, nsmap=root.nsmap)
- child_element.attrib['name'] = element.xpath('name()')
- namespace_uri = element.xpath('namespace-uri()')
- if namespace_uri:
- child_element.attrib['namespace'] = namespace_uri
- attr_map = element.attrib
- for name, value in attr_map.items():
- attr_element = etree.SubElement(child_element, '{%s}attribute' % self._ns, nsmap=child_element.nsmap)
- name, namespace_uri = self._getQName(element, name)
- attr_element.attrib['name'] = name
- if namespace_uri:
- attr_element.attrib['namespace'] = namespace_uri
- attr_element.text = value
- for child in element:
- clone_node = deepcopy(child)
- child_element.append(clone_node)
- if self._hasChildren(child_element) and element.text is not None:
- child_element[-1].tail = element.text
- else:
- child_element.text = element.text
-
- def _testElements(self, element1, element2):
- """
- Test if two given elements are matching. Matching does not mean that they are identical.
- """
- # Make sure that they are elements.
- if type(element1) != type(element2) or type(element1) != etree._Element:
- return False
-
- if element1.tag != element2.tag:
- return False
-
- id_list = []
- for attr_map in (element1.attrib, element2.attrib):
- if 'id' in attr_map:
- id_list.append(attr_map['id'])
-
- if len(id_list) == 0:
- return True
- if len(id_list) == 1:
- return False
- return (id_list[0] == id_list[1])
-
- def _testAttributes(self, element1, element2, path):
- """
- Test attrib of two given elements. Add differences, if any.
- """
- # Make a list of dictionaries of the attributes.
- dict_list = []
- for element in (element1, element2):
- d = {}
- for name, value in element.attrib.items():
- name, namespace_uri = self._getQName(element, name)
- d[(name, namespace_uri)] = value
- dict_list.append(d)
- dict1, dict2 = dict_list
-
- # Find all added or removed or changed attrib.
- #sort key list to stick expected output
- key_list1 = dict1.keys()
- key_list1.sort()
- for name1 in key_list1:
- val1 = dict1[name1]
- if name1 in dict2:
- if val1 != dict2[name1]:
- # The value is different.
- self._xupdateUpdateAttribute(name1, dict2[name1], path, nsmap=element.nsmap)
- # Mark this attribute.
- dict2[name1] = None
- else:
- # This attribute is removed.
- self._xupdateRemoveAttribute(name1, path, nsmap=element.nsmap)
- d = {}
- for name2, val2 in dict2.iteritems():
- if val2 is not None:
- # This attribute is added.
- d[name2] = val2
- if d != {}:
- self._xupdateAppendAttributes(d, path, nsmap=element.nsmap)
-
- def _checkEmptiness(self, element):
- """
- Check if an element has Element or Text nodes
- """
- for child in element:
- if type(child) == etree._Element:
- return False
- if element.text is not None:
- return False
- return True
-
- def _checkIgnoreText(self, element):
- """
- Determine if text should be ignored by heuristics,
- because ERP5 does not define any schema at the moment.
- We ignore white-space text nodes between elements.
- pseudo code:
- tree = parse("
- <node>
- </node>")
- tree.node.text == '\n '
- """
- for child in element:
- if type(child) == etree._Element:
- return True
- if element.text is None:
- return True
- return bool(element.text.strip()) is False or False
-
- def _makeRelativePathList(self, element_list, before=0):
- """
- Make a list of relative paths from a list of elements.
- """
-
- path_list = []
- for element in element_list:
- # Check if this element has an attribute 'id'.s
- id_val = None
- attr_map = element.attrib
- for name, value in attr_map.items():
- if name in ('id', 'gid',):
- id_val = value
- id_of_id = name
- break
-
- if id_val is not None:
- # If an attribute 'id' or 'gid' is present, uses the attribute for convenience.
- position_predicate = ''
- len_all_similar_sibling = len(element.xpath('../*[@%s = "%s"]' %\
- (id_of_id, id_val)))
- if len_all_similar_sibling > 1:
- position = len_all_similar_sibling - \
- element.xpath('count(following-sibling::%s[@%s = "%s"])' %\
- (element.xpath('name()'), id_of_id, id_val),
- namespaces=element.nsmap)
- position_predicate = '[%i]' % position
- path_list.append("%s[@%s='%s']%s" % (element.xpath('name()'), id_of_id,
- id_val, position_predicate,))
- # Increase the count, for a case where other elements with the same tag name do not have
- # 'id' attrib.
- 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.xpath('name()'), position-before))
- else:
- path_list.append(element.xpath('name()'))
-
- return path_list
-
- def _aggregateElements(self, element):
- """
- Aggregate child elements of an element into a list.
- """
- return [child for child in element if type(child) == etree._Element]
-
- def _aggregateText(self, element):
- """
- Aggregate child text nodes of an element into a single string.
- """
- return '%s' % element.xpath('string(.)')
-
- def _removeStrictEqualsSubNodeList(self, old_list, new_list):
- """Remove inside list all elements which are similar
- by using c14n serialisation
- This script returns the same list of nodes whithout twins from other list
- and a dictionary with nodes whose position has changed.
- misplaced_node_dict :
- key = anchor_node (node from which the moving node_list will be append)
- value = list of tuple:
- -old_element (to remove)
- -new_element (to insert)
- """
- old_candidate_list = old_list[:]
- new_candidate_list = new_list[:]
- misplaced_node_dict = {}
- misplaced_node_dict_after = {}
- misplaced_node_dict_before = {}
- old_new_index_mapping = {}
- for old_index, old_element in enumerate(old_list):
- if old_element not in old_candidate_list:
- continue
- for new_element in new_list:
- new_index = new_list.index(new_element)
- if new_element not in new_candidate_list:
- continue
- node_equality = isNodeEquals(old_element, new_element)
- if node_equality:
- index_key_on_new_tree = new_element.getparent().index(new_element)
- old_new_index_mapping[index_key_on_new_tree] = old_element
- new_start = new_index + 1
- 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)
- if old_index == new_index:
- break
- elif old_index < new_index:
- misplaced_node_dict = misplaced_node_dict_after
- else:
- misplaced_node_dict = misplaced_node_dict_before
- previous_new_element = new_element.getprevious()
- for key, preceding_value_list in misplaced_node_dict.items():
- for element_tuple in preceding_value_list:
- if previous_new_element == element_tuple[1]:
- #reuse the same previous as much as possible
- if key is not None:
- previous_new_element = previous_new_element.getparent()[key]
- else:
- previous_new_element = None
- break
- if previous_new_element is not None:
- index_key_on_new_tree = previous_new_element.getparent().index(previous_new_element)
- else:
- index_key_on_new_tree = None
- misplaced_node_dict.setdefault(index_key_on_new_tree, []).append((old_element, new_element))
- break
-
- # Chosse the lighter one to minimise diff
- after_dict_weight = sum(len(i) for i in misplaced_node_dict_after.values())
- before_dict_weight = sum(len(i) for i in misplaced_node_dict_before.values())
- if after_dict_weight > before_dict_weight and before_dict_weight:
- misplaced_node_dict = misplaced_node_dict_before
- elif after_dict_weight <= before_dict_weight and after_dict_weight:
- misplaced_node_dict = misplaced_node_dict_after
- else:
- misplaced_node_dict = {}
-
- for k, v in misplaced_node_dict.items():
- if k in old_new_index_mapping:
- value = misplaced_node_dict[k]
- misplaced_node_dict[old_new_index_mapping[k]] = value
- if k is not None:
- #if the element which suppose to support insert-after does not exist in old_tree,
- #its just an added node not an moving
- #None means that the node will become first child, so keep it
- del misplaced_node_dict[k]
- return old_candidate_list, new_candidate_list, misplaced_node_dict
-
-
- def _compareChildNodes(self, old_element, new_element, path):
- """
- Compare children of two elements, and add differences into the result, if any.
- Call itself recursively, if these elements have grandchilden.
- """
- self._p("Comparing %s with %s at %s..." % (repr(old_element), repr(new_element), path))
-
- # First, determine if they are empty.
- old_is_empty = self._checkEmptiness(old_element)
- new_is_empty = self._checkEmptiness(new_element)
-
- if old_is_empty and new_is_empty:
- # Nothing to do.
- self._p("Both are empty.")
- pass
- else:
- # Second, determine if text should be ignored.
- old_ignore_text = self._checkIgnoreText(old_element)
- new_ignore_text = self._checkIgnoreText(new_element)
-
- if old_ignore_text != new_ignore_text:
- # This means that the semantics of this element is quite different.
- self._p("One of them has only text and the other does not, so just update all the contents.")
- self._xupdateUpdateElement(new_element, path, nsmap=new_element.nsmap)
- elif not old_ignore_text:
- # The contents are only text.
- self._p("Both have only text.")
- old_text = self._aggregateText(old_element)
- new_text = self._aggregateText(new_element)
- if old_text != new_text:
- self._p("They differ, so update the elements.")
- self._xupdateUpdateElement(new_element, path, nsmap=new_element.nsmap)
- else:
- # 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, misplaced_node_dict = self._removeStrictEqualsSubNodeList(old_list, new_list)
- path_list = self._makeRelativePathList(old_list)
- new_start = 0
- new_len = len(new_list)
- # Usefull set to detect orphan in new_list
- new_object_left_index_set = set()
- for old_node, node_path in zip(old_list, path_list):
- child_path = self._concatPath(path, node_path)
- for new_current in range(new_start, new_len):
- new_node = new_list[new_current]
- if self._testElements(old_node, new_node):
- self._testAttributes(old_node, new_node, child_path)
- self._compareChildNodes(old_node, new_node, child_path)
- new_start = new_current + 1
- if new_current in new_object_left_index_set:
- new_object_left_index_set.remove(new_current)
- break
- else:
- new_object_left_index_set.add(new_current)
- else:
- # There is no matching node. So this element must be removed.
- self._xupdateRemoveElement(child_path, old_node.nsmap)
- if new_len > new_start:
- # There are remaining nodes in the new children.
- self._xupdateAppendElements(new_list[new_start:new_len], path)
- # if New children are allready added, clean up new_object_left_index_set
- [new_object_left_index_set.remove(index)\
- for index in range(new_start, new_len) if\
- index in new_object_left_index_set]
- if new_object_left_index_set:
- self._xupdateAppendElements([new_list[index] for index \
- in new_object_left_index_set], path)
- if misplaced_node_dict:
- self._xupdateMoveElements(misplaced_node_dict, path)
-
- def compare(self, old_xml, new_xml):
- """
- Compare two given XML documents.
- If an argument is a string, it is assumed to be a XML document itself.
- Otherwise, it is assumed to be a file object which contains a XML document.
- """
- old_doc, new_doc = self._makeDocList(old_xml, new_xml)
- old_root_element = old_doc.getroottree().getroot()
- new_root_element = new_doc.getroottree().getroot()
- try:
- if self._result is not None:
- self._result = None
- self._result = etree.Element('{%s}modifications' % self._ns, nsmap={'xupdate': self._ns})
- self._result.set('version', '1.0')
- if self._testElements(old_root_element, new_root_element):
- qname = old_root_element.xpath('name()')
- self._testAttributes(old_root_element, new_root_element, '/%s' % qname)
- self._compareChildNodes(old_root_element, new_root_element, '/%s' % qname)
- else:
- # These XML documents seem to be completely different...
- if old_root_element.tag != new_root_element.tag:
- nsmap = old_root_element.nsmap
- nsmap.update(new_root_element.nsmap)
- self._xupdateRenameElement(new_root_element.xpath('name()'), '/%s' % old_root_element.xpath('name()'), nsmap)
- qname = new_root_element.xpath('name()')
- self._testAttributes(old_root_element, new_root_element, '/%s' % qname)
- self._compareChildNodes(old_root_element, new_root_element, '/%s' % qname)
- finally:
- del old_doc
- del new_doc
-
- def output(self, output_file=None):
- """
- Output the result of parsing XML documents to 'output_file'.
- If it is not specified, stdout is assumed.
- """
- if output_file is None:
- output_file = sys.stdout
- # stream
- xml = etree.tostring(self._result, encoding='utf-8', pretty_print=True)
- output_file.write(xml)
-
- def outputString(self):
- """
- Return the result as a string object.
- """
- io = StringIO()
- self.output(io)
- ret = io.getvalue()
- io.close()
- return ret
-
-def main():
- """
- The main routine of ERP5Diff.
- """
- try:
- opts, args = getopt.getopt(sys.argv[1:], "ho:v", ["help", "output=", "verbose"])
- except getopt.GetoptError, msg:
- print msg
- print "Try ``erp5diff --help'' for more information."
- sys.exit(2)
- output = None
- verbose = 0
- for o, a in opts:
- if o == "-v":
- verbose = 1
- elif o in ("-h", "--help"):
- print '''Usage: erp5diff [OPTION]... OLD_XML NEW_XML
-Make a difference between two XML documents in XUpdate format.
-
- -h, --help display this message and exit
- -o, --output=FILE output the result to the file FILE
- -v, --verbose print verbose messages
-
-Report bugs to <yo at nexedi.com>.'''
- sys.exit()
- elif o in ("-o", "--output"):
- output = a
-
- if len(args) != 2:
- if len(args) > 2:
- print "Too many arguments."
- else:
- print "Too few arguments."
- print "Try ``erp5diff --help'' for more information."
- sys.exit(2)
-
- d = ERP5Diff()
- d.setVerbosity(verbose)
-
- old_xml = open(args[0])
- new_xml = open(args[1])
- d.compare(old_xml, new_xml)
- old_xml.close()
- new_xml.close()
-
- try:
- if output is not None:
- file = open(output, 'w')
- else:
- file = None
- d.output(file)
- except:
- if output is not None:
- file.close()
- os.remove(output)
- raise
- else:
- if file is not None:
- file.close()
-
- sys.exit()
-
-if __name__ == '__main__':
- main()
Modified: erp5/trunk/utils/erp5diff/README
URL: http://svn.erp5.org/erp5/trunk/utils/erp5diff/README?rev=42652&r1=42651&r2=42652&view=diff
==============================================================================
--- erp5/trunk/utils/erp5diff/README [utf8] (original)
+++ erp5/trunk/utils/erp5diff/README [utf8] Tue Jan 25 14:17:13 2011
@@ -11,1033 +11,6 @@ Once you have installed erp5diff, you ca
$ erp5diff old.xml new.xml
See the manpage erp5diff(1) or "erp5diff --help" for more information.
-Also, you can use the module ERP5Diff from your Python script.
-Do "pydoc ERP5Diff" for more information.
-
-
-ERP5Diff Usage and its output example
-=====================================
-
-1. update the texts of the three elements
-
- >>> from ERP5Diff import ERP5Diff
- >>> erp5diff = ERP5Diff()
-
- >>> old_xml = """
- ... <erp5>
- ... <object portal_type="Person" id="313730">
- ... <description type="text">description1 --- $sdfrç_sdfsçdf_oisfsopf</description>
- ... <first_name type="string">Kamada</first_name>
- ... <last_name type="string">Kamada</last_name>
- ... <workflow_action id="edit_workflow">
- ... <time type="date">2009/08/28 19:12:24.700 GMT+9</time>
- ... </workflow_action>
- ... </object>
- ... </erp5>
- ... """
- >>> new_xml = """
- ... <erp5>
- ... <object portal_type="Person" id="313730">
- ... <description type="text">description3 çsdf__sdfççç_df___&amp;&amp;é]]]°°°°°°</description>
- ... <first_name type="string">Tatuya</first_name>
- ... <last_name type="string">Kamada</last_name>
- ... <workflow_action id="edit_workflow">
- ... <time type="date">2009/08/28 19:12:24.703 GMT+9</time>
- ... </workflow_action>
- ... </object>
- ... </erp5>
- ... """
-
- >>> erp5diff.compare(old_xml, new_xml)
- >>> erp5diff.output()
- <xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0">
- <xupdate:update select="/erp5/object[@id='313730']/description">description3 çsdf__sdfççç_df___&amp;&amp;é]]]°°°°°°</xupdate:update>
- <xupdate:update select="/erp5/object[@id='313730']/first_name">Tatuya</xupdate:update>
- <xupdate:update select="/erp5/object[@id='313730']/workflow_action[@id='edit_workflow']/time">2009/08/28 19:12:24.703 GMT+9</xupdate:update>
- </xupdate:modifications>
-
-2. update one element
-
- >>> old_xml = """
- ... <erp5>
- ... <object portal_type="Person" id="313730">
- ... <description type="text">description2éà@ $*&lt; &lt; -----</description>
- ... </object>
- ... </erp5>
- ... """
- >>> new_xml = """
- ... <erp5>
- ... <object portal_type="Person" id="313730">
- ... <description type="text">description3éà@ $*&lt; &lt; -----</description>
- ... </object>
- ... </erp5>
- ... """
- >>> erp5diff.compare(old_xml, new_xml)
- >>> erp5diff.output()
- <xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0">
- <xupdate:update select="/erp5/object[@id='313730']/description">description3éà@ $*&lt; &lt; -----</xupdate:update>
- </xupdate:modifications>
-
-3. same
-
- >>> old_xml = """
- ... <erp5>
- ... <object portal_type="Person" id="313730">
- ... <title type="string">Tatuya Kamada</title>
- ... <subject_list type="lines"><?xml version="1.0"?><marshal><list id="i2"></list></marshal></subject_list>
- ... <first_name type="string">Kamada</first_name>
- ... <last_name type="string">Tatuya</last_name>
- ... <workflow_action id="edit_workflow">
- ... <actor type="string">tatuya</actor>
- ... <time type="date">2009/08/28 19:12:26.631 GMT+9</time>
- ... </workflow_action>
- ... </object>
- ... </erp5>
- ... """
- >>> new_xml = """
- ... <erp5>
- ... <object portal_type="Person" id="313730">
- ... <title type="string">Tatuya Kamada</title>
- ... <subject_list type="lines"><?xml version="1.0"?><marshal><list id="i2"></list></marshal></subject_list>
- ... <first_name type="string">Kamada</first_name>
- ... <last_name type="string">Tatuya</last_name>
- ... <workflow_action id="edit_workflow">
- ... <actor type="string">tatuya</actor>
- ... <time type="date">2009/08/28 19:12:26.631 GMT+9</time>
- ... </workflow_action>
- ... </object>
- ... </erp5>
- ... """
- >>> erp5diff.compare(old_xml, new_xml)
- >>> erp5diff.output()
- <xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0"/>
-
-4. update the texts of the elements and remove an element
-
- >>> old_xml = """
- ... <erp5>
- ... <object portal_type="Person" id="313730">
- ... <description type="text">description2éà@ $*&lt; &lt;&lt;&lt; -----</description>
- ... <language type="string">en</language>
- ... <workflow_action id="edit_workflow">
- ... <time type="date">2009/08/28 19:12:34.424 GMT+9</time>
- ... </workflow_action>
- ... <workflow_action id="edit_workflow">
- ... <time type="date">2009/08/28 19:12:34.432 GMT+9</time>
- ... </workflow_action>
- ... </object>
- ... </erp5>
- ... """
- >>> new_xml = """
- ... <erp5>
- ... <object portal_type="Person" id="313730">
- ... <description type="text">description1 --- $sdfrç_sdfsçdf_oisfsopf</description>
- ... <language type="None"/>
- ... <workflow_action id="edit_workflow">
- ... <time type="date">2009/08/28 19:12:34.424 GMT+9</time>
- ... </workflow_action>
- ... </object>
- ... </erp5>
- ... """
- >>> erp5diff.compare(old_xml, new_xml)
- >>> erp5diff.output()
- <xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0">
- <xupdate:update select="/erp5/object[@id='313730']/description">description1 --- $sdfrç_sdfsçdf_oisfsopf</xupdate:update>
- <xupdate:update select="/erp5/object[@id='313730']/language/attribute::type">None</xupdate:update>
- <xupdate:update select="/erp5/object[@id='313730']/language"/>
- <xupdate:remove select="/erp5/object[@id='313730']/workflow_action[@id='edit_workflow'][2]"/>
- </xupdate:modifications>
-
-5. update two elements includes some symbols
-
- >>> old_xml = """
- ... <erp5>
- ... <object portal_type="Person" id="313730">
- ... <description type="text">description2éà@ $*&lt;&lt;-----&gt;&gt;</description>
- ... <language type="string">jp</language>
- ... </object>
- ... </erp5>
- ... """
- >>> new_xml = """
- ... <erp5>
- ... <object portal_type="Person" id="313730">
- ... <description type="text">description4 sdflkmooo^^^^]]]]]{{{{{{{</description>
- ... <language type="string">ca</language>
- ... </object>
- ... </erp5>
- ... """
- >>> erp5diff.compare(old_xml, new_xml)
- >>> erp5diff.output()
- <xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0">
- <xupdate:update select="/erp5/object[@id='313730']/description">description4 sdflkmooo^^^^]]]]]{{{{{{{</xupdate:update>
- <xupdate:update select="/erp5/object[@id='313730']/language">ca</xupdate:update>
- </xupdate:modifications>
-
-6. update two date element which have same id
-
- >>> old_xml = """
- ... <erp5>
- ... <object portal_type="Person" id="313730">
- ... <workflow_action id="edit_workflow">
- ... <time type="date">2009/08/28 19:12:40.550 GMT+9</time>
- ... </workflow_action>
- ... <workflow_action id="edit_workflow">
- ... <time type="date">2009/08/28 19:12:40.903 GMT+9</time>
- ... </workflow_action>
- ... <workflow_action id="edit_workflow">
- ... <time type="date">2009/08/28 19:12:40.907 GMT+9</time>
- ... </workflow_action>
- ... </object>
- ... </erp5>
- ... """
- >>> new_xml = """
- ... <erp5>
- ... <object portal_type="Person" id="313730">
- ... <workflow_action id="edit_workflow">
- ... <time type="date">2009/08/28 19:12:40.550 GMT+9</time>
- ... </workflow_action>
- ... <workflow_action id="edit_workflow">
- ... <time type="date">2009/08/28 19:12:40.905 GMT+9</time>
- ... </workflow_action>
- ... <workflow_action id="edit_workflow">
- ... <time type="date">2009/08/28 19:12:40.910 GMT+9</time>
- ... </workflow_action>
- ... </object>
- ... </erp5>
- ... """
- >>> erp5diff.compare(old_xml, new_xml)
- >>> erp5diff.output()
- <xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0">
- <xupdate:update select="/erp5/object[@id='313730']/workflow_action[@id='edit_workflow'][2]/time">2009/08/28 19:12:40.905 GMT+9</xupdate:update>
- <xupdate:update select="/erp5/object[@id='313730']/workflow_action[@id='edit_workflow'][3]/time">2009/08/28 19:12:40.910 GMT+9</xupdate:update>
- </xupdate:modifications>
-
-7. insert and remove elements
-
- >>> old_xml = """
- ... <erp5>
- ... <object portal_type="Person" id="313731">
- ... <local_role type="tokens" id="tk"><?xml version="1.0"?><marshal><tuple><string>Manager</string><string>Owner</string></tuple></marshal></local_role>
- ... <local_permission type="tokens" id="Access contents information"><?xml version="1.0"?></local_permission>
- ... <local_permission type="tokens" id="Add portal content"><?xml version="1.0"?></local_permission>
- ... <local_permission type="tokens" id="View"><?xml version="1.0"?></local_permission>
- ... </object>
- ... </erp5>
- ... """
- >>> new_xml = """
- ... <erp5>
- ... <object portal_type="Person" id="313731">
- ... <local_role type="tokens" id="tatuya"><?xml version="1.0"?><marshal><tuple><string>Owner</string></tuple></marshal></local_role>
- ... <JohnDoe>Go to the beach</JohnDoe>
- ... <local_permission type="tokens" id="Access contents information"><?xml version="1.0"?></local_permission>
- ... <local_permission type="tokens" id="Add portal content"><?xml version="1.0"?></local_permission>
- ... <local_permission type="tokens" id="Manage portal content"><?xml version="1.0"?></local_permission>
- ... <local_permission type="tokens" id="View"><?xml version="1.0"?></local_permission>
- ... </object>
- ... </erp5>
- ... """
- >>> erp5diff.compare(old_xml, new_xml)
- >>> erp5diff.output()
- <xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0">
- <xupdate:remove select="/erp5/object[@id='313731']/local_role[@id='tk']"/>
- <xupdate:append select="/erp5/object[@id='313731']" child="first()">
- <xupdate:element name="local_role"><xupdate:attribute name="type">tokens</xupdate:attribute><xupdate:attribute name="id">tatuya</xupdate:attribute><?xml version="1.0"?><marshal><tuple><string>Owner</string></tuple></marshal></xupdate:element>
- <xupdate:element name="JohnDoe">Go to the beach</xupdate:element>
- </xupdate:append>
- <xupdate:insert-before select="/erp5/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><?xml version="1.0"?></xupdate:element>
- </xupdate:insert-before>
- </xupdate:modifications>
-
-8. update xml in xml
-
- >>> old_xml = """
- ... <erp5>
- ... <object portal_type="Person" id="313731">
- ... <local_permission type="tokens" id="View"><?xml version="1.0"?><marshal><tuple><string>Manager</string><string>Owner</string></tuple></marshal></local_permission>
- ... </object>
- ... </erp5>
- ... """
- >>> new_xml = """
- ... <erp5>
- ... <object portal_type="Person" id="313731">
- ... <local_permission type="tokens" id="View"><?xml version="1.0"?><marshal><tuple><string>Assignee</string><string>Assignor</string><string>Associate</string><string>Auditor</string><string>Author</string><string>Manager</string><string>Owner</string></tuple></marshal></local_permission>
- ... </object>
- ... </erp5>
- ... """
- >>> erp5diff.compare(old_xml, new_xml)
- >>> erp5diff.output()
- <xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0">
- <xupdate:update select="/erp5/object[@id='313731']/local_permission[@id='View']"><?xml version="1.0"?><marshal><tuple><string>Assignee</string><string>Assignor</string><string>Associate</string><string>Auditor</string><string>Author</string><string>Manager</string><string>Owner</string></tuple></marshal></xupdate:update>
- </xupdate:modifications>
-
-9. rename element
-
- >>> old_xml = """
- ... <erp5>
- ... <object portal_type="Person" id="313730">
- ... <first_name type="string">Tatuya</first_name>
- ... <last_name type="string">Kamada</last_name>
- ... </object>
- ... </erp5>
- ... """
- >>> new_xml = """
- ... <erp5>
- ... <object portal_type="Person" id="313730">
- ... <given_name type="string">Tatuya</given_name>
- ... <family_name type="string">Kamada</family_name>
- ... </object>
- ... </erp5>
- ... """
- >>> erp5diff.compare(old_xml, new_xml)
- >>> erp5diff.output()
- <xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0">
- <xupdate:remove select="/erp5/object[@id='313730']/first_name"/>
- <xupdate:remove select="/erp5/object[@id='313730']/last_name"/>
- <xupdate:append select="/erp5/object[@id='313730']" child="first()">
- <xupdate:element name="given_name"><xupdate:attribute name="type">string</xupdate:attribute>Tatuya</xupdate:element>
- <xupdate:element name="family_name"><xupdate:attribute name="type">string</xupdate:attribute>Kamada</xupdate:element>
- </xupdate:append>
- </xupdate:modifications>
-
-10. rename root element
-
->>> old_xml = """
-... <erp5>
-... <object portal_type="Person" id="313730">
-... <id type="string">313730</id>
-... <title type="string">Tatuya Kamada</title>
-... </object>
-... </erp5>
-... """
->>> new_xml = """
-... <erp6>
-... <object portal_type="Person" id="313730">
-... <id type="string">313730</id>
-... <title type="string">Tatuya Kamada</title>
-... </object>
-... </erp6>
-... """
->>> erp5diff.compare(old_xml, new_xml)
->>> erp5diff.output()
-<xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0">
- <xupdate:rename select="/erp5">erp6</xupdate:rename>
-</xupdate:modifications>
-
-
-11. Update one attribute
-
->>> old_xml = """
-... <erp5>
-... <object portal_type="Person" id="313730">
-... <local_role type="tokens" id="fab"><?xml version="1.0"?><marshal><tuple><string>Owner</string></tuple></marshal></local_role>
-... </object>
-... </erp5>
-... """
->>> new_xml = """
-... <erp5>
-... <object portal_type="Person" id="313730">
-... <local_role type="ccc" id="fab"><?xml version="1.0"?><marshal><tuple><string>Owner</string></tuple></marshal></local_role>
-... </object>
-... </erp5>
-... """
->>> erp5diff.compare(old_xml, new_xml)
->>> erp5diff.output()
-<xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0">
- <xupdate:update select="/erp5/object[@id='313730']/local_role[@id='fab']/attribute::type">ccc</xupdate:update>
-</xupdate:modifications>
-
-12. Update two attribute
-
- >>> old_xml = """
- ... <erp5>
- ... <object portal_type="Person" id="313730">
- ... <local_permission attr_a='aaa' type="tokens" id="View"><?xml version="1.0"?><marshal><tuple><string>Assignee</string><string>Assignor</string><string>Associate</string><string>Auditor</string><string>Author</string><string>Manager</string><string>Owner</string></tuple></marshal></local_permission>
- ... </object>
- ... </erp5>
- ... """
- >>> new_xml = """
- ... <erp5>
- ... <object portal_type="Person" id="313730">
- ... <local_permission attr_a='ccc' type="ccc" id="View"><?xml version="1.0"?><marshal><tuple><string>Assignee</string><string>Assignor</string><string>Associate</string><string>Auditor</string><string>Author</string><string>Manager</string><string>Owner</string></tuple></marshal></local_permission>
- ... </object>
- ... </erp5>
- ... """
- >>> erp5diff.compare(old_xml, new_xml)
- >>> erp5diff.output()
- <xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0">
- <xupdate:update select="/erp5/object[@id='313730']/local_permission[@id='View']/attribute::attr_a">ccc</xupdate:update>
- <xupdate:update select="/erp5/object[@id='313730']/local_permission[@id='View']/attribute::type">ccc</xupdate:update>
- </xupdate:modifications>
-
-13. Update three attribute
-
- >>> old_xml = """
- ... <erp5>
- ... <object portal_type="Person" id="313730">
- ... <title attribute_a="aaa" attribute_b="bbb" attribute_c="ccc" type="string">Tatuya Kamada</title>
- ... </object>
- ... </erp5>
- ... """
- >>> new_xml = """
- ... <erp5>
- ... <object portal_type="Person" id="313730">
- ... <title attribute_a="nnn" attribute_b="nnn" attribute_c="nnn" type="string">Tatuya Kamada</title>
- ... </object>
- ... </erp5>
- ... """
- >>> erp5diff.compare(old_xml, new_xml)
- >>> erp5diff.output()
- <xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0">
- <xupdate:update select="/erp5/object[@id='313730']/title/attribute::attribute_a">nnn</xupdate:update>
- <xupdate:update select="/erp5/object[@id='313730']/title/attribute::attribute_b">nnn</xupdate:update>
- <xupdate:update select="/erp5/object[@id='313730']/title/attribute::attribute_c">nnn</xupdate:update>
- </xupdate:modifications>
-
-14. Remove one attribute
-
- >>> old_xml = """
- ... <erp5>
- ... <object portal_type="Person" id="313730">
- ... <first_name attribute_a="aaa" attribute_b="bbb" attribute_c="ccc" type="string">Tatuya</first_name>
- ... </object>
- ... </erp5>
- ... """
- >>> new_xml = """
- ... <erp5>
- ... <object portal_type="Person" id="313730">
- ... <first_name attribute_a="aaa" attribute_b="bbb" type="string">Tatuya</first_name>
- ... </object>
- ... </erp5>
- ... """
- >>> erp5diff.compare(old_xml, new_xml)
- >>> erp5diff.output()
- <xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0">
- <xupdate:remove select="/erp5/object[@id='313730']/first_name/attribute::attribute_c"/>
- </xupdate:modifications>
-
-15. Remove two attribute
-
- >>> old_xml = """
- ... <erp5>
- ... <object portal_type="Person" id="313730">
- ... <first_name attribute_a="aaa" attribute_b="bbb" attribute_c="ccc" type="string">Tatuya</first_name>
- ... </object>
- ... </erp5>
- ... """
- >>> new_xml = """
- ... <erp5>
- ... <object portal_type="Person" id="313730">
- ... <first_name attribute_a="aaa" type="string">Tatuya</first_name>
- ... </object>
- ... </erp5>
- ... """
- >>> erp5diff.compare(old_xml, new_xml)
- >>> erp5diff.output()
- <xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0">
- <xupdate:remove select="/erp5/object[@id='313730']/first_name/attribute::attribute_b"/>
- <xupdate:remove select="/erp5/object[@id='313730']/first_name/attribute::attribute_c"/>
- </xupdate:modifications>
-
-
-16. Remove three attribute
-
- >>> old_xml = """
- ... <erp5>
- ... <object portal_type="Person" id="313730">
- ... <first_name attribute_a="aaa" attribute_b="bbb" attribute_c="ccc" type="string">Tatuya</first_name>
- ... </object>
- ... </erp5>
- ... """
- >>> new_xml = """
- ... <erp5>
- ... <object portal_type="Person" id="313730">
- ... <first_name type="string">Tatuya</first_name>
- ... </object>
- ... </erp5>
- ... """
- >>> erp5diff.compare(old_xml, new_xml)
- >>> erp5diff.output()
- <xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0">
- <xupdate:remove select="/erp5/object[@id='313730']/first_name/attribute::attribute_a"/>
- <xupdate:remove select="/erp5/object[@id='313730']/first_name/attribute::attribute_b"/>
- <xupdate:remove select="/erp5/object[@id='313730']/first_name/attribute::attribute_c"/>
- </xupdate:modifications>
-
-17. Append one attribute
-
- >>> old_xml = """
- ... <erp5>
- ... <object portal_type="Person" id="313730">
- ... <last_name type="string">Kamada</last_name>
- ... </object>
- ... </erp5>
- ... """
- >>> new_xml = """
- ... <erp5>
- ... <object portal_type="Person" id="313730">
- ... <last_name attribute_a="aaa" type="string">Kamada</last_name>
- ... </object>
- ... </erp5>
- ... """
- >>> erp5diff.compare(old_xml, new_xml)
- >>> erp5diff.output()
- <xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0">
- <xupdate:append select="/erp5/object[@id='313730']/last_name">
- <xupdate:attribute name="attribute_a">aaa</xupdate:attribute>
- </xupdate:append>
- </xupdate:modifications>
-
-
-18. Append two attribute
-
- >>> old_xml = """
- ... <erp5>
- ... <object portal_type="Person" id="313730">
- ... <last_name type="string">Kamada</last_name>
- ... </object>
- ... </erp5>
- ... """
- >>> new_xml = """
- ... <erp5>
- ... <object portal_type="Person" id="313730">
- ... <last_name attribute_a="aaa" attribute_b="bbb" type="string">Kamada</last_name>
- ... </object>
- ... </erp5>
- ... """
- >>> erp5diff.compare(old_xml, new_xml)
- >>> erp5diff.output()
- <xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0">
- <xupdate:append select="/erp5/object[@id='313730']/last_name">
- <xupdate:attribute name="attribute_a">aaa</xupdate:attribute>
- <xupdate:attribute name="attribute_b">bbb</xupdate:attribute>
- </xupdate:append>
- </xupdate:modifications>
-
-19. Append three attribute
-
- >>> old_xml = """
- ... <erp5>
- ... <object portal_type="Person" id="313730">
- ... <last_name type="string">Kamada</last_name>
- ... </object>
- ... </erp5>
- ... """
- >>> new_xml = """
- ... <erp5>
- ... <object portal_type="Person" id="313730">
- ... <last_name attribute_a="aaa" attribute_b="bbb" attribute_c="ccc" type="string">Kamada</last_name>
- ... </object>
- ... </erp5>
- ... """
- >>> erp5diff.compare(old_xml, new_xml)
- >>> erp5diff.output()
- <xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0">
- <xupdate:append select="/erp5/object[@id='313730']/last_name">
- <xupdate:attribute name="attribute_a">aaa</xupdate:attribute>
- <xupdate:attribute name="attribute_b">bbb</xupdate:attribute>
- <xupdate:attribute name="attribute_c">ccc</xupdate:attribute>
- </xupdate:append>
- </xupdate:modifications>
-
-
-20. Remove some elements that have same id
-
-This is an unexpected case for current ERP5Diff alogrithm. So current ERP5Diff
-does not work as bellow example. This is a known bug.
-
- >>> old_xml = """
- ... <erp5>
- ... <object portal_type="Person" id="313730">
- ... <workflow_action id="edit_workflow">
- ... <time type="date">2009/08/28 19:12:34.424 GMT+9</time>
- ... </workflow_action>
- ... <workflow_action id="edit_workflow">
- ... <time type="date">2009/08/28 19:12:34.432 GMT+9</time>
- ... </workflow_action>
- ... <workflow_action id="edit_workflow">
- ... <time type="date">2009/08/28 19:12:34.434 GMT+9</time>
- ... </workflow_action>
- ... <workflow_action id="edit_workflow">
- ... <time type="date">2009/08/28 19:12:34.432 GMT+9</time>
- ... </workflow_action>
- ... <workflow_action id="edit_workflow">
- ... <time type="date">2009/08/28 19:12:34.430 GMT+9</time>
- ... </workflow_action>
- ... <workflow_action id="edit_workflow">
- ... <time type="date">2009/08/28 19:12:34.428 GMT+9</time>
- ... </workflow_action>
- ... <workflow_action id="edit_workflow">
- ... <time type="date">2009/08/28 19:12:34.426 GMT+9</time>
- ... </workflow_action>
- ... </object>
- ... </erp5>
- ... """
- >>> new_xml = """
- ... <erp5>
- ... <object portal_type="Person" id="313730">
- ... <workflow_action id="edit_workflow">
- ... <time type="date">2009/08/28 19:12:34.424 GMT+9</time>
- ... </workflow_action>
- ... <workflow_action id="edit_workflow">
- ... <time type="date">2009/08/28 19:12:34.430 GMT+9</time>
- ... </workflow_action>
- ... <workflow_action id="edit_workflow">
- ... <time type="date">2009/08/28 19:12:34.428 GMT+9</time>
- ... </workflow_action>
- ... <workflow_action id="edit_workflow">
- ... <time type="date">2009/08/28 19:12:34.426 GMT+9</time>
- ... </workflow_action>
- ... </object>
- ... </erp5>
- ... """
- >>> erp5diff.compare(old_xml, new_xml)
- >>> erp5diff.output()
- <xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0">
- <xupdate:remove select="/erp5/object[@id='313730']/workflow_action[@id='edit_workflow'][2]"/>
- <xupdate:remove select="/erp5/object[@id='313730']/workflow_action[@id='edit_workflow'][3]"/>
- <xupdate:remove select="/erp5/object[@id='313730']/workflow_action[@id='edit_workflow'][4]"/>
- </xupdate:modifications>
-
-21. Modify two elements that have same id
-
- As well as No.20. This a known bug, too.
-
- >>> old_xml = """
- ... <erp5>
- ... <object portal_type="Person" id="313730">
- ... <workflow_action id="edit_workflow">
- ... <time type="date">2009/08/28 19:12:34.424 GMT+9</time>
- ... </workflow_action>
- ... <workflow_action id="edit_workflow">
- ... <time type="date">2009/08/28 19:12:34.432 GMT+9</time>
- ... </workflow_action>
- ... <workflow_action id="edit_workflow">
- ... <time type="date">2009/08/28 19:12:34.434 GMT+9</time>
- ... </workflow_action>
- ... <workflow_action id="edit_workflow">
- ... <time type="date">2009/08/28 19:12:34.436 GMT+9</time>
- ... </workflow_action>
- ... </object>
- ... </erp5>
- ... """
- >>> new_xml = """
- ... <erp5>
- ... <object portal_type="Person" id="313730">
- ... <workflow_action id="edit_workflow">
- ... <time type="date">2009/08/28 19:12:34.424 GMT+9</time>
- ... </workflow_action>
- ... <workflow_action id="edit_workflow">
- ... <time type="date">2009/08/29 19:12:34.432 GMT+9</time>
- ... </workflow_action>
- ... <workflow_action id="edit_workflow">
- ... <time type="date">2009/08/30 19:12:34.434 GMT+9</time>
- ... </workflow_action>
- ... <workflow_action id="edit_workflow">
- ... <time type="date">2009/08/31 19:12:34.436 GMT+9</time>
- ... </workflow_action>
- ... </object>
- ... </erp5>
- ... """
- >>> erp5diff.compare(old_xml, new_xml)
- >>> erp5diff.output()
- <xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0">
- <xupdate:update select="/erp5/object[@id='313730']/workflow_action[@id='edit_workflow'][2]/time">2009/08/29 19:12:34.432 GMT+9</xupdate:update>
- <xupdate:update select="/erp5/object[@id='313730']/workflow_action[@id='edit_workflow'][3]/time">2009/08/30 19:12:34.434 GMT+9</xupdate:update>
- <xupdate:update select="/erp5/object[@id='313730']/workflow_action[@id='edit_workflow'][4]/time">2009/08/31 19:12:34.436 GMT+9</xupdate:update>
- </xupdate:modifications>
-
-22. Modify attributes of sequencial objects
-
- ERP5Diff creates target index from 0 as a XPath string, but according to the
- definition of the XPath specification <http://www.w3.org/TR/xpath>, it is wrong.
- It should be start from 1. This is a known problem.
-
- >>> old_xml = """
- ... <erp5>
- ... <object portal_type="Test">
- ... <title>A</title>
- ... </object>
- ... <object portal_type="Test">
- ... <title>A</title>
- ... </object>
- ... <object portal_type="Test">
- ... <title>A</title>
- ... </object>
- ... </erp5>
- ... """
- >>> new_xml = """
- ... <erp5>
- ... <object portal_type="Test">
- ... <title>A</title>
- ... </object>
- ... <object portal_type="Test">
- ... <title>B</title>
- ... </object>
- ... <object portal_type="Test">
- ... <title>C</title>
- ... </object>
- ... </erp5>
- ... """
- >>> erp5diff.compare(old_xml, new_xml)
- >>> erp5diff.output()
- <xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0">
- <xupdate:update select="/erp5/object[2]/title">B</xupdate:update>
- <xupdate:update select="/erp5/object[3]/title">C</xupdate:update>
- </xupdate:modifications>
-
-23. Modify nodes with Qualified Names
- ERP5Diff should create xpath valid expression with correct prefix
- >>> old_xml = """
- ... <erp5>
- ... <object portal_type="Test">
- ... <prefix:title xmlns:prefix="http://any_uri">A</prefix:title>
- ... </object>
- ... <object portal_type="Test">
- ... <prefixbis:title xmlns:prefixbis="http://any_uri_bis">A</prefixbis:title>
- ... </object>
- ... <object portal_type="Test">
- ... <againanotherprefix:title xmlns:againanotherprefix="http://any_uri">A</againanotherprefix:title>
- ... </object>
- ... </erp5>
- ... """
- >>> new_xml = """
- ... <erp5>
- ... <object portal_type="Test">
- ... <anotherprefix:title xmlns:anotherprefix="http://any_uri">A</anotherprefix:title>
- ... </object>
- ... <object portal_type="Test">
- ... <prefix:title xmlns:prefix="http://any_uri" prefix:myattr="anyvalue">B</prefix:title>
- ... </object>
- ... <object portal_type="Test">
- ... <title>A</title>
- ... </object>
- ... <erp5:object portal_type="Test" xmlns:erp5="http://www.erp5.org/namespaces/erp5_object">
- ... <title>B</title>
- ... </erp5:object>
- ... <object portal_type="Test">
- ... <prefix:title xmlns:prefix="http://any_uri">C</prefix:title>
- ... </object>
- ... </erp5>
- ... """
- >>> erp5diff.compare(old_xml, new_xml)
- >>> erp5diff.output()
- <xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0">
- <xupdate:remove xmlns:prefixbis="http://any_uri_bis" select="/erp5/object[2]/prefixbis:title"/>
- <xupdate:append xmlns:prefix="http://any_uri" select="/erp5/object[2]" child="first()">
- <xupdate:element name="prefix:title" namespace="http://any_uri"><xupdate:attribute name="prefix:myattr" namespace="http://any_uri">anyvalue</xupdate:attribute>B</xupdate:element>
- </xupdate:append>
- <xupdate:remove xmlns:againanotherprefix="http://any_uri" select="/erp5/object[3]/againanotherprefix:title"/>
- <xupdate:append select="/erp5/object[3]" child="first()">
- <xupdate:element name="title">A</xupdate:element>
- </xupdate:append>
- <xupdate:insert-after xmlns:erp5="http://www.erp5.org/namespaces/erp5_object" select="/erp5/object[3]">
- <xupdate:element name="erp5:object" namespace="http://www.erp5.org/namespaces/erp5_object">
- <xupdate:attribute name="portal_type">Test</xupdate:attribute>
- <title>B</title>
- </xupdate:element>
- <xupdate:element name="object">
- <xupdate:attribute name="portal_type">Test</xupdate:attribute>
- <prefix:title xmlns:prefix="http://any_uri">C</prefix:title>
- </xupdate:element>
- </xupdate:insert-after>
- </xupdate:modifications>
-
-24. Modify nodes with Qualified Names
- Work on Attributes specially
- >>> old_xml = """
- ... <erp5>
- ... <object portal_type="Test">
- ... <title xmlns:prefix="http://any_uri" prefix:attr="A">A</title>
- ... </object>
- ... </erp5>
- ... """
- >>> new_xml = """
- ... <erp5>
- ... <object portal_type="Test">
- ... <title xmlns:prefix="http://any_uri" prefix:attr="B">A</title>
- ... </object>
- ... </erp5>
- ... """
- >>> erp5diff.compare(old_xml, new_xml)
- >>> erp5diff.output()
- <xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0">
- <xupdate:update xmlns:prefix="http://any_uri" select="/erp5/object/title/attribute::prefix:attr">B</xupdate:update>
- </xupdate:modifications>
-
-25. Modify nodes with Qualified Names at root level
- Work on Attributes specially
- >>> old_xml = """
- ... <erp5:erp5 xmlns:erp5="http://www.erp5.org/namspaces/erp5_object" a="aaa" b="bbb">
- ... <object portal_type="Test">
- ... <title xmlns:prefix="http://any_uri" prefix:attr="A">A</title>
- ... </object>
- ... </erp5:erp5>
- ... """
- >>> new_xml = """
- ... <aaa:erp5 xmlns:aaa="http://www.erp5.org/namspaces/aaa" b="bbb" >
- ... <object portal_type="Test">
- ... <title xmlns:prefix="http://any_uri" prefix:attr="B">A</title>
- ... </object>
- ... </aaa:erp5>
- ... """
- >>> erp5diff.compare(old_xml, new_xml)
- >>> erp5diff.output()
- <xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0">
- <xupdate:rename xmlns:aaa="http://www.erp5.org/namspaces/aaa" xmlns:erp5="http://www.erp5.org/namspaces/erp5_object" select="/erp5:erp5">aaa:erp5</xupdate:rename>
- <xupdate:remove xmlns:aaa="http://www.erp5.org/namspaces/aaa" select="/aaa:erp5/attribute::a"/>
- <xupdate:update xmlns:prefix="http://any_uri" xmlns:aaa="http://www.erp5.org/namspaces/aaa" select="/aaa:erp5/object/title/attribute::prefix:attr">B</xupdate:update>
- </xupdate:modifications>
-
-26. Reorder some nodes to the end of list
- >>> old_xml = """
- ... <ul>
- ... <li>1</li>
- ... <li>2</li>
- ... <li>3</li>
- ... <li>4</li>
- ... <li>5</li>
- ... <li>6</li>
- ... <li>7</li>
- ... <li>8</li>
- ... <li>9</li>
- ... </ul>
- ... """
- >>> new_xml = """
- ... <ul>
- ... <li>1</li>
- ... <li>2</li>
- ... <li>5</li>
- ... <li>6</li>
- ... <li>7</li>
- ... <li>3</li>
- ... <li>4</li>
- ... <li>8</li>
- ... <li>9</li>
- ... </ul>
- ... """
- >>> erp5diff.compare(old_xml, new_xml)
- >>> erp5diff.output()
- <xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0">
- <xupdate:remove select="/ul/li[3]"/>
- <xupdate:remove select="/ul/li[4]"/>
- <xupdate:insert-after select="/ul/li[7]">
- <xupdate:element name="li">3</xupdate:element>
- <xupdate:element name="li">4</xupdate:element>
- </xupdate:insert-after>
- </xupdate:modifications>
-
-26. Reorder some nodes from the end of list
- >>> old_xml = """
- ... <ul>
- ... <li>1</li>
- ... <li>2</li>
- ... <li>3</li>
- ... <li>4</li>
- ... <li>5</li>
- ... <li>6</li>
- ... <li>7</li>
- ... <li>8</li>
- ... <li>9</li>
- ... </ul>
- ... """
- >>> new_xml = """
- ... <ul>
- ... <li>1</li>
- ... <li>2</li>
- ... <li>7</li>
- ... <li>8</li>
- ... <li>3</li>
- ... <li>4</li>
- ... <li>5</li>
- ... <li>6</li>
- ... <li>9</li>
- ... </ul>
- ... """
- >>> erp5diff.compare(old_xml, new_xml)
- >>> erp5diff.output()
- <xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0">
- <xupdate:remove select="/ul/li[7]"/>
- <xupdate:remove select="/ul/li[8]"/>
- <xupdate:insert-after select="/ul/li[2]">
- <xupdate:element name="li">7</xupdate:element>
- <xupdate:element name="li">8</xupdate:element>
- </xupdate:insert-after>
- </xupdate:modifications>
-
-27. Reorder some nodes at start
- >>> old_xml = """
- ... <ul>
- ... <li>1</li>
- ... <li>2</li>
- ... <li>3</li>
- ... <li>4</li>
- ... <li>5</li>
- ... <li>6</li>
- ... <li>7</li>
- ... <li>8</li>
- ... <li>9</li>
- ... </ul>
- ... """
- >>> new_xml = """
- ... <ul>
- ... <li>5</li>
- ... <li>6</li>
- ... <li>1</li>
- ... <li>2</li>
- ... <li>3</li>
- ... <li>4</li>
- ... <li>7</li>
- ... <li>8</li>
- ... <li>9</li>
- ... </ul>
- ... """
- >>> erp5diff.compare(old_xml, new_xml)
- >>> erp5diff.output()
- <xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0">
- <xupdate:remove select="/ul/li[5]"/>
- <xupdate:remove select="/ul/li[6]"/>
- <xupdate:append child="first()">
- <xupdate:element name="li">5</xupdate:element>
- <xupdate:element name="li">6</xupdate:element>
- </xupdate:append>
- </xupdate:modifications>
-
-28. Reorder some nodes at the end
- >>> old_xml = """
- ... <ul>
- ... <li>1</li>
- ... <li>2</li>
- ... <li>3</li>
- ... <li>4</li>
- ... <li>5</li>
- ... <li>6</li>
- ... <li>7</li>
- ... <li>8</li>
- ... <li>9</li>
- ... </ul>
- ... """
- >>> new_xml = """
- ... <ul>
- ... <li>1</li>
- ... <li>4</li>
- ... <li>5</li>
- ... <li>6</li>
- ... <li>7</li>
- ... <li>8</li>
- ... <li>9</li>
- ... <li>2</li>
- ... <li>3</li>
- ... </ul>
- ... """
- >>> erp5diff.compare(old_xml, new_xml)
- >>> erp5diff.output()
- <xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0">
- <xupdate:remove select="/ul/li[2]"/>
- <xupdate:remove select="/ul/li[3]"/>
- <xupdate:insert-after select="/ul/li[9]">
- <xupdate:element name="li">2</xupdate:element>
- <xupdate:element name="li">3</xupdate:element>
- </xupdate:insert-after>
- </xupdate:modifications>
-
-29. Delete children with white-space as text nodes
- >>> old_xml = """
- ... <object>
- ... <local_permission type="tokens" id="View">
- ... <marshal:marshal xmlns:marshal="http://www.erp5.org/namespaces/marshaller">
- ... <marshal:tuple>
- ... <marshal:string>Assignee</marshal:string>
- ... <marshal:string>Assignor</marshal:string>
- ... </marshal:tuple>
- ... </marshal:marshal>
- ... </local_permission>
- ... </object>
- ... """
- >>> new_xml = """
- ... <object>
- ... <local_permission type="tokens" id="View">
- ... <marshal:marshal xmlns:marshal="http://www.erp5.org/namespaces/marshaller">
- ... <marshal:tuple>
- ... </marshal:tuple>
- ... </marshal:marshal>
- ... </local_permission>
- ... </object>
- ... """
- >>> erp5diff.compare(old_xml, new_xml)
- >>> erp5diff.output()
- <xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0">
- <xupdate:remove xmlns:marshal="http://www.erp5.org/namespaces/marshaller" select="/object/local_permission[@id='View']/marshal:marshal/marshal:tuple/marshal:string[1]"/>
- <xupdate:remove xmlns:marshal="http://www.erp5.org/namespaces/marshaller" select="/object/local_permission[@id='View']/marshal:marshal/marshal:tuple/marshal:string[2]"/>
- </xupdate:modifications>
-
-29Bis. Delete childrens with auto-closing nodes
- >>> old_xml = """
- ... <object>
- ... <local_permission type="tokens" id="View">
- ... <marshal:marshal xmlns:marshal="http://www.erp5.org/namespaces/marshaller">
- ... <marshal:tuple>
- ... <marshal:string>Assignee</marshal:string>
- ... <marshal:string>Assignor</marshal:string>
- ... </marshal:tuple>
- ... </marshal:marshal>
- ... </local_permission>
- ... </object>
- ... """
- >>> new_xml = """
- ... <object>
- ... <local_permission type="tokens" id="View">
- ... <marshal:marshal xmlns:marshal="http://www.erp5.org/namespaces/marshaller">
- ... <marshal:tuple/>
- ... </marshal:marshal>
- ... </local_permission>
- ... </object>
- ... """
- >>> erp5diff.compare(old_xml, new_xml)
- >>> erp5diff.output()
- <xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0">
- <xupdate:remove xmlns:marshal="http://www.erp5.org/namespaces/marshaller" select="/object/local_permission[@id='View']/marshal:marshal/marshal:tuple/marshal:string[1]"/>
- <xupdate:remove xmlns:marshal="http://www.erp5.org/namespaces/marshaller" select="/object/local_permission[@id='View']/marshal:marshal/marshal:tuple/marshal:string[2]"/>
- </xupdate:modifications>
-
-30. Replace a node by another one following by a modification
- >>> old_xml = """
- ... <resource reference="Product Ballon de Plage a5962z">
- ... <title>Ballon de Plage</title>
- ... <reference>a5962z</reference>
- ... <sale_price>200.250000</sale_price>
- ... <purchase_price>100.250000</purchase_price>
- ... <category>ball_size/s4</category>
- ... <category>ball_size/s5</category>
- ... <category>colour/black</category>
- ... <category>colour/white</category>
- ... <category>type/product</category>
- ... </resource>
- ... """
- >>> new_xml = """
- ... <resource reference="Product Ballon de Plage a5962z">
- ... <title>Ballon de Plage</title>
- ... <reference>a5962z</reference>
- ... <sale_price>120.000000</sale_price>
- ... <ean13>1357913579130</ean13><!--replace purchase_price -->
- ... <category>ball_size/s4</category>
- ... <category>ball_size/s6</category><!--first modification to trig the bug -->
- ... <category>colour/red</category>
- ... <category>colour/white</category>
- ... <category>type/product</category>
- ... </resource>
- ... """
- >>> erp5diff.compare(old_xml, new_xml)
- >>> erp5diff.output()
- <xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0">
- <xupdate:update select="/resource/sale_price">120.000000</xupdate:update>
- <xupdate:remove select="/resource/purchase_price"/>
- <xupdate:update select="/resource/category[2]">ball_size/s6</xupdate:update>
- <xupdate:update select="/resource/category[3]">colour/red</xupdate:update>
- <xupdate:insert-before select="/resource/category[0]">
- <xupdate:element name="ean13">1357913579130</xupdate:element>
- </xupdate:insert-before>
- </xupdate:modifications>
- 2003-12-04, Yoshinori OKUJI <yo at nexedi.com>
- 2009-09-15, Tatuya Kamada <tatuya at nexedi.com>
Removed: erp5/trunk/utils/erp5diff/erp5diff
URL: http://svn.erp5.org/erp5/trunk/utils/erp5diff/erp5diff?rev=42651&view=auto
==============================================================================
--- erp5/trunk/utils/erp5diff/erp5diff [utf8] (original)
+++ erp5/trunk/utils/erp5diff/erp5diff (removed)
@@ -1,27 +0,0 @@
-#! /usr/bin/python
-
-##############################################################################
-#
-# Yoshinori OKUJI <yo at nexedi.com>
-#
-# Copyright (C) 2003 Nexedi SARL
-#
-# This program is Free Software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ?See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA ?02111-1307, USA.
-#
-##############################################################################
-
-from ERP5Diff import main
-
-main()
\ No newline at end of file
Removed: erp5/trunk/utils/erp5diff/erp5diff.1
URL: http://svn.erp5.org/erp5/trunk/utils/erp5diff/erp5diff.1?rev=42651&view=auto
==============================================================================
--- erp5/trunk/utils/erp5diff/erp5diff.1 [utf8] (original)
+++ erp5/trunk/utils/erp5diff/erp5diff.1 (removed)
@@ -1,32 +0,0 @@
-.TH ERP5DIFF 1 "4 Dec 2003" "ERP5DIFF version 0.1" Nexedi
-.SH NAME
-erp5diff \- find differences between two XML documents for ERP5
-.SH SYNOPSIS
-.B erp5diff
-[\fIoptions\fR]...
-.LP
-.SH DESCRIPTION
-ERP5Diff is a XUpdate Generator for ERP5. It takes two XML files
-as input data, and generates differences between these two XML
-documents in XUpdate language.
-.LP
-ERP5Diff depends on more or less ERP5's XML data format. So this tool
-cannot be used for general purpose, but might work if your XML files
-are similar to ERP5's.
-.SH OPTIONS
-.TP
-\fB\-o\fR, \fB\-\-output\fR=\fIFILE\fR
-Specify the output file. The standard output is used by default.
-.TP
-\fB\-h\fR, \fB\-\-help\fR
-Display the usage and exit.
-.TP
-\fB\-v\fR, \fB\-\-verbose\fR
-Print verbose messages. Only useful for debugging.
-.SH AUTHOR
-Yoshinori OKUJI <yo at nexedi.com>
-.SH "SEE ALSO"
-\fIhttp://www.xmldb.org/xupdate/index.html\fR,
-\fIhttp://www.w3.org/TR/xpath\fR,
-\fIhttp://www.w3.org/TR/REC-xml\fR,
-\fIhttp://erp5.org\fR
Modified: erp5/trunk/utils/erp5diff/setup.py
URL: http://svn.erp5.org/erp5/trunk/utils/erp5diff/setup.py?rev=42652&r1=42651&r2=42652&view=diff
==============================================================================
--- erp5/trunk/utils/erp5diff/setup.py [utf8] (original)
+++ erp5/trunk/utils/erp5diff/setup.py [utf8] Tue Jan 25 14:17:13 2011
@@ -5,27 +5,28 @@ from setuptools import setup, find_packa
import re
api_version = re.search(r'\s*__version__\s*=\s*(\S+)',
- open('ERP5Diff.py').read()).group(1).strip()
+ open('src/ERP5Diff.py').read()).group(1).strip()
revision = 0
version = '%s.%s' % (api_version.replace("'", ''), revision)
+
setup(name="erp5diff",
version=version,
description="XUpdate Generator for ERP5",
author="Yoshinori OKUJI",
author_email="yo at nexedi.com",
url="http://www.erp5.org/",
- download_url="http://www.nexedi.org/static/packages/source/erp5diff-%s.tar.gz" % version,
license="GPL",
- packages=find_packages(),
- py_modules=["ERP5Diff"],
- scripts=["erp5diff"],
- data_files=[('share/man/man1', ['erp5diff.1'])],
- install_requires=['zope.interface', 'lxml'],
+ packages=find_packages('src'),
+ package_dir={'': 'src'},
+ entry_points={'console_scripts': ["erp5diff = ERP5Diff:main"]},
+ data_files=[('share/man/man1', ['src/erp5diff.1'])],
+ install_requires=['lxml'],
classifiers=['License :: OSI Approved :: GNU General Public License (GPL)',
'Operating System :: OS Independent',
'Topic :: Text Processing :: Markup :: XML',
'Topic :: Utilities'],
include_package_data=True,
zip_safe=False,
+ test_suite='tests',
)
Removed: erp5/trunk/utils/erp5diff/tests.py
URL: http://svn.erp5.org/erp5/trunk/utils/erp5diff/tests.py?rev=42651&view=auto
==============================================================================
--- erp5/trunk/utils/erp5diff/tests.py [utf8] (original)
+++ erp5/trunk/utils/erp5diff/tests.py (removed)
@@ -1,23 +0,0 @@
-from zope import interface
-
-import zope.testing
-import unittest
-
-OPTIONFLAGS = (zope.testing.doctest.ELLIPSIS |
- zope.testing.doctest.NORMALIZE_WHITESPACE)
-
-
-def test_suite():
- doctests = ('README',)
-
- globs = dict(interface=interface)
-
- return unittest.TestSuite((
- zope.testing.doctest.DocFileSuite(doctest,
- optionflags=OPTIONFLAGS,
- globs=globs,
- ) for doctest in doctests
- ))
-
-if __name__ == '__main__':
- unittest.main(defaultTest='test_suite')
More information about the Erp5-report
mailing list