Commit b14f6814 authored by Sebastien Robin's avatar Sebastien Robin

- add source_uri and target_uri fields in the dtml files

- change the subscriber property to use id, gid and rid
- encode the gid in base16
- change some parts to make VCard synchronization working
- remove some logs
- change the status implementation to use xpath expressions
- use utf-8 everywhere


git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@14954 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 6b7e714c
......@@ -139,7 +139,6 @@ class ERP5Conduit(XMLSyncUtilsMixin):
xml = self.convertToXml(xml)
if xml is None:
return {'conflict_list':conflict_list, 'object':sub_object}
#LOG('addNode',0,'xml_reconstitued: %s' % str(xml))
# In the case where this new node is a object to add
if xml.nodeName in self.XUPDATE_INSERT_OR_ADD and \
self.getSubObjectDepth(xml)==0:
......@@ -153,7 +152,6 @@ class ERP5Conduit(XMLSyncUtilsMixin):
if object_id is None:
object_id = self.getAttribute(xml,'id')
docid = self.getObjectDocid(xml)
#LOG('addNode',0,'object_id: %s' % object_id)
if object_id is not None:
if sub_object is None:
try:
......@@ -181,7 +179,6 @@ class ERP5Conduit(XMLSyncUtilsMixin):
elif xml.nodeName in self.XUPDATE_INSERT_OR_ADD \
and self.getSubObjectDepth(xml)>=1:
sub_object_id = self.getSubObjectId(xml)
#LOG('addNode',0,'getSubObjectModification number: %s' % sub_object_id)
if previous_xml is not None and sub_object_id is not None:
#LOG('addNode',0,'previous xml is not none and also sub_object_id')
# Find the previous xml corresponding to this subobject
......@@ -242,7 +239,7 @@ class ERP5Conduit(XMLSyncUtilsMixin):
sub_object = object._getOb(sub_object_id)
sub_xml = self.getSubObjectXupdate(xml)
conflict_list += self.deleteNode(xml=sub_xml,object=sub_object,
force=force, simulate=simulate, **kw)
force=force, simulate=simulate, **kw)
except (KeyError, AttributeError, TypeError):
#LOG('ERP5Conduit',0,'deleteNode, Unable to delete SubObject: %s' % str(sub_object_id))
pass
......@@ -385,7 +382,6 @@ class ERP5Conduit(XMLSyncUtilsMixin):
#subscriber_value=data)] # not needed any more
# We will now apply the argument with the method edit
if args != {} and (isConflict==0 or force) and (not simulate):
#LOG('updateNode',0,'object._edit, args: %s' % str(args))
#object._edit(**args)
self.editDocument(object=object,**args)
# It is sometimes required to do something after an edit
......@@ -394,12 +390,10 @@ class ERP5Conduit(XMLSyncUtilsMixin):
if keyword == 'object':
# This is the case where we have to call addNode
#LOG('updateNode',0,'we will add sub-object')
conflict_list += self.addNode(xml=xml, object=object, force=force,
simulate=simulate, **kw)['conflict_list']
elif keyword == self.history_tag and not simulate:
# This is the case where we have to call addNode
#LOG('updateNode',0,'we will add history')
conflict_list += self.addNode(xml=subnode,object=object,force=force,
simulate=simulate,**kw)['conflict_list']
elif keyword in (self.local_role_tag,self.local_permission_tag) and not simulate:
......@@ -433,8 +427,9 @@ class ERP5Conduit(XMLSyncUtilsMixin):
sub_xml = self.getSubObjectXupdate(xml)
#LOG('updateNode',0,'sub_xml: %s' % str(sub_xml))
# Then do the udpate
conflict_list += self.updateNode(xml=sub_xml, object=sub_object, force=force,
previous_xml=sub_previous_xml, simulate=simulate, **kw)
conflict_list += self.updateNode(xml=sub_xml, object=sub_object,
force=force, previous_xml=sub_previous_xml,
simulate=simulate, **kw)
elif previous_xml is None and xml is not None and sub_object_id is not None:
sub_object = None
try:
......@@ -470,7 +465,6 @@ class ERP5Conduit(XMLSyncUtilsMixin):
This lookd inside the args dictionnary and then
convert any unicode string to string
"""
#LOG('ERP5Conduit.getFormatedArgs',0,'args: %s' % str(args))
new_args = {}
for keyword in args.keys():
data = args[keyword]
......@@ -646,7 +640,6 @@ class ERP5Conduit(XMLSyncUtilsMixin):
xml = self.convertToXml(xml)
for subnode in self.getElementNodeList(xml):
if subnode.nodeName==self.xml_object_tag:
LOG('getSub0bjectXml: object_id:',0,object_id)
if object_id == self.getAttribute(subnode,'id'):
return subnode
return None
......@@ -700,7 +693,6 @@ class ERP5Conduit(XMLSyncUtilsMixin):
if xml is None:
return
if type(xml) in (type('a'),type(u'a')):
#LOG('Conduit.convertToXml xml',0,repr(xml))
if type(xml) is type(u'a'):
xml = xml.encode('utf-8')
xml = Parse(xml)
......@@ -981,7 +973,7 @@ class ERP5Conduit(XMLSyncUtilsMixin):
force=force, simulate=simulate, **kw)['conflict_list']
elif subnode.nodeName in self.XUPDATE_DEL:
conflict_list += conduit.deleteNode(xml=sub_xupdate, object=object, \
force=force, simulate=simulate, **kw)
force=force, simulate=simulate, **kw)
elif subnode.nodeName in self.XUPDATE_UPDATE:
conflict_list += conduit.updateNode(xml=sub_xupdate, object=object, \
force=force, simulate=simulate, **kw)
......@@ -1065,27 +1057,19 @@ class ERP5Conduit(XMLSyncUtilsMixin):
This is really usefull if you want to write your own Conduit.
"""
conflict_list = []
#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())#toxml isn't in 4Suite
#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)
#for action in self.getWorkflowActionFromXml(xml):
status = self.getStatusFromXml(xml)
#LOG('addNode, status:',0,status)
add_action = self.isWorkflowActionAddable(object=object,
status=status,wf_tool=wf_tool,
wf_id=wf_id,xml=xml)
#LOG('addNode, workflow_history add_action:',0,add_action)
if add_action and not simulate:
#LOG('addNode, setting status:',0,'ok')
wf_tool.setStatusOf(wf_id,object,status)
# Specific CPS, try to remove duplicate lines in portal_repository._histories
......@@ -1191,4 +1175,3 @@ class ERP5Conduit(XMLSyncUtilsMixin):
xml_string = buf.getvalue()
buf.close()
return xml_string
......@@ -152,7 +152,7 @@ class Publication(Subscription):
constructors = (addPublication,)
# Constructor
def __init__(self, id, title, publication_url, destination_path,
def __init__(self, id, title, publication_url, destination_path, source_uri,
query, xml_mapping, conduit, gpg_key, id_generator, gid_generator,
media_type, auth_required=False, authentication_format='',
authentication_type=''):
......@@ -162,6 +162,7 @@ class Publication(Subscription):
self.id = id
self.publication_url = publication_url
self.destination_path = destination_path
self.setSourceURI(source_uri)
self.setQuery(query)
self.xml_mapping = xml_mapping
#self.list_subscribers = PersistentMapping()
......
......@@ -110,7 +110,7 @@ class PublicationSynchronization(XMLSyncUtils):
if authentication_format == publication.getAuthenticationFormat():
if authentication_type == publication.getAuthenticationType():
decoded = subscriber.decode(authentication_format, data)
if decoded not in ('', None) and decoded.__contains__(':'):
if decoded not in ('', None) and ':' in decoded:
(login, password) = decoded.split(':')
uf = self.getPortalObject().acl_users
for plugin_name, plugin in uf._getOb('plugins').listPlugins(
......@@ -124,6 +124,8 @@ class PublicationSynchronization(XMLSyncUtils):
newSecurityManager(None, user)
subscriber.setUser(login)
break
else:
auth_code=self.UNAUTHORIZED
#in all others cases, the auth_code is set to UNAUTHORIZED
......@@ -148,6 +150,13 @@ class PublicationSynchronization(XMLSyncUtils):
subscriber.getSubscriptionUrl(), publication.getPublicationUrl(),
subscriber.getLastAnchor(), subscriber.getNextAnchor()))
cmd_id += 1
else:
# chal message
xml(self.SyncMLChal(cmd_id, "SyncHdr",
publication.getPublicationUrl(), subscriber.getSubscriptionUrl(),
publication.getAuthenticationFormat(),
publication.getAuthenticationType(), self.AUTH_REQUIRED))
cmd_id += 1
xml(' </SyncBody>\n')
xml('</SyncML>\n')
xml_a = ''.join(xml_list)
......
This diff is collapsed.
......@@ -49,7 +49,7 @@ class SubscriptionSynchronization(XMLSyncUtils):
# syncml header
xml(self.SyncMLHeader(subscription.incrementSessionId(),
subscription.incrementMessageId(), subscription.getPublicationUrl(),
subscription.getSubscriptionUrl()))
subscription.getSubscriptionUrl(), source_name=subscription.getLogin()))
# syncml body
xml(' <SyncBody>\n')
......@@ -59,16 +59,15 @@ class SubscriptionSynchronization(XMLSyncUtils):
# alert message
xml(self.SyncMLAlert(cmd_id, subscription.getSynchronizationType(),
subscription.getPublicationUrl(),
subscription.getDestinationPath(),
subscription.getTargetURI(),
subscription.getSourceURI(),
subscription.getLastAnchor(),
subscription.getNextAnchor()))
cmd_id += 1
xml(' <Put>\n')
xml(' <CmdID>%s</CmdID>\n' % cmd_id)
cmd_id += 1
xml(' </Put>\n')
syncml_put = self.SyncMLPut(cmd_id, subscription)
if syncml_put not in ('', None):
xml(syncml_put)
cmd_id += 1
xml(' </SyncBody>\n')
xml('</SyncML>\n')
xml_a = ''.join(xml_list)
......@@ -79,20 +78,17 @@ class SubscriptionSynchronization(XMLSyncUtils):
return {'has_response':1,'xml':xml_a}
def SubSync(self, id, msg=None, RESPONSE=None):
def SubSync(self, subscription, msg=None, RESPONSE=None):
"""
This is the synchronization method for the client
"""
#LOG('SubSync',0,'starting... id: %s' % str(id))
#LOG('SubSync',0,'starting... msg: %s' % str(msg))
response = None #check if subsync replies to this messages
subscription = self.getSubscription(id)
if msg==None and (subscription.getSubscriptionUrl()).find('file')>=0:
msg = self.readResponse(sync_id=id,
msg = self.readResponse(sync_id=subscription.getSourceURI(),
from_url=subscription.getSubscriptionUrl())
if msg==None:
response = self.SubSyncInit(self.getSubscription(id))
response = self.SubSyncInit(subscription)
else:
xml_client = msg
if isinstance(xml_client, str) or isinstance(xml_client, unicode):
......@@ -105,21 +101,24 @@ class SubscriptionSynchronization(XMLSyncUtils):
if status_code == self.AUTH_REQUIRED:
if self.checkChal(xml_client):
authentication_format, authentication_type = self.getChal(xml_client)
subscription.setAuthenticationFormat(authentication_format)
subscription.setAuthenticationType(authentication_type)
#LOG('auth_required :',0, 'format:%s, type:%s' % (authentication_format, authentication_type))
if authentication_format is not None and \
authentication_type is not None:
subscription.setAuthenticationFormat(authentication_format)
subscription.setAuthenticationType(authentication_type)
else:
raise ValueError, "Sorry, the server chalenge for an \
authentication, but the authentication format is not find"
#LOG('readResponse', 0, 'Authentication required')
response = self.SubSyncCred(id, xml_client)
response = self.SubSyncCred(subscription, xml_client)
elif status_code == self.UNAUTHORIZED:
#LOG('readResponse', 0, 'Bad authentication')
LOG('readResponse', 0, 'Bad authentication')
return {'has_response':0,'xml':xml_client}
else:
response = self.SubSyncModif(self.getSubscription(id), xml_client)
response = self.SubSyncModif(subscription, xml_client)
else:
response = self.SubSyncModif(self.getSubscription(id), xml_client)
response = self.SubSyncModif(subscription, xml_client)
if RESPONSE is not None:
......@@ -127,43 +126,43 @@ class SubscriptionSynchronization(XMLSyncUtils):
else:
return response
def SubSyncCred (self, id, msg=None, RESPONSE=None):
def SubSyncCred (self, subscription, msg=None, RESPONSE=None):
"""
This method send crendentials
"""
#LOG('SubSyncCred',0,'starting... id: %s' % str(id))
#LOG('SubSyncCred',0,'starting... msg: %s' % str(msg))
cmd_id = 1 # specifies a SyncML message-unique command identifier
subscription = self.getSubscription(id)
xml_list = []
xml = xml_list.append
xml('<SyncML>\n')
# syncml header
data = "%s:%s" % (subscription.getLogin(), subscription.getPassword())
data=subscription.encode(subscription.getAuthenticationFormat(), data)
xml(self.SyncMLHeader(subscription.getSessionId(),
subscription.incrementMessageId(), subscription.getPublicationUrl(),
subscription.getSubscriptionUrl(), dataCred=data,
xml(self.SyncMLHeader(
subscription.incrementSessionId(),
subscription.incrementMessageId(),
subscription.getPublicationUrl(),
subscription.getSubscriptionUrl(),
source_name=subscription.getLogin(),
dataCred=data,
authentication_format=subscription.getAuthenticationFormat(),
authentication_type=subscription.getAuthenticationType()))
# syncml body
xml(' <SyncBody>\n')
# We have to set every object as NOT_SYNCHRONIZED
subscription.startSynchronization()
# alert message
xml(self.SyncMLAlert(cmd_id, subscription.getSynchronizationType(),
subscription.getPublicationUrl(),
subscription.getDestinationPath(),
subscription.getTargetURI(),
subscription.getSourceURI(),
subscription.getLastAnchor(),
subscription.getNextAnchor()))
cmd_id += 1
xml(' <Put>\n')
xml(' <CmdID>%s</CmdID>\n' % cmd_id)
xml(self.SyncMLPut(cmd_id, subscription))
cmd_id += 1
xml(' </Put>\n')
xml(' <Final/>\n')
xml(' </SyncBody>\n')
xml('</SyncML>\n')
xml_a = ''.join(xml_list)
......
......@@ -41,6 +41,8 @@ class SyncCode(Persistent):
# SyncML Status Codes
SUCCESS = 200
ITEM_ADDED = 201
CHUNK_OK = 214
CONFLICT = 409 # A conflict is detected
CONFLICT_MERGE = 207 # We have merged the two versions, sending
......
This diff is collapsed.
This diff is collapsed.
......@@ -67,6 +67,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
<input type="text" name="destination_path" value="<dtml-var getDestinationPath>" size="40" />
</td>
</tr>
<tr>
<td align="left" valign="top">
<div class="form-label">
Source URI
</label></div>
</td>
<td align="left" valign="top">
<input type="text" name="source_uri" size="40" value="<dtml-var getSourceURI>" />
</td>
</tr>
<tr>
<td align="left" valign="top">
<div class="form-label">
......
......@@ -77,6 +77,26 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
<input type="text" name="destination_path" value="<dtml-var getDestinationPath>" size="40" />
</td>
</tr>
<tr>
<td align="left" valign="top">
<div class="form-label">
Source URI
</label></div>
</td>
<td align="left" valign="top">
<input type="text" name="source_uri" size="40" value="<dtml-var getSourceURI>" />
</td>
</tr>
<tr>
<td align="left" valign="top">
<div class="form-label">
Target URI
</label></div>
</td>
<td align="left" valign="top">
<input type="text" name="target_uri" size="40" value="<dtml-var getTargetURI>" />
</td>
</tr>
<tr>
<td align="left" valign="top">
<div class="form-label">
......
......@@ -63,6 +63,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
<input type="text" name="destination_path" size="40" />
</td>
</tr>
<tr>
<td align="left" valign="top">
<div class="form-label">
Source URI
</label></div>
</td>
<td align="left" valign="top">
<input type="text" name="source_uri" size="40" />
</td>
</tr>
<tr>
<td align="left" valign="top">
<div class="form-label">
......
......@@ -73,6 +73,26 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
<input type="text" name="destination_path" size="40" />
</td>
</tr>
<tr>
<td align="left" valign="top">
<div class="form-label">
Source URI
</label></div>
</td>
<td align="left" valign="top">
<input type="text" name="source_uri" size="40" />
</td>
</tr>
<tr>
<td align="left" valign="top">
<div class="form-label">
Target URI
</label></div>
</td>
<td align="left" valign="top">
<input type="text" name="target_uri" size="40" />
</td>
</tr>
<tr>
<td align="left" valign="top">
<div class="form-label">
......
......@@ -43,9 +43,10 @@ from Products.ERP5SyncML.SyncCode import SyncCode
from zLOG import LOG
try:
from base64 import b64encode, b64decode
from base64 import b64encode, b64decode, b16encode, b16decode
except ImportError:
from base64 import encodestring as b64encode, decodestring as b64decode
from base64 import encodestring as b64encode, decodestring as b64decode, \
encodestring as b16encode, decodestring as b16decode
class TestERP5SyncMLMixin:
......@@ -195,10 +196,10 @@ class TestERP5SyncMLMixin:
file.write('')
file.close()
nb_message = 1
result = portal_sync.SubSync(subscription.getTitle())
result = portal_sync.SubSync(subscription)
while result['has_response']==1:
portal_sync.PubSync(publication.getTitle())
result = portal_sync.SubSync(subscription.getTitle())
result = portal_sync.SubSync(subscription)
nb_message += 1 + result['has_response']
return nb_message
......@@ -226,16 +227,16 @@ class TestERP5SyncMLMixin:
file.write('')
file.close()
nb_message = 1
result = portal_sync.SubSync(subscription.getTitle())
result = portal_sync.SubSync(subscription)
while result['has_response']==1:
# We do thing three times, so that we will test
# if we manage well duplicate messages
portal_sync.PubSync(publication.getTitle())
portal_sync.PubSync(publication.getTitle())
portal_sync.PubSync(publication.getTitle())
result = portal_sync.SubSync(subscription.getTitle())
result = portal_sync.SubSync(subscription.getTitle())
result = portal_sync.SubSync(subscription.getTitle())
result = portal_sync.SubSync(subscription)
result = portal_sync.SubSync(subscription)
result = portal_sync.SubSync(subscription)
nb_message += 1 + result['has_response']
return nb_message
......@@ -337,9 +338,15 @@ class TestERP5SyncML(TestERP5SyncMLMixin, ERP5TypeTestCase):
LOG('Testing... ',0,'test_02_AddPublication')
portal_id = self.getPortalName()
portal_sync = self.getSynchronizationTool()
portal_sync.manage_addPublication(self.pub_id,self.publication_url,
'/%s/person_server' % portal_id,'objectValues', self.xml_mapping,
'ERP5Conduit','')
portal_sync.manage_addPublication(title=self.pub_id,
publication_url=self.publication_url,
destination_path='/%s/person_server' % portal_id,
source_uri='Person',
query='objectValues',
xml_mapping=self.xml_mapping,
conduit='ERP5Conduit',
gpg_key='',
gid_generator='getId')
pub = portal_sync.getPublication(self.pub_id)
self.failUnless(pub is not None)
......@@ -350,9 +357,17 @@ class TestERP5SyncML(TestERP5SyncMLMixin, ERP5TypeTestCase):
LOG('Testing... ',0,'test_03_AddSubscription1')
portal_id = self.getPortalId()
portal_sync = self.getSynchronizationTool()
portal_sync.manage_addSubscription(self.sub_id1, self.publication_url,
self.subscription_url1,'/%s/person_client1' % portal_id,'objectValues',
self.xml_mapping,'ERP5Conduit','')
portal_sync.manage_addSubscription(title=self.sub_id1,
publication_url=self.publication_url,
subscription_url=self.subscription_url1,
destination_path='/%s/person_client1' % portal_id,
source_uri='Person',
target_uri='Person',
query='objectValues',
xml_mapping=self.xml_mapping,
conduit='ERP5Conduit',
gpg_key='',
gid_generator='getId')
sub = portal_sync.getSubscription(self.sub_id1)
self.failUnless(sub is not None)
......@@ -363,9 +378,17 @@ class TestERP5SyncML(TestERP5SyncMLMixin, ERP5TypeTestCase):
LOG('Testing... ',0,'test_04_AddSubscription2')
portal_id = self.getPortalId()
portal_sync = self.getSynchronizationTool()
portal_sync.manage_addSubscription(self.sub_id2,self.publication_url,
self.subscription_url2,'/%s/person_client2' % portal_id,'objectValues',
self.xml_mapping,'ERP5Conduit','')
portal_sync.manage_addSubscription(title=self.sub_id2,
publication_url=self.publication_url,
subscription_url=self.subscription_url2,
destination_path='/%s/person_client2' % portal_id,
source_uri='Person',
target_uri='Person',
query='objectValues',
xml_mapping=self.xml_mapping,
conduit='ERP5Conduit',
gpg_key='',
gid_generator='getId')
sub = portal_sync.getSubscription(self.sub_id2)
self.failUnless(sub is not None)
......@@ -530,7 +553,7 @@ class TestERP5SyncML(TestERP5SyncMLMixin, ERP5TypeTestCase):
# By default we can just give the id
portal_sync = self.getSynchronizationTool()
publication = portal_sync.getPublication(self.pub_id)
object = publication.getObjectFromGid(self.id1)
object = publication.getObjectFromId(self.id1)
self.failUnless(object is not None)
self.failUnless(object.getId()==self.id1)
......@@ -994,10 +1017,11 @@ class TestERP5SyncML(TestERP5SyncMLMixin, ERP5TypeTestCase):
publication = portal_sync.getPublication(self.pub_id)
self.failUnless(len(publication.getObjectList())==nb_person)
gid = self.first_name1 + ' ' + self.last_name1 # ie the title 'Sebastien Robin'
gid = b16encode(gid)
person_c1 = subscription1.getObjectFromGid(gid)
id_c1 = person_c1.getId()
self.failUnless(id_c1 in ('1','2')) # id given by the default generateNewId
person_s = publication.getObjectFromGid(gid)
person_s = publication.getSubscriber(self.subscription_url1).getObjectFromGid(gid)
id_s = person_s.getId()
self.failUnless(id_s==self.id1)
# This will test updating object
......@@ -1014,7 +1038,7 @@ class TestERP5SyncML(TestERP5SyncMLMixin, ERP5TypeTestCase):
self.checkSynchronizationStateIsSynchronized()
self.failUnless(len(subscription1.getObjectList())==(nb_person-1))
self.failUnless(len(publication.getObjectList())==(nb_person-1))
person_s = publication.getObjectFromGid(gid)
person_s = publication.getSubscriber(self.subscription_url1).getObjectFromGid(gid)
person_c1 = subscription1.getObjectFromGid(gid)
self.failUnless(person_s.getDescription()==self.description3)
self.failUnless(person_c1.getDescription()==self.description3)
......@@ -1299,9 +1323,17 @@ class TestERP5SyncML(TestERP5SyncMLMixin, ERP5TypeTestCase):
LOG('Testing... ',0,'test_32_AddOneWaySubscription')
portal_id = self.getPortalId()
portal_sync = self.getSynchronizationTool()
portal_sync.manage_addSubscription(self.sub_id1, self.publication_url,
self.subscription_url1, '/%s/person_client1' % portal_id,
'objectValues', '', 'ERP5Conduit', '')
portal_sync.manage_addSubscription(title=self.sub_id1,
publication_url=self.publication_url,
subscription_url=self.subscription_url1,
destination_path='/%s/person_client1' % portal_id,
source_uri='Person',
target_uri='Person',
query='objectValues',
xml_mapping='',
conduit='ERP5Conduit',
gpg_key='',
gid_generator='getId')
sub = portal_sync.getSubscription(self.sub_id1)
self.failUnless(sub is not None)
......
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