Commit 24b3ec49 authored by Nicolas Delaby's avatar Nicolas Delaby

Refactor ERP5SyncML partialy

  - replace 4Suite by lxml
  - use new None type
  - store Partial Data in CDATA node instead a Comment node (avoid replacement of '--' by '@-@@-@')
  - list type are loads with marshaler
  - several optimisations, clean useless code
  - testERP5SyncML ran 33% faster than before.


git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@25205 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 52b3897e
This diff is collapsed.
...@@ -69,8 +69,7 @@ class VCardConduit(ERP5Conduit, SyncCode): ...@@ -69,8 +69,7 @@ class VCardConduit(ERP5Conduit, SyncCode):
portal_type = 'Person' #the VCard can just use Person portal_type = 'Person' #the VCard can just use Person
if sub_object is None: if sub_object is None:
new_object, reset_local_roles, reset_workflow = ERP5Conduit.constructContent(self, object, object_id, new_object, reset_local_roles, reset_workflow = ERP5Conduit.constructContent(self, object, object_id, portal_type)
portal_type)
else: #if the object exist, it juste must be update else: #if the object exist, it juste must be update
new_object = sub_object new_object = sub_object
#LOG('addNode', 0, 'new_object:%s, sub_object:%s' % (new_object, sub_object)) #LOG('addNode', 0, 'new_object:%s, sub_object:%s' % (new_object, sub_object))
...@@ -80,7 +79,7 @@ class VCardConduit(ERP5Conduit, SyncCode): ...@@ -80,7 +79,7 @@ class VCardConduit(ERP5Conduit, SyncCode):
simulate=simulate, simulate=simulate,
**kw) **kw)
#in a first time, conflict are not used #in a first time, conflict are not used
return {'conflict_list':None, 'object': new_object} return {'conflict_list':[], 'object': new_object}
security.declareProtected(Permissions.ModifyPortalContent, 'deleteNode') security.declareProtected(Permissions.ModifyPortalContent, 'deleteNode')
def deleteNode(self, xml=None, object=None, object_id=None, force=None, def deleteNode(self, xml=None, object=None, object_id=None, force=None,
...@@ -89,12 +88,11 @@ class VCardConduit(ERP5Conduit, SyncCode): ...@@ -89,12 +88,11 @@ class VCardConduit(ERP5Conduit, SyncCode):
A node is deleted A node is deleted
""" """
#LOG('deleteNode :', 0, 'object:%s, object_id:%s' % (str(object), str(object_id))) #LOG('deleteNode :', 0, 'object:%s, object_id:%s' % (str(object), str(object_id)))
conflict_list = []
try: try:
object._delObject(object_id) object._delObject(object_id)
except (AttributeError, KeyError): except (AttributeError, KeyError):
LOG('VCardConduit',0,'deleteNode, Unable to delete: %s' % str(object_id)) LOG('VCardConduit',0,'deleteNode, Unable to delete: %s' % str(object_id))
return conflict_list return []
security.declareProtected(Permissions.ModifyPortalContent, 'updateNode') security.declareProtected(Permissions.ModifyPortalContent, 'updateNode')
def updateNode(self, xml=None, object=None, previous_xml=None, force=0, def updateNode(self, xml=None, object=None, previous_xml=None, force=0,
...@@ -156,7 +154,7 @@ class VCardConduit(ERP5Conduit, SyncCode): ...@@ -156,7 +154,7 @@ class VCardConduit(ERP5Conduit, SyncCode):
property_value_list_well_incoded.append(property_value) property_value_list_well_incoded.append(property_value)
#elif ... put here the other encodings #elif ... put here the other encodings
else: else:
property_value_list_well_incoded=property_value_list property_value_list_well_incoded = property_value_list
return property_value_list_well_incoded return property_value_list_well_incoded
...@@ -175,7 +173,7 @@ class VCardConduit(ERP5Conduit, SyncCode): ...@@ -175,7 +173,7 @@ class VCardConduit(ERP5Conduit, SyncCode):
for vcard_line in vcard_list: for vcard_line in vcard_list:
if ':' in vcard_line: if ':' in vcard_line:
property, property_value = vcard_line.split(':') property, property_value = vcard_line.split(':')
property_value_list=property_value.split(';') property_value_list = property_value.split(';')
property_parameters_list = [] property_parameters_list = []
property_name = '' property_name = ''
if ';' in property: if ';' in property:
...@@ -195,28 +193,28 @@ class VCardConduit(ERP5Conduit, SyncCode): ...@@ -195,28 +193,28 @@ class VCardConduit(ERP5Conduit, SyncCode):
property_parameters_list = tmp property_parameters_list = tmp
#now property_parameters_list looks like : #now property_parameters_list looks like :
# [{'ENCODING':'QUOTED-PRINTABLE'}, {'CHARSET':'UTF-8'}] # [{'ENCODING':'QUOTED-PRINTABLE'}, {'CHARSET':'UTF-8'}]
property_value_list = \ property_value_list = \
self.changePropertyEncoding(property_parameters_list, self.changePropertyEncoding(property_parameters_list,
property_value_list) property_value_list)
else: else:
property_name=property property_name=property
if type(property_name) is type(u'a'): if isinstance(property_name, unicode):
property_name = property_name.encode('utf-8') property_name = property_name.encode('utf-8')
tmp=[] tmp = []
for property_value in property_value_list: for property_value in property_value_list:
if type(property_value) is type(u'a'): if isinstance(property_value, unicode):
property_value = property_value.encode('utf-8') property_value = property_value.encode('utf-8')
tmp.append(property_value) tmp.append(property_value)
property_value_list=tmp property_value_list = tmp
if property_name in convert_dict.keys(): if property_name in convert_dict.keys():
if property_name == 'N' and len(property_value_list) > 1: if property_name == 'N' and len(property_value_list) > 1:
edit_dict[convert_dict['N']]=property_value_list[0] edit_dict[convert_dict['N']] = property_value_list[0]
edit_dict[convert_dict['FN']]=property_value_list[1] edit_dict[convert_dict['FN']] = property_value_list[1]
else: else:
edit_dict[convert_dict[property_name]]=property_value_list[0] edit_dict[convert_dict[property_name]] = property_value_list[0]
#LOG('edit_dict =',0,edit_dict) #LOG('edit_dict =',0,edit_dict)
return edit_dict return edit_dict
...@@ -29,7 +29,6 @@ ...@@ -29,7 +29,6 @@
import smtplib # to send emails import smtplib # to send emails
from Publication import Publication,Subscriber from Publication import Publication,Subscriber
from Subscription import Signature from Subscription import Signature
from XMLSyncUtils import Parse
from XMLSyncUtils import XMLSyncUtils from XMLSyncUtils import XMLSyncUtils
from Conduit.ERP5Conduit import ERP5Conduit from Conduit.ERP5Conduit import ERP5Conduit
from Products.CMFCore.utils import getToolByName from Products.CMFCore.utils import getToolByName
...@@ -54,9 +53,9 @@ class PublicationSynchronization(XMLSyncUtils): ...@@ -54,9 +53,9 @@ class PublicationSynchronization(XMLSyncUtils):
""" """
LOG('PubSyncInit', INFO, 'Starting... publication: %s' % (publication.getPath())) LOG('PubSyncInit', INFO, 'Starting... publication: %s' % (publication.getPath()))
#the session id is set at the same value of those of the client #the session id is set at the same value of those of the client
subscriber.setSessionId(self.getSessionId(xml_client)) subscriber.setSessionId(self.getSessionIdFromXml(xml_client))
#same for the message id #same for the message id
subscriber.setMessageId(self.getMessageId(xml_client)) subscriber.setMessageId(self.getMessageIdFromXml(xml_client))
#at the begining of the synchronization the subscriber is not authenticated #at the begining of the synchronization the subscriber is not authenticated
subscriber.setAuthenticated(False) subscriber.setAuthenticated(False)
#the last_message_id is 1 because the message that #the last_message_id is 1 because the message that
...@@ -137,7 +136,7 @@ class PublicationSynchronization(XMLSyncUtils): ...@@ -137,7 +136,7 @@ class PublicationSynchronization(XMLSyncUtils):
if authentication_type == publication.getAuthenticationType(): if authentication_type == publication.getAuthenticationType():
authentication_format = publication.getAuthenticationFormat() authentication_format = publication.getAuthenticationFormat()
decoded = subscriber.decode(authentication_format, data) decoded = subscriber.decode(authentication_format, data)
if decoded not in ('', None) and ':' in decoded: if decoded and ':' in decoded:
(login, password) = decoded.split(':') (login, password) = decoded.split(':')
uf = self.getPortalObject().acl_users uf = self.getPortalObject().acl_users
for plugin_name, plugin in uf._getOb('plugins').listPlugins( for plugin_name, plugin in uf._getOb('plugins').listPlugins(
......
...@@ -492,10 +492,6 @@ class Signature(Folder, SyncCode): ...@@ -492,10 +492,6 @@ class Signature(Folder, SyncCode):
Set the partial string we will have to Set the partial string we will have to
deliver in the future deliver in the future
""" """
if type(xml) is type(u'a'):
xml = xml.encode('utf-8')
if xml is not None:
xml = xml.replace('@-@@-@','--') # need to put back '--'
self.partial_xml = xml self.partial_xml = xml
def getPartialXML(self): def getPartialXML(self):
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
import smtplib # to send emails import smtplib # to send emails
from Subscription import Subscription,Signature from Subscription import Subscription,Signature
from XMLSyncUtils import XMLSyncUtils, Parse from XMLSyncUtils import XMLSyncUtils
import commands import commands
from Conduit.ERP5Conduit import ERP5Conduit from Conduit.ERP5Conduit import ERP5Conduit
from AccessControl import getSecurityManager from AccessControl import getSecurityManager
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
from Products.ERP5Type.Accessor.TypeDefinition import list_types from Products.ERP5Type.Accessor.TypeDefinition import list_types
from Globals import Persistent from Globals import Persistent
import re
class SyncCode(Persistent): class SyncCode(Persistent):
""" """
...@@ -87,6 +88,7 @@ class SyncCode(Persistent): ...@@ -87,6 +88,7 @@ class SyncCode(Persistent):
tuple(XUPDATE_UPDATE) + tuple(XUPDATE_DEL) tuple(XUPDATE_UPDATE) + tuple(XUPDATE_DEL)
text_type_list = ('text','string') text_type_list = ('text','string')
list_type_list = list_types list_type_list = list_types
none_type = 'None'
force_conflict_list = ('layout_and_schema','ModificationDate') force_conflict_list = ('layout_and_schema','ModificationDate')
binary_type_list = ('image','file','document','pickle') binary_type_list = ('image','file','document','pickle')
date_type_list = ('date',) date_type_list = ('date',)
...@@ -105,18 +107,12 @@ class SyncCode(Persistent): ...@@ -105,18 +107,12 @@ class SyncCode(Persistent):
ADDABLE_PROPERTY = local_role_list + (history_tag,) + local_permission_list ADDABLE_PROPERTY = local_role_list + (history_tag,) + local_permission_list
NOT_EDITABLE_PROPERTY = ('id','object','uid','xupdate:attribute') \ NOT_EDITABLE_PROPERTY = ('id','object','uid','xupdate:attribute') \
+ XUPDATE_EL + ADDABLE_PROPERTY + XUPDATE_EL + ADDABLE_PROPERTY
sub_object_exp = "/object\[@id='.*'\]/" sub_object_exp = re.compile("/object\[@id='.*'\]/")
object_exp = "/object\[@id='.*'\]" object_exp = re.compile("/object\[@id='.*'\]")
sub_sub_object_exp = "/object\[@id='.*'\]/object\[@id='.*'\]/" attribute_type_exp = re.compile("^.*attribute::type$")
history_exp = "/%s\[@id='.*'\]" % history_tag sub_sub_object_exp = re.compile("/object\[@id='.*'\]/object\[@id='.*'\]/")
local_role_exp = "/%s\[@id='.*'\]" % local_role_tag history_exp = re.compile("/%s\[@id='.*'\]" % history_tag)
local_group_exp = "/%s\[@id='.*'\]" % local_group_tag bad_history_exp = re.compile("/%s\[@id='.*'\]/" % history_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)
#media types : #media types :
......
...@@ -40,7 +40,6 @@ from Products.ERP5SyncML import Conduit ...@@ -40,7 +40,6 @@ from Products.ERP5SyncML import Conduit
from Publication import Publication, Subscriber from Publication import Publication, Subscriber
from Products.BTreeFolder2.BTreeFolder2 import BTreeFolder2 from Products.BTreeFolder2.BTreeFolder2 import BTreeFolder2
from Subscription import Subscription from Subscription import Subscription
from XMLSyncUtils import Parse
from Products.ERP5Type import Permissions from Products.ERP5Type import Permissions
from PublicationSynchronization import PublicationSynchronization from PublicationSynchronization import PublicationSynchronization
from SubscriptionSynchronization import SubscriptionSynchronization from SubscriptionSynchronization import SubscriptionSynchronization
...@@ -490,7 +489,7 @@ class SynchronizationTool( SubscriptionSynchronization, ...@@ -490,7 +489,7 @@ class SynchronizationTool( SubscriptionSynchronization,
for conflict in conflict_list: for conflict in conflict_list:
if conflict.getObjectPath() == path: if conflict.getObjectPath() == path:
#LOG('getSynchronizationState', DEBUG, 'found a conflict: %s' % str(conflict)) #LOG('getSynchronizationState', DEBUG, 'found a conflict: %s' % str(conflict))
state_list += [[conflict.getSubscriber(),self.CONFLICT]] state_list.append([conflict.getSubscriber(), self.CONFLICT])
for domain in self.getSynchronizationList(): for domain in self.getSynchronizationList():
destination = domain.getDestinationPath() destination = domain.getDestinationPath()
#LOG('getSynchronizationState', TRACE, 'destination: %s' % str(destination)) #LOG('getSynchronizationState', TRACE, 'destination: %s' % str(destination))
...@@ -499,7 +498,6 @@ class SynchronizationTool( SubscriptionSynchronization, ...@@ -499,7 +498,6 @@ class SynchronizationTool( SubscriptionSynchronization,
if j_path.find(destination)==0: if j_path.find(destination)==0:
o_id = j_path[len(destination)+1:].split('/')[0] o_id = j_path[len(destination)+1:].split('/')[0]
#LOG('getSynchronizationState', TRACE, 'o_id: %s' % o_id) #LOG('getSynchronizationState', TRACE, 'o_id: %s' % o_id)
subscriber_list = []
if domain.domain_type==self.PUB: if domain.domain_type==self.PUB:
subscriber_list = domain.getSubscriberList() subscriber_list = domain.getSubscriberList()
else: else:
...@@ -512,13 +510,13 @@ class SynchronizationTool( SubscriptionSynchronization, ...@@ -512,13 +510,13 @@ class SynchronizationTool( SubscriptionSynchronization,
state = signature.getStatus() state = signature.getStatus()
#LOG('getSynchronizationState:', TRACE, 'sub.dest :%s, state: %s' % \ #LOG('getSynchronizationState:', TRACE, 'sub.dest :%s, state: %s' % \
#(subscriber.getSubscriptionUrl(),str(state))) #(subscriber.getSubscriptionUrl(),str(state)))
found = None found = False
# Make sure there is not already a conflict giving the state # Make sure there is not already a conflict giving the state
for state_item in state_list: for state_item in state_list:
if state_item[0]==subscriber: if state_item[0] == subscriber:
found = 1 found = True
if found is None: if not found:
state_list += [[subscriber,state]] state_list.append([subscriber, state])
return state_list return state_list
security.declareProtected(Permissions.AccessContentsInformation, security.declareProtected(Permissions.AccessContentsInformation,
......
This diff is collapsed.
# -*- coding: utf-8 -*-
############################################################################## ##############################################################################
# #
# Copyright (c) 2004 Nexedi SARL and Contributors. All Rights Reserved. # Copyright (c) 2004 Nexedi SARL and Contributors. All Rights Reserved.
# Sebastien Robin <seb@nexedi.com> # Sebastien Robin <seb@nexedi.com>
# #
...@@ -486,23 +487,23 @@ class TestERP5SyncML(TestERP5SyncMLMixin, ERP5TypeTestCase): ...@@ -486,23 +487,23 @@ class TestERP5SyncML(TestERP5SyncMLMixin, ERP5TypeTestCase):
ZopeTestCase._print('\nTest First Synchronization ') ZopeTestCase._print('\nTest First Synchronization ')
LOG('Testing... ',0,'test_08_FirstSynchronization') LOG('Testing... ',0,'test_08_FirstSynchronization')
self.login() self.login()
self.setupPublicationAndSubscription(quiet=1,run=1) self.setupPublicationAndSubscription(quiet=1, run=1)
nb_person = self.populatePersonServer(quiet=1,run=1) nb_person = self.populatePersonServer(quiet=1, run=1)
portal_sync = self.getSynchronizationTool() portal_sync = self.getSynchronizationTool()
for sub in portal_sync.getSubscriptionList(): for sub in portal_sync.getSubscriptionList():
self.assertEquals(sub.getSynchronizationType(),SyncCode.SLOW_SYNC) self.assertEquals(sub.getSynchronizationType(), SyncCode.SLOW_SYNC)
# Synchronize the first client # Synchronize the first client
nb_message1 = self.synchronize(self.sub_id1) nb_message1 = self.synchronize(self.sub_id1)
for sub in portal_sync.getSubscriptionList(): for sub in portal_sync.getSubscriptionList():
if sub.getTitle() == self.sub_id1: if sub.getTitle() == self.sub_id1:
self.assertEquals(sub.getSynchronizationType(),SyncCode.TWO_WAY) self.assertEquals(sub.getSynchronizationType(), SyncCode.TWO_WAY)
else: else:
self.assertEquals(sub.getSynchronizationType(),SyncCode.SLOW_SYNC) self.assertEquals(sub.getSynchronizationType(), SyncCode.SLOW_SYNC)
self.assertEqual(nb_message1, self.nb_message_first_synchronization) self.assertEqual(nb_message1, self.nb_message_first_synchronization)
# Synchronize the second client # Synchronize the second client
nb_message2 = self.synchronize(self.sub_id2) nb_message2 = self.synchronize(self.sub_id2)
for sub in portal_sync.getSubscriptionList(): for sub in portal_sync.getSubscriptionList():
self.assertEquals(sub.getSynchronizationType(),SyncCode.TWO_WAY) self.assertEquals(sub.getSynchronizationType(), SyncCode.TWO_WAY)
self.assertEqual(nb_message2, self.nb_message_first_synchronization) self.assertEqual(nb_message2, self.nb_message_first_synchronization)
self.checkFirstSynchronization(id=self.id1, nb_person=nb_person) self.checkFirstSynchronization(id=self.id1, nb_person=nb_person)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment