From 9f6a786b1433d8c48b1d0cec9cebde764af32f1d Mon Sep 17 00:00:00 2001 From: Sebastien Robin <seb@nexedi.com> Date: Tue, 11 May 2004 12:46:12 +0000 Subject: [PATCH] use faster xml libraries git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@868 20353a03-c40f-0410-a6d1-a30d3c3de9de --- product/ERP5SyncML/Conduit/ERP5Conduit.py | 55 ++++++++++++------- .../ERP5SyncML/PublicationSynchronization.py | 5 +- product/ERP5SyncML/Subscription.py | 6 +- .../ERP5SyncML/SubscriptionSynchronization.py | 3 +- product/ERP5SyncML/SyncCode.py | 6 ++ product/ERP5SyncML/SynchronizationTool.py | 3 +- product/ERP5SyncML/XMLSyncUtils.py | 39 ++++++------- product/ERP5SyncML/tests/testERP5SyncML.py | 9 +++ 8 files changed, 78 insertions(+), 48 deletions(-) diff --git a/product/ERP5SyncML/Conduit/ERP5Conduit.py b/product/ERP5SyncML/Conduit/ERP5Conduit.py index 54f80667af..7650e60e21 100755 --- a/product/ERP5SyncML/Conduit/ERP5Conduit.py +++ b/product/ERP5SyncML/Conduit/ERP5Conduit.py @@ -34,6 +34,7 @@ from Products.ERP5SyncML.XupdateUtils import XupdateUtils from Products.ERP5Type.Utils import convertToUpperCase from Products.ERP5Type.Accessor.TypeDefinition import list_types from xml.dom.ext.reader.Sax2 import FromXml +from xml.dom.minidom import parse, parseString from DateTime.DateTime import DateTime from email.MIMEBase import MIMEBase from email import Encoders @@ -127,6 +128,7 @@ class ERP5Conduit(XMLSyncUtilsMixin): LOG('addNode',0,'xml.nodeName: %s' % xml.nodeName) LOG('addNode',0,'getSubObjectDepth: %i' % self.getSubObjectDepth(xml)) LOG('addNode',0,'isHistoryAdd: %i' % self.isHistoryAdd(xml)) + LOG('addNode xml',0,repr(xml.toxml())) if xml.nodeName in self.XUPDATE_INSERT_OR_ADD and self.getSubObjectDepth(xml)==0: if self.isHistoryAdd(xml)!=-1: # bad hack XXX to be removed for element in self.getXupdateElementList(xml): @@ -200,11 +202,15 @@ class ERP5Conduit(XMLSyncUtilsMixin): previous_xml=sub_previous_xml, force=force, simulate=simulate, **kw) elif xml.nodeName == self.history_tag or self.isHistoryAdd(xml)>0: + LOG('addNode, workflow_history isHistoryAdd:',0,self.isHistoryAdd(xml)) # We want to add a workflow action wf_tool = getToolByName(object,'portal_workflow') wf_id = self.getAttribute(xml,'id') if wf_id is None: # History added by xupdate wf_id = self.getHistoryIdFromSelect(xml) + LOG('addNode, workflow_history id:',0,wf_id) + LOG('addNode, workflow_history xml:',0,xml.toxml()) + LOG('addNode, workflow_history xml.getElmentNodeList:',0,self.getElementNodeList(xml)) xml = self.getElementNodeList(xml)[0] LOG('addNode, workflow_history id:',0,wf_id) LOG('addNode, workflow_history xml:',0,xml) @@ -221,7 +227,8 @@ class ERP5Conduit(XMLSyncUtilsMixin): wf_tool.setStatusOf(wf_id,object,status) #else: # conflict_list += wf_conflict_list - elif xml.nodeName in self.local_role_list and not simulate: + #elif xml.nodeName in self.local_role_list or self.isLocalRole(xml)>0 and not simulate: + elif xml.nodeName in self.local_role_list: # We want to add a local role roles = self.convertXmlValue(xml.childNodes[0].data,data_type='tokens') user = self.getAttribute(xml,'id') @@ -305,9 +312,7 @@ class ERP5Conduit(XMLSyncUtilsMixin): LOG('updateNode, force: ',0,force) # we have an xupdate xml if xml.nodeName == 'xupdate:modifications': - #xupdate_utils = XupdateUtils() - xupdate_utils = self - conflict_list += xupdate_utils.applyXupdate(object=object,xupdate=xml,conduit=self, + conflict_list += self.applyXupdate(object=object,xupdate=xml,conduit=self, previous_xml=previous_xml, force=force, simulate=simulate, **kw) # we may have only the part of an xupdate @@ -501,7 +506,7 @@ class ERP5Conduit(XMLSyncUtilsMixin): security.declareProtected(Permissions.AccessContentsInformation,'isHistoryAdd') def isHistoryAdd(self, xml): - bad_list = (self.history_exp) + bad_list = (self.history_exp,) for subnode in self.getAttributeNodeList(xml): if subnode.nodeName=='select': value = subnode.nodeValue @@ -668,8 +673,12 @@ class ERP5Conduit(XMLSyncUtilsMixin): if xml is a string, convert it to a node """ if type(xml) in (type('a'),type(u'a')): - xml = FromXml(xml) - xml = xml.childNodes[1] # Because we just created a new xml + LOG('Conduit.convertToXml xml',0,repr(xml)) + if xml is type(u'a'): + xml = xml.encode('utf-8') + xml = parseString(xml) + LOG('Conduit.convertToXml not failed',0,'ok') + xml = xml.childNodes[0] # Because we just created a new xml # If we have the xml from the node erp5, we just take the subnode if xml.nodeName=='erp5': xml = self.getElementNodeList(xml)[0] @@ -693,7 +702,7 @@ class ERP5Conduit(XMLSyncUtilsMixin): """ Retrieve the portal type from an xml """ - p_type = None + p_type = None # use getElementsByTagName !!!! XXX for subnode in self.getAttributeNodeList(xml): if subnode.nodeName=='type': p_type = subnode.nodeValue @@ -801,23 +810,27 @@ class ERP5Conduit(XMLSyncUtilsMixin): from a xupdate:element returns the element as xml """ if xml.nodeName in self.XUPDATE_EL: - result = u'<' - result += xml.attributes[0].nodeValue + result = unicode('<',encoding='utf-8') + result += xml.attributes.values()[0].nodeValue for subnode in self.getElementNodeList(xml): #getElementNodeList if subnode.nodeName == 'xupdate:attribute': - result += ' ' + subnode.attributes[0].nodeValue + '=' + result += ' ' + subnode.attributes.values()[0].nodeValue + '=' result += '"' + subnode.childNodes[0].nodeValue + '"' result += '>' # Then dumps the xml and remove what we does'nt want - xml_string = StringIO() - PrettyPrint(xml,xml_string) - xml_string = xml_string.getvalue() + #xml_string = StringIO() + #PrettyPrint(xml,xml_string) + #xml_string = xml_string.getvalue() + #xml_string = unicode(xml_string,encoding='utf-8') + xml_string = xml.toxml(encoding='utf-8') xml_string = unicode(xml_string,encoding='utf-8') + #if type(xml_string) is type (u'a'): + # xml_string = xml_string.encode('utf-8') maxi = max(xml_string.find('>')+1,\ xml_string.rfind('</xupdate:attribute>')+len('</xupdate:attribute>')) result += xml_string[maxi:xml_string.find('</xupdate:element>')] - result += '</' + xml.attributes[0].nodeValue + '>' - return self.convertToXml(result) + result += '</' + xml.attributes.values()[0].nodeValue + '>' + return self.convertToXml(result.encode('utf-8')) if xml.nodeName in (self.XUPDATE_UPDATE+self.XUPDATE_DEL): result = u'<' for subnode in self.getAttributeNodeList(xml): @@ -839,9 +852,11 @@ class ERP5Conduit(XMLSyncUtilsMixin): result += ' id=%s' % select_id result += '>' # Then dumps the xml and remove what we does'nt want - xml_string = StringIO() - PrettyPrint(xml,xml_string) - xml_string = xml_string.getvalue() + #xml_string = StringIO() + #PrettyPrint(xml,xml_string) + #xml_string = xml_string.getvalue() + #xml_string = unicode(xml_string,encoding='utf-8') + xml_string = xml.toxml(encoding='utf-8') xml_string = unicode(xml_string,encoding='utf-8') maxi = xml_string.find('>')+1 result += xml_string[maxi:xml_string.find('</%s>' % xml.nodeName)] @@ -926,7 +941,7 @@ class ERP5Conduit(XMLSyncUtilsMixin): """ conflict_list = [] if type(xupdate) in (type('a'),type(u'a')): - xupdate = FromXml(xupdate) + xupdate = parseString(xupdate) for subnode in self.getElementNodeList(xupdate): sub_xupdate = self.getSubObjectXupdate(subnode) diff --git a/product/ERP5SyncML/PublicationSynchronization.py b/product/ERP5SyncML/PublicationSynchronization.py index 40bd0e3a14..0c5de33a40 100755 --- a/product/ERP5SyncML/PublicationSynchronization.py +++ b/product/ERP5SyncML/PublicationSynchronization.py @@ -30,6 +30,7 @@ import smtplib # to send emails from Publication import Publication,Subscriber from Subscription import Signature from xml.dom.ext.reader.Sax2 import FromXmlStream, FromXml +from xml.dom.minidom import parse, parseString from XMLSyncUtils import XMLSyncUtils from Conduit.ERP5Conduit import ERP5Conduit from Products.CMFCore.utils import getToolByName @@ -118,8 +119,8 @@ class PublicationSynchronization(XMLSyncUtils): if xml_client is not None: if type(xml_client) in (type('a'),type(u'a')): - xml_client = FromXml(xml_client) - first_node = xml_client.childNodes[1] + xml_client = parseString(xml_client) + first_node = xml_client.childNodes[0] if first_node.nodeName != "SyncML": LOG('PubSync',0,'This is not a SyncML Message') diff --git a/product/ERP5SyncML/Subscription.py b/product/ERP5SyncML/Subscription.py index 89654e1587..403bafbe1b 100755 --- a/product/ERP5SyncML/Subscription.py +++ b/product/ERP5SyncML/Subscription.py @@ -253,6 +253,7 @@ class Signature(SyncCode): self.setXML(self.getTempXML()) self.setTempXML(None) self.setSubscriberXupdate(None) + self.setPublisherXupdate(None) if len(self.getConflictList())>0: self.resetConflictList() elif status in (self.PUB_CONFLICT_MERGE,self.SENT): @@ -690,7 +691,6 @@ class Subscription(SyncCode, Implicit): to the query """ destination = self.getDestination() - LOG('getObjectList',0,'this is a log') query = self.getQuery() query_list = [] if type(query) is type('a'): @@ -699,9 +699,11 @@ class Subscription(SyncCode, Implicit): query_list = query_method() if callable(query): query_list = query(destination) + return filter(lambda x: x.id.find('conflict_copy')<0,query_list) + # if query is not None: # query_list = query() - return query_list +# return query_list def generateNewId(self, object=None,gid=None): """ diff --git a/product/ERP5SyncML/SubscriptionSynchronization.py b/product/ERP5SyncML/SubscriptionSynchronization.py index 643425f9bc..eef0cc988b 100755 --- a/product/ERP5SyncML/SubscriptionSynchronization.py +++ b/product/ERP5SyncML/SubscriptionSynchronization.py @@ -29,6 +29,7 @@ import smtplib # to send emails from Subscription import Subscription,Signature from xml.dom.ext.reader.Sax2 import FromXmlStream, FromXml +from xml.dom.minidom import parse, parseString from xml.dom.ext import PrettyPrint from XMLSyncUtils import XMLSyncUtils import commands @@ -95,7 +96,7 @@ class SubscriptionSynchronization(XMLSyncUtils): else: xml_client = msg if type(xml_client) in (type('a'),type(u'a')): - xml_client = FromXml(xml_client) + xml_client = parseString(xml_client) response = self.SubSyncModif(self.getSubscription(id),xml_client) diff --git a/product/ERP5SyncML/SyncCode.py b/product/ERP5SyncML/SyncCode.py index 3df415eb93..47894f5359 100755 --- a/product/ERP5SyncML/SyncCode.py +++ b/product/ERP5SyncML/SyncCode.py @@ -98,4 +98,10 @@ class SyncCode(Persistent): object_exp = "/object\[@id='.*'\]" sub_sub_object_exp = "/object\[@id='.*'\]/object\[@id='.*'\]/" history_exp = "/%s\[@id='.*'\]" % history_tag + local_role_exp = "/%s\[@id='.*'\]" % local_role_tag + local_group_exp = "/%s\[@id='.*'\]" % local_group_tag + bad_local_role_exp = "/%s\[@id='.*'\]/" % local_role_tag + bad_local_group_exp = "/%s\[@id='.*'\]/" % local_group_tag bad_history_exp = "/%s\[@id='.*'\]/" % history_tag + local_role_and_group_list = (local_group_exp,local_role_exp) + bad_local_role_and_group_list = (bad_local_group_exp,bad_local_role_exp) diff --git a/product/ERP5SyncML/SynchronizationTool.py b/product/ERP5SyncML/SynchronizationTool.py index a7920916ae..1b000d76cd 100755 --- a/product/ERP5SyncML/SynchronizationTool.py +++ b/product/ERP5SyncML/SynchronizationTool.py @@ -38,6 +38,7 @@ from Products.ERP5SyncML import _dtmldir from Publication import Publication,Subscriber from Subscription import Subscription,Signature from xml.dom.ext.reader.Sax2 import FromXmlStream, FromXml +from xml.dom.minidom import parse, parseString from Products.ERP5Type import Permissions from PublicationSynchronization import PublicationSynchronization from SubscriptionSynchronization import SubscriptionSynchronization @@ -744,7 +745,7 @@ class SynchronizationTool( UniqueObject, SimpleItem, commands.getstatusoutput('rm -f /tmp/%s.gz.gpg' % filename) # Get the target and then find the corresponding publication or # Subscription - xml = FromXml(text) + xml = parseString(text) url = '' for subnode in self.getElementNodeList(xml): if subnode.nodeName == 'SyncML': diff --git a/product/ERP5SyncML/XMLSyncUtils.py b/product/ERP5SyncML/XMLSyncUtils.py index 5d551422ab..42cbbdb0b0 100755 --- a/product/ERP5SyncML/XMLSyncUtils.py +++ b/product/ERP5SyncML/XMLSyncUtils.py @@ -30,6 +30,7 @@ import smtplib from Products.ERP5SyncML.SyncCode import SyncCode from Products.ERP5SyncML.Subscription import Signature from xml.dom.ext.reader.Sax2 import FromXml +from xml.dom.minidom import parse, parseString from cStringIO import StringIO from xml.dom.ext import PrettyPrint import random @@ -128,7 +129,6 @@ class XMLSyncUtilsMixin(SyncCode, ActiveObject): msg = header + msg LOG('SubSendMail',0,'from: %s, to: %s' % (fromaddr,toaddr)) server = smtplib.SMTP('localhost') - #server.set_debuglevel(1) server.sendmail(fromaddr, toaddr, msg) # if we want to send the email to someone else (debugging) #server.sendmail(fromaddr, "seb@localhost", msg) @@ -161,12 +161,9 @@ class XMLSyncUtilsMixin(SyncCode, ActiveObject): xml = "" xml += ' <Delete>\n' xml += ' <CmdID>%s</CmdID>\n' % cmd_id - #xml += ' <Meta><Type>%s</Type></Meta>\n' % object.portal_type xml += ' <Item>\n' xml += ' <Source><LocURI>%s</LocURI></Source>\n' % object_gid xml += ' <Data>\n' - #xml += xml_object # We have to send the data, because it allows to - # wich object to delete (it could be clever things xml += ' </Data>\n' xml += ' </Item>\n' xml += ' </Delete>\n' @@ -233,25 +230,21 @@ class XMLSyncUtilsMixin(SyncCode, ActiveObject): Return the value of the last anchor, in the alert section of the xml_stream """ - first_node = xml_stream.childNodes[1] - #if first_node.nodeName != "SyncML": - # print "This is not a SyncML message" + first_node = xml_stream.childNodes[0] # Get informations from the body client_body = first_node.childNodes[3] - #if client_body.nodeName != "SyncBody": - # print "This is not a SyncML Body" for subnode in client_body.childNodes: if subnode.nodeType == subnode.ELEMENT_NODE and subnode.nodeName == "Alert": for subnode2 in subnode.childNodes: if subnode2.nodeType == subnode2.ELEMENT_NODE and subnode2.nodeName == "Item": for subnode3 in subnode2.childNodes: if subnode3.nodeType == subnode3.ELEMENT_NODE and subnode3.nodeName == "Meta": - for subnode4 in subnode3.childNodes: + for subnode4 in subnode3.childNodes: if subnode4.nodeType == subnode4.ELEMENT_NODE and subnode4.nodeName == "Anchor": for subnode5 in subnode4.childNodes: # Get the last time we had a synchronization - if subnode5.nodeType == subnode5.ELEMENT_NODE and subnode5.nodeName == "Last": + if subnode5.nodeType == subnode5.ELEMENT_NODE and subnode5.nodeName == "Last": last_anchor = subnode5.childNodes[0].data return last_anchor @@ -260,7 +253,7 @@ class XMLSyncUtilsMixin(SyncCode, ActiveObject): Return the value of the next anchor, in the alert section of the xml_stream """ - first_node = xml_stream.childNodes[1] + first_node = xml_stream.childNodes[0] if first_node.nodeName != "SyncML": print "This is not a SyncML message" @@ -275,7 +268,7 @@ class XMLSyncUtilsMixin(SyncCode, ActiveObject): for subnode3 in subnode2.childNodes: if subnode3.nodeType == subnode3.ELEMENT_NODE and subnode3.nodeName == "Meta": for subnode4 in subnode3.childNodes: - if subnode4.nodeType == subnode4.ELEMENT_NODE and subnode4.nodeName == "Anchor": + if subnode4.nodeType == subnode4.ELEMENT_NODE and subnode4.nodeName == "Anchor": for subnode5 in subnode4.childNodes: # Get the last time we had a synchronization if subnode5.nodeType == subnode5.ELEMENT_NODE and subnode5.nodeName == "Next": @@ -320,7 +313,7 @@ class XMLSyncUtilsMixin(SyncCode, ActiveObject): Return the value of the alert code inside the full syncml message """ # Get informations from the body - first_node = xml_stream.childNodes[1] + first_node = xml_stream.childNodes[0] client_body = first_node.childNodes[3] if client_body.nodeName != "SyncBody": LOG('XMLSyncUtils.getAlertCode',0,"This is not a SyncML Body") @@ -336,7 +329,7 @@ class XMLSyncUtilsMixin(SyncCode, ActiveObject): """ Check if there's an Alert section in the xml_xtream """ - first_node = xml_stream.childNodes[1] + first_node = xml_stream.childNodes[0] client_body = first_node.childNodes[3] if client_body.nodeName != "SyncBody": print "This is not a SyncML Body" @@ -350,7 +343,7 @@ class XMLSyncUtilsMixin(SyncCode, ActiveObject): """ Check if there's an Sync section in the xml_xtream """ - first_node = xml_stream.childNodes[1] + first_node = xml_stream.childNodes[0] client_body = first_node.childNodes[3] if client_body.nodeName != "SyncBody": LOG('checkSync',0,"This is not a SyncML Body") @@ -363,7 +356,7 @@ class XMLSyncUtilsMixin(SyncCode, ActiveObject): """ Check if there's a Status section in the xml_xtream """ - first_node = xml_stream.childNodes[1] + first_node = xml_stream.childNodes[0] client_body = first_node.childNodes[3] if client_body.nodeName != "SyncBody": print "This is not a SyncML Body" @@ -379,7 +372,7 @@ class XMLSyncUtilsMixin(SyncCode, ActiveObject): then it returns the next action (could be "add", "replace", "delete"). """ - first_node = xml_stream.childNodes[1] + first_node = xml_stream.childNodes[0] client_body = first_node.childNodes[3] if client_body.nodeName != "SyncBody": print "This is not a SyncML Body" @@ -407,7 +400,7 @@ class XMLSyncUtilsMixin(SyncCode, ActiveObject): then it returns the next action (could be "add", "replace", "delete"). """ - first_node = xml_stream.childNodes[1] + first_node = xml_stream.childNodes[0] client_body = first_node.childNodes[3] if client_body.nodeName != "SyncBody": LOG('getNextSyncBodyStatus',0,"This is not a SyncML Body") @@ -505,6 +498,7 @@ class XMLSyncUtilsMixin(SyncCode, ActiveObject): """ Return childNodes that are ElementNode """ + #return node.getElementsByTagName('*') subnode_list = [] for subnode in node.childNodes or []: if subnode.nodeType == subnode.ELEMENT_NODE: @@ -526,7 +520,7 @@ class XMLSyncUtilsMixin(SyncCode, ActiveObject): Return childNodes that are ElementNode """ attribute_list = [] - for subnode in node.attributes or []: + for subnode in node.attributes.values() or []: if subnode.nodeType == subnode.ATTRIBUTE_NODE: attribute_list += [subnode] return attribute_list @@ -717,7 +711,8 @@ class XMLSyncUtilsMixin(SyncCode, ActiveObject): if partial_data != None: data_subnode = signature.getPartialXML() + partial_data LOG('SyncModif',0,'data_subnode: %s' % data_subnode) - data_subnode = FromXml(data_subnode) + #data_subnode = FromXml(data_subnode) + data_subnode = parseString(data_subnode) data_subnode = data_subnode.childNodes[1] # Because we just created a new xml # document, with childNodes[0] a DocumentType and childNodes[1] the Element Node else: @@ -879,7 +874,7 @@ class XMLSyncUtils(XMLSyncUtilsMixin): # Get the destination folder destination_path = self.unrestrictedTraverse(domain.getDestinationPath()) - first_node = remote_xml.childNodes[1] + first_node = remote_xml.childNodes[0] # Get informations from the header xml_header = first_node.childNodes[1] if xml_header.nodeName != "SyncHdr": diff --git a/product/ERP5SyncML/tests/testERP5SyncML.py b/product/ERP5SyncML/tests/testERP5SyncML.py index 30fcae4cc3..6059630543 100755 --- a/product/ERP5SyncML/tests/testERP5SyncML.py +++ b/product/ERP5SyncML/tests/testERP5SyncML.py @@ -404,6 +404,14 @@ class TestERP5SyncML(ERP5TypeTestCase): state_list = portal_sync.getSynchronizationState(person) for state in state_list: self.failUnless(state[1]==state[0].SYNCHRONIZED) + # Check for each signature that the tempXML is None + for sub in portal_sync.getSubscriptionList(): + for m in sub.getSignatureList(): + self.assertEquals(m.getTempXML(),None) + for pub in portal_sync.getPublicationList(): + for sub in pub.getSubscriberList(): + for m in sub.getSignatureList(): + self.assertEquals(m.getTempXML(),None) def checkSynchronizationStateIsConflict(self, quiet=0, run=run_all_test): portal_sync = self.getSynchronizationTool() @@ -930,6 +938,7 @@ class TestERP5SyncML(ERP5TypeTestCase): self.failUnless(person1_s.getFormat()==self.format4) self.failUnless(person1_c1.getFormat()==self.format4) self.failUnless(person1_c2.getFormat()==self.format4) + def testSynchronizeWorkflowHistory(self, quiet=0, run=run_all_test): """ -- 2.30.9