Commit 6f2372aa authored by Arnaud Fontaine's avatar Arnaud Fontaine

ZODB Components: Migrate ERP5SyncML Product from filesystem.

To avoid too generic names for Products.ERP5SyncML.{Engine,Transport}, prefix
the ZODB Components references with SyncML{Engine,Transport}.
parent c8ad77fb
......@@ -65,7 +65,7 @@ def findMessageListFromPythonInProduct(function_name_list):
erp5_product_list = ('CMFActivity', 'CMFCategory',
'ERP5', 'ERP5Banking', 'ERP5Catalog',
'ERP5Form', 'ERP5OOo', 'ERP5Security',
'ERP5SyncML', 'ERP5Type', 'ERP5Wizard', 'ERP5Workflow',
'ERP5Type', 'ERP5Wizard', 'ERP5Workflow',
'HBTreeFolder2', 'MailTemplates', 'TimerService',
'ZMySQLDA', 'ZSQLCatalog',
)
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Document Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>SyncMLConflict</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5SyncML.Document.SyncMLConflict</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>document.erp5.SyncMLConflict</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Document Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -27,10 +27,10 @@
#
##############################################################################
from Products.ERP5SyncML.Document.SyncMLSubscription import SyncMLSubscription
from erp5.component.document.SyncMLSubscription import SyncMLSubscription
from Products.ERP5Type import Permissions
from AccessControl import ClassSecurityInfo
from Products.ERP5SyncML.SyncMLConstant import ACTIVITY_PRIORITY
from erp5.component.module.SyncMLConstant import ACTIVITY_PRIORITY
from Products.ERP5Type.UnrestrictedMethod import UnrestrictedMethod
class SyncMLPublication(SyncMLSubscription):
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Document Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>SyncMLPublication</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5SyncML.Document.SyncMLPublication</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>document.erp5.SyncMLPublication</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Document Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -34,11 +34,11 @@ from AccessControl import ClassSecurityInfo
from Products.ERP5Type.XMLObject import XMLObject
from Products.ERP5Type import Permissions
from Products.ERP5Type import PropertySheet
from Products.ERP5SyncML.Utils import PdataHelper
from erp5.component.module.SyncMLUtils import PdataHelper
from Products.ERP5Type.Accessor.Constant import PropertyGetter as ConstantGetter
_MARKER = []
_MARKER = object()
class SyncMLSignature(XMLObject):
"""
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Document Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>SyncMLSignature</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5SyncML.Document.SyncMLSignature</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>document.erp5.SyncMLSignature</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Document Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -41,18 +41,18 @@ from MySQLdb import ProgrammingError
from Products.ERP5Type.XMLObject import XMLObject
from Products.ERP5Type import Permissions, PropertySheet
from Products.ERP5Type.Utils import deprecated
from Products.ERP5SyncML.XMLSyncUtils import getConduitByName, \
from erp5.component.module.XMLSyncUtils import getConduitByName, \
buildAnchorFromDate
from Products.ERP5SyncML.SyncMLConstant import MAX_OBJECTS, ACTIVITY_PRIORITY,\
from erp5.component.module.SyncMLConstant import MAX_OBJECTS, ACTIVITY_PRIORITY,\
NULL_ANCHOR
from Products.ERP5SyncML.SyncMLMessage import SyncMLResponse
from Products.ERP5SyncML.Transport.HTTP import HTTPTransport
from Products.ERP5SyncML.Transport.File import FileTransport
from Products.ERP5SyncML.Transport.Mail import MailTransport
from Products.ERP5SyncML.Transport.ERP5 import ERP5Transport
from Products.ERP5SyncML.SyncMLConstant import MAX_LEN, ADD_ACTION, \
from erp5.component.module.SyncMLMessage import SyncMLResponse
from erp5.component.module.SyncMLTransportHTTP import HTTPTransport
from erp5.component.module.SyncMLTransportFile import FileTransport
from erp5.component.module.SyncMLTransportMail import MailTransport
from erp5.component.module.SyncMLTransportERP5 import ERP5Transport
from erp5.component.module.SyncMLConstant import MAX_LEN, ADD_ACTION, \
REPLACE_ACTION
from Products.ERP5SyncML.XMLSyncUtils import cutXML
from erp5.component.module.XMLSyncUtils import cutXML
transport_scheme_dict = {
"http" : HTTPTransport(),
......@@ -68,7 +68,7 @@ MAX_OBJECT_PER_MESSAGE = 300
RETRO_COMPATIBLE = True
_MARKER = []
_MARKER = object()
class SyncMLSubscription(XMLObject):
"""
"""
......@@ -128,8 +128,8 @@ class SyncMLSubscription(XMLObject):
if not RETRO_COMPATIBLE:
raise
else:
syncml_logger.warning("Script %s does not accept paramaters limit=%s kw=%s" %
(self.getListMethodId(), limit, search_kw,))
syncml_logger.warning("Script %s does not accept paramaters limit=%s kw=%s",
self.getListMethodId(), limit, search_kw)
r_list = self.getDocumentList() # It is assumed that
# the result is sorted
result_count = len(r_list)
......@@ -137,22 +137,22 @@ class SyncMLSubscription(XMLObject):
r = [str(x.path) for x in r_list]
if not limit:
# We do not split in activity so call the callback right now
syncml_logger.info("getAndIndex : got %d result and no limit, calling callback..." %
(result_count,))
syncml_logger.info("getAndIndex : got %d result and no limit, calling callback...",
result_count)
callback_method = getattr(self, callback)
callback_method(path_list=r[:],
activate_kw=activate_kw,
**method_kw)
else:
syncml_logger.info("getAndIndex : got %d, %r result, limit = %r, packet %r" %
(result_count, r, limit, packet_size))
syncml_logger.info("getAndIndex : got %d, %r result, limit = %r, packet %r",
result_count, r, limit, packet_size)
generated_other_activity = False
if result_count == limit:
# Recursive call to prevent too many activity generation
next_kw = dict(activate_kw, priority=1+activate_kw.get('priority', 1))
kw["min_id"] = r_list[-1].getId()
syncml_logger.info("--> calling getAndIndex in activity, min = %s" %
(kw["min_id"],))
syncml_logger.info("--> calling getAndIndex in activity, min = %s",
kw["min_id"])
self.activate(**next_kw).getAndIndex(
callback, method_kw, activate_kw, **kw)
generated_other_activity = True
......@@ -161,23 +161,23 @@ class SyncMLSubscription(XMLObject):
callback_method = getattr(activate(**activate_kw), callback)
if generated_other_activity:
for i in xrange(0, result_count, packet_size):
syncml_logger.info("-- getAndIndex : recursive call, generating for %s"
% (r[i:i+packet_size],))
syncml_logger.info("-- getAndIndex : recursive call, generating for %s",
r[i:i+packet_size])
callback_method(path_list=r[i:i+packet_size],
activate_kw=activate_kw,
**method_kw)
else:
if result_count > packet_size and limit:
for i in xrange(0, result_count-packet_size, packet_size):
syncml_logger.info("-- getAndIndex : i %s, call, generating for %s : %s" %
(i, r[i:i+packet_size], activate_kw))
syncml_logger.info("-- getAndIndex : i %s, call, generating for %s : %s",
i, r[i:i+packet_size], activate_kw)
callback_method(path_list=r[i:i+packet_size],
**method_kw)
final_min = i + packet_size
else:
final_min = 0
syncml_logger.info("---- getAndIndex : final call for %s %s : %s" \
%(final_min, r[final_min:], activate_kw))
syncml_logger.info("---- getAndIndex : final call for %s %s : %s",
final_min, r[final_min:], activate_kw)
callback_method(path_list=r[final_min:],
activate_kw=activate_kw,
**method_kw)
......@@ -205,7 +205,7 @@ class SyncMLSubscription(XMLObject):
Return the path of the subscription that will be used in sql table
_ char must be escaped because of the LIKE behaviour
"""
return "%s/%%" % (self.getSourceValue().getPath().replace("_","\_"),)
return "%s/%%" % (self.getSourceValue().getPath().replace("_","\_"),) # pylint: disable=anomalous-backslash-in-string
security.declarePrivate('sendSyncCommand')
def sendSyncCommand(self, min_gid, max_gid, message_id, activate_kw):
......@@ -244,9 +244,9 @@ class SyncMLSubscription(XMLObject):
# Send the message in activity to prevent recomputing data in case of
# transport failure
if syncml_response:
syncml_logger("---- %s sending %s notifications of sync"
% (self.getTitle(),
syncml_response.sync_confirmation_counter))
syncml_logger("---- %s sending %s notifications of sync",
self.getTitle(),
syncml_response.sync_confirmation_counter)
self.activate(activity="SQLQueue",
# group_method_id=None,
# group_method_cost=.05,
......@@ -274,8 +274,8 @@ class SyncMLSubscription(XMLObject):
search_kw = dict(kw)
packet_size = search_kw.pop('packet_size', 30)
limit = packet_size * search_kw.pop('activity_count', 100)
syncml_logger.debug("--> calling getAndActivate packet size = %s, limit = %s" %
(packet_size, limit))
syncml_logger.debug("--> calling getAndActivate packet size = %s, limit = %s",
packet_size, limit)
# We must know if we have a lower limit or not to propagate
if not kw.has_key("strict_min_gid"):
first_call = True
......@@ -292,13 +292,13 @@ class SyncMLSubscription(XMLObject):
result_count = len(r)
generated_other_activity = False
if result_count:
syncml_logger.info("getAndActivate : got %d result" % (result_count,))
syncml_logger.info("getAndActivate : got %d result", result_count)
if result_count == limit:
# Recursive call to prevent too many activity generation
next_kw = dict(activate_kw, priority=1+activate_kw.get('priority', 1))
kw["strict_min_gid"] = r[-1]
syncml_logger.info("--> calling getAndActivate in activity, min = %s" %
(kw.get("strict_min_gid", None),))
syncml_logger.info("--> calling getAndActivate in activity, min = %s",
kw.get("strict_min_gid", None))
self.activate(**next_kw).getAndActivate(
callback, activate_kw, **kw)
generated_other_activity = True
......@@ -321,8 +321,8 @@ class SyncMLSubscription(XMLObject):
except IndexError:
# Last packet
max_gid = r[-1]
syncml_logger.info("-- getAndActivate : recursive call i = %s, min = %s, max = %s" \
% (i, min_gid, max_gid,))
syncml_logger.info("-- getAndActivate : recursive call i = %s, min = %s, max = %s",
i, min_gid, max_gid)
callback_method(min_gid=min_gid,
max_gid=max_gid,
message_id=message_id_list.pop(),
......@@ -336,8 +336,8 @@ class SyncMLSubscription(XMLObject):
first_call = False
else:
min_gid = r[i]
syncml_logger.info("-- getAndActivate : call min = %s, max = %s" \
% (min_gid, r[i+packet_size-1]))
syncml_logger.info("-- getAndActivate : call min = %s, max = %s",
min_gid, r[i+packet_size-1])
callback_method(min_gid=min_gid,
max_gid=r[i+packet_size-1],
message_id=message_id_list.pop(),
......@@ -351,8 +351,8 @@ class SyncMLSubscription(XMLObject):
min_gid = None
else:
min_gid = r[final_min]
syncml_logger.info("-- getAndActivate : final call min = %s, max = None" \
% (min_gid,))
syncml_logger.info("-- getAndActivate : final call min = %s, max = None",
min_gid)
callback_method(min_gid=min_gid,
max_gid=None, # No limit when last call
message_id=message_id_list.pop(),
......@@ -456,8 +456,8 @@ class SyncMLSubscription(XMLObject):
portal_type='SyncML Signature',
id=gid,
)
syncml_logger.info("Created a signature for %s - document : %s"
% (signature.getPath(), document))
syncml_logger.info("Created a signature for %s - document : %s",
signature.getPath(), document)
if document is not None:
signature.setReference(document.getPath())
......@@ -484,7 +484,7 @@ class SyncMLSubscription(XMLObject):
signature.appendPartialData(incoming_data)
incoming_data = signature.getPartialData()
signature.setPartialData(None)
__traceback_info__ = (gid, document, incoming_data, action['command'])
__traceback_info__ = (gid, document, incoming_data, action['command']) # pylint: disable=unused-variable
# Browse possible actions
if action["command"] == 'Add':
status_code = "item_added" # Default status code for addition
......@@ -518,7 +518,7 @@ class SyncMLSubscription(XMLObject):
if data_diff and len(data_diff):
# XXX Here maybe a conflict must be raised as document was never
# synchronized and we try to add one which is different
syncml_logger.critical("trying to add data, but already existing object exists, diff is\n%s" % (data_diff))
syncml_logger.critical("trying to add data, but already existing object exists, diff is\n%s", data_diff)
conflict_list.extend(conduit.updateNode(
xml=data_diff,
......@@ -577,8 +577,8 @@ class SyncMLSubscription(XMLObject):
elif action['command'] == 'Delete':
status_code="success"
document = self.getDocumentFromGid(signature.getId())
syncml_logger.info("Deleting signature %s & doc %s" %(signature.getPath(),
document.getPath()))
syncml_logger.info("Deleting signature %s & doc %s", signature.getPath(),
document.getPath())
path_list.remove(signature.getPath())
if document is not None:
# XXX Can't we get conflict ?
......@@ -589,8 +589,8 @@ class SyncMLSubscription(XMLObject):
# Delete signature
self._delObject(gid)
else:
syncml_logger.error("Document with gid %s is already deleted"
% (gid,))
syncml_logger.error("Document with gid %s is already deleted",
gid)
self.z_delete_data_from_path(path="%s" %(signature.getPath(),))
else:
......@@ -610,8 +610,8 @@ class SyncMLSubscription(XMLObject):
else:
signature.setData(str(xml_document))
signature.synchronize()
syncml_logger.info("change state of signature to %s with %s"
% (signature.getValidationState(), signature.getData()))
syncml_logger.info("change state of signature to %s with %s",
signature.getValidationState(), signature.getData())
if signature:
# Generate status about the object synchronized
......@@ -625,8 +625,8 @@ class SyncMLSubscription(XMLObject):
message_ref=request_message_id)
else: # We want to retrieve more data
syncml_logger.info("we need to retrieve more data for %s"
% (signature.getRelativeUrl(),))
syncml_logger.info("we need to retrieve more data for %s",
signature.getRelativeUrl())
signature.appendPartialData(incoming_data)
# XXX Must check if size is present into the xml
# if not, client might ask it to server with a 411 alert
......@@ -665,8 +665,8 @@ class SyncMLSubscription(XMLObject):
'priority' :ACTIVITY_PRIORITY + 1,
'tag' : "%s_delete" %(self.getRelativeUrl(),)
}
syncml_logger.info("Sending final message for modificationson on %s"
% (self.getRelativeUrl(),))
syncml_logger.info("Sending final message for modificationson on %s",
self.getRelativeUrl())
self.activate(**final_activate_kw).sendMessage(xml=str(syncml_response))
......@@ -685,10 +685,10 @@ class SyncMLSubscription(XMLObject):
signature_path=self.getSearchablePath(),
source_path=self.getSearchableSourcePath())
syncml_logger.info("\t---> delete signature are %r" % (len(deleted_signature_set)))
syncml_logger.info("\t---> delete signature are %r", len(deleted_signature_set))
for r in deleted_signature_set:
syncml_response.addDeleteCommand(gid=r.gid)
syncml_logger.info("\t\t---> %r" % (r.gid))
syncml_logger.info("\t\t---> %r", r.gid)
syncml_response.addFinal()
# Now send the message
......@@ -698,12 +698,12 @@ class SyncMLSubscription(XMLObject):
'priority' :ACTIVITY_PRIORITY + 1,
'tag' : "%s_delete" %(self.getRelativeUrl(),)
}
syncml_logger.info("Sending final message for modificationson on %s"
% (self.getRelativeUrl(),))
syncml_logger.info("Sending final message for modificationson on %s",
self.getRelativeUrl())
self.activate(**final_activate_kw).sendMessage(xml=str(syncml_response))
def getSearchablePath(self):
return "%s%%" %(self.getPath().replace('_', '\_'),)
return "%s%%" %(self.getPath().replace('_', '\_'),) # pylint: disable=anomalous-backslash-in-string
def _generateSyncCommand(self, action, signature, data_diff ,document_data, gid,
......@@ -715,7 +715,7 @@ class SyncMLSubscription(XMLObject):
if signature:
if len(data_diff) > MAX_LEN and not self.getIsActivityEnabled():
# XXX-Aurel : I do not think splitting is working when running in activity
syncml_logger.info("data for %s too big, splitting..." %(signature.getPath(),))
syncml_logger.info("data for %s too big, splitting...", signature.getPath())
more_data = True
data_diff, rest_string = cutXML(data_diff, MAX_LEN)
# Store the remaining data to send it later
......@@ -727,7 +727,7 @@ class SyncMLSubscription(XMLObject):
signature.setTemporaryData(document_data)
# Generate the message
syncml_logger.info("adding sync command %s for %s" %(action, gid))
syncml_logger.info("adding sync command %s for %s", action, gid)
syncml_response.addSyncCommand(
sync_command=action,
gid=gid,
......@@ -747,7 +747,7 @@ class SyncMLSubscription(XMLObject):
min_gid = the lower limit for browsing data
max_gid = the upper limit for browsing data
"""
syncml_logger.info("getSyncMLData, min %s - max %r" % (min_gid, max_gid,))
syncml_logger.info("getSyncMLData, min %s - max %r", min_gid, max_gid)
conduit = self.getConduit()
portal = self.getPortalObject()
......@@ -762,7 +762,7 @@ class SyncMLSubscription(XMLObject):
max_gid=max_gid,
path=self.getSearchableSourcePath())
syncml_logger.info("getSyncMLData, object list is %s" % ([x.path for x in object_list]))
syncml_logger.info("getSyncMLData, object list is %s", [x.path for x in object_list])
alert_code = self.getSyncmlAlertCode()
sync_all = alert_code in ("refresh_from_client_only", "slow_sync")
......@@ -782,8 +782,8 @@ class SyncMLSubscription(XMLObject):
document_data = result.data
signature = self.getSignatureFromGid(gid)
if signature:
syncml_logger.info("signature is %s = %s" %(signature.getRelativeUrl(),
signature.getValidationState()))
syncml_logger.info("signature is %s = %s", signature.getRelativeUrl(),
signature.getValidationState())
if not document_data:
raise ValueError("No data for %s / %s" %(gid, document_path))
......@@ -799,8 +799,8 @@ class SyncMLSubscription(XMLObject):
id=gid,
reference=document_path,
temporary_data=document_data)
syncml_logger.info("Created a signature %s for gid = %s, path %s"
% (signature.getPath(), gid, document_path))
syncml_logger.info("Created a signature %s for gid = %s, path %s",
signature.getPath(), gid, document_path)
more_data = self._generateSyncCommand(
action=ADD_ACTION,
signature=signature,
......@@ -820,7 +820,7 @@ class SyncMLSubscription(XMLObject):
# We need to convert XML to a CDATA type to prevent collision
# with syncml's XML
document_data = etree.CDATA(xml_string.decode('utf-8'))
syncml_logger.info("adding partial sync command for %s" %(gid,))
syncml_logger.info("adding partial sync command for %s", gid)
syncml_response.addSyncCommand(
sync_command=signature.getPartialAction(),
gid=gid,
......@@ -829,8 +829,8 @@ class SyncMLSubscription(XMLObject):
media_type=conduit.getContentType())
if not more_data:
syncml_logger.info("signature %s is syncing from partial"
% (signature.getRelativeUrl(),))
syncml_logger.info("signature %s is syncing from partial",
signature.getRelativeUrl())
elif signature.getValidationState() in ('no_conflict',
'conflict_resolved_with_merge'):
......@@ -848,8 +848,8 @@ class SyncMLSubscription(XMLObject):
sync_code='conflict_resolved_with_merge',
command='Replace')
syncml_logger.info("\tMD5 is %s for %s" %((signature.checkMD5(document_data)),
signature.getReference()))
syncml_logger.info("\tMD5 is %s for %s", signature.checkMD5(document_data),
signature.getReference())
if not signature.checkMD5(document_data):
# MD5 checksum tell there is a modification of the object
# XXX this diff generation must managed by the conduit
......@@ -868,12 +868,12 @@ class SyncMLSubscription(XMLObject):
# MD5 Checksum can detect changes like <lang/> != <lang></lang>
# but Diff generator will return no diff for it
# in this case, no need to send diff
syncml_logger.info("\tFake diff, signature %s is synchronized"
% (signature.getRelativeUrl(),))
syncml_logger.info("\tFake diff, signature %s is synchronized",
signature.getRelativeUrl())
continue
# Reindex modified document
syncml_logger.info("\tGot a diff for %s : %s" %(gid, data_diff))
syncml_logger.info("\tGot a diff for %s : %s", gid, data_diff)
more_data = self._generateSyncCommand(
action=REPLACE_ACTION,
signature=signature,
......@@ -903,15 +903,15 @@ class SyncMLSubscription(XMLObject):
sync_code='conflict_resolved_with_client_command_winning',
command='Replace')
signature.synchronize()
syncml_logger.debug("signature %s is synchronized"
% (signature.getRelativeUrl(),))
syncml_logger.debug("signature %s is synchronized",
signature.getRelativeUrl())
if more_data:
syncml_logger.info("Splitting document")
break
syncml_logger.info("_getSyncMLData end with more_data %s"
% (more_data,))
syncml_logger.info("_getSyncMLData end with more_data %s",
more_data)
return not more_data
security.declareProtected(Permissions.AccessContentsInformation,
......@@ -961,7 +961,7 @@ class SyncMLSubscription(XMLObject):
security.declareProtected(Permissions.AccessContentsInformation,
'getGidFromObject')
def getGidFromObject(self, object, encoded=True):
def getGidFromObject(self, object, encoded=True): # pylint: disable=redefined-builtin
"""
Returns the object gid
"""
......@@ -1094,7 +1094,7 @@ class SyncMLSubscription(XMLObject):
security.declareProtected(Permissions.AccessContentsInformation,
'getSignatureFromObjectId')
def getSignatureFromObjectId(self, id):
def getSignatureFromObjectId(self, id): # pylint: disable=redefined-builtin
"""
return the signature corresponding to the id
### Use a reverse dictionary will be usefull
......@@ -1106,7 +1106,7 @@ class SyncMLSubscription(XMLObject):
if document is not None:
if id == document.getId():
return signature
else: # XXX-Aurel : maybe none is expected
else: # XXX-Aurel : maybe none is expected # pylint: disable=useless-else-on-loop
raise KeyError, id
security.declareProtected(Permissions.AccessContentsInformation,
......@@ -1203,7 +1203,7 @@ class SyncMLSubscription(XMLObject):
)
else:
r = [x.getPath() for x in self.getDocumentList()]
syncml_logger.info("indexing data from %s : %r" %(self.getPath(), r))
syncml_logger.info("indexing data from %s : %r", self.getPath(), r)
portal.SQLCatalog_indexSyncMLDocumentList(
path_list=r[:],
subscription_path=self.getRelativeUrl())
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Document Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_recorded_property_dict</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>SyncMLSubscription</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5SyncML.Document.SyncMLSubscription</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>document.erp5.SyncMLSubscription</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Document Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -67,7 +67,7 @@ class IConduit(Interface):
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
"""
def constructContent(object, object_id, portal_type):
def constructContent(object, object_id, portal_type): # pylint: disable=redefined-builtin
"""
This allows to specify how to construct a new content.
This is really usefull if you want to write your
......@@ -82,7 +82,7 @@ class IConduit(Interface):
return newObject, reset_local_roles boolean, reset_workflow boolean
"""
def addNode(xml=None, object=None, previous_xml=None,
def addNode(xml=None, object=None, previous_xml=None, # pylint: disable=redefined-builtin
object_id=None, sub_object=None, force=0, simulate=0, **kw):
"""
A node is added
......@@ -100,13 +100,13 @@ class IConduit(Interface):
[object.getPath(),keyword,local_and_actual_value,subscriber_value]
"""
def deleteNode(xml=None, object=None, object_id=None, force=None,
def deleteNode(xml=None, object=None, object_id=None, force=None, # pylint: disable=redefined-builtin
simulate=0, **kw):
"""
A node is deleted
"""
def updateNode(xml=None, object=None, previous_xml=None, force=0,
def updateNode(xml=None, object=None, previous_xml=None, force=0, # pylint: disable=redefined-builtin
simulate=0, **kw):
"""
A node is updated with some xupdate
......@@ -117,7 +117,7 @@ class IConduit(Interface):
"""
def getGidFromObject(object, configurable_gid_dictionary=None):
def getGidFromObject(object, configurable_gid_dictionary=None): # pylint: disable=redefined-builtin
"""
return the Gid composed with the object information
- object is the document on which for we are building the gid.
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Interface Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>IConduit</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5SyncML.interfaces.conduit</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>interface.erp5.IConduit</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Interface Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -31,15 +31,15 @@ from AccessControl import ClassSecurityInfo, getSecurityManager
from Products.PluggableAuthService.interfaces.plugins import \
IAuthenticationPlugin
from Products.ERP5SyncML.XMLSyncUtils import resolveSyncmlStatusCode, decode
from Products.ERP5SyncML.SyncMLMessage import SyncMLResponse
from Products.ERP5SyncML.SyncMLConstant import NULL_ANCHOR, ACTIVITY_PRIORITY, \
from erp5.component.module.XMLSyncUtils import resolveSyncmlStatusCode, decode
from erp5.component.module.SyncMLMessage import SyncMLResponse
from erp5.component.module.SyncMLConstant import NULL_ANCHOR, ACTIVITY_PRIORITY, \
SynchronizationError
syncml_logger = getLogger('ERP5SyncML')
class EngineMixin(object):
class SyncMLEngineMixin(object):
"""
Mixin class that holds generci methods used by engines
"""
......@@ -75,9 +75,11 @@ class EngineMixin(object):
status['authentication_type']))
# XXX Not working To Review !
raise NotImplementedError("Adding credentials")
"""
syncml_response = domain.generateBaseResponse()
syncml_response.addCredentialMessage(domain)
return syncml_response
"""
elif status['status_code'] == \
resolveSyncmlStatusCode('invalid_credentials'):
syncml_logger.error("\tClient authentication refused")
......@@ -92,8 +94,8 @@ class EngineMixin(object):
# XXX Must check status for asked synchrozation
# and must be done for command, not for
# For now do nothing = say it is always OK
syncml_logger.info("\tChecking database, will generate alert %s"
% (generate_alert))
syncml_logger.info("\tChecking database, will generate alert %s",
generate_alert)
elif status["command"] in ('Add', 'Replace'):
sync_status_counter += 1
object_gid = status['source'] or status['target']
......@@ -110,27 +112,27 @@ class EngineMixin(object):
% (domain.getPath(), object_gid))
if status['status_code'] == resolveSyncmlStatusCode('conflict'):
signature.changeToConflict()
syncml_logger.error("\tObject in conflict %s" %
(status['source'] or status['target']))
syncml_logger.error("\tObject in conflict %s",
status['source'] or status['target'])
elif status['status_code'] == resolveSyncmlStatusCode(
'conflict_resolved_with_merge'):
# We will have to apply the update, and we should not care
# about conflicts, so we have to force the update
signature.noConflict()
signature.setForce(True)
syncml_logger.error("\tObject merged %s" %
(status['source'] or status['target']))
syncml_logger.error("\tObject merged %s",
status['source'] or status['target'])
elif status['status_code'] in (resolveSyncmlStatusCode('success'),
resolveSyncmlStatusCode('item_added'),
resolveSyncmlStatusCode(
'conflict_resolved_with_client_command_winning')):
syncml_logger.error("\tObject synchronized %s" %
(status['source'] or status['target'],))
syncml_logger.error("\tObject synchronized %s",
status['source'] or status['target'])
if signature.getValidationState() != "no_conflict":
signature.noConflict()
signature.synchronize()
elif status['status_code'] == resolveSyncmlStatusCode('chunk_accepted'):
syncml_logger.info("Chunk was accepted for %s" % (object_gid,))
syncml_logger.info("Chunk was accepted for %s", object_gid)
else:
raise ValueError("Unknown status code : %r" % (status['status_code'],))
# Index signature now to fill the data column
......@@ -147,8 +149,8 @@ class EngineMixin(object):
raise ValueError("Found no signature to delete for gid %s" %(object_gid,))
else:
raise ValueError("Unknown status code : %r" % (status['status_code'],))
syncml_logger.error("\tObject deleted %s" %
(status['source'] or status['target']))
syncml_logger.error("\tObject deleted %s",
status['source'] or status['target'])
else:
raise ValueError("Unknown status command : %r" % (status['command'],))
......@@ -174,8 +176,8 @@ class EngineMixin(object):
done here but can be a way of improvement to decrease number of messages
exchanged.
"""
syncml_logger.info('--- Starting synchronization on client side : %s ---'
% (subscription.getPath(),))
syncml_logger.info('--- Starting synchronization on client side : %s ---',
subscription.getPath())
if not subscription.getSynchronizationState() == "initializing":
# This can be called many time in sync init when credentials failed
subscription.initialize() # Worflow action
......@@ -309,8 +311,8 @@ class EngineMixin(object):
% syncml_request.alert['data'])
syncml_logger.info('--- Starting synchronization on server side : %s in mode %s ---'
% (publication.getPath(), alert_dict["data"]))
syncml_logger.info('--- Starting synchronization on server side : %s in mode %s ---',
publication.getPath(), alert_dict["data"])
# at the begining of the synchronization the subscriber is not authenticated
if subscriber.getAuthenticationState() == 'logged_in':
subscriber.logout()
......@@ -339,13 +341,13 @@ class EngineMixin(object):
login, password = decoded.split(':')
# TODO: make it work for users existing anywhere
user_folder = publication.getPortalObject().acl_users
for plugin_name, plugin in user_folder._getOb('plugins')\
for _, plugin in user_folder._getOb('plugins')\
.listPlugins(IAuthenticationPlugin):
if plugin.authenticateCredentials(
{'login': login, 'password': password}) is not None:
subscriber.login()
syncml_logger.info("\tServer accepted authentication for user %s"
% (login,))
syncml_logger.info("\tServer accepted authentication for user %s",
login)
authentication_code = 'authentication_accepted'
subscriber._loginUser(login)
subscriber._edit(authenticated_user=login)
......@@ -356,21 +358,21 @@ class EngineMixin(object):
# authentication_code = 'missing_credentials'
# else:
authentication_code = 'invalid_credentials'
syncml_logger.error("\tServer rejected authentication for %s" % (login))
syncml_logger.error("\tServer rejected authentication for %s", login)
else:
# if header_kw["message_id"] == 1:
# authentication_code = 'missing_credentials'
# else:
authentication_code = 'invalid_credentials'
syncml_logger.warning(
"\tCredentials does not look like auth-basis, decoded value is '%s,'"
% (decoded))
"\tCredentials does not look like auth-basis, decoded value is '%s,'",
decoded)
else:
# To complete, must send a challenge message
syncml_logger.warning(
"\tAuthentication type does not math, from client '%s', from server '%s'" %(
"\tAuthentication type does not math, from client '%s', from server '%s'",
syncml_request.credentials['type'],
publication.getAuthenticationType()))
publication.getAuthenticationType())
authentication_code = 'missing_credentials'
......@@ -397,9 +399,9 @@ class EngineMixin(object):
elif subscriber.getNextAnchor() != alert_dict['last_anchor']:
# Anchor does not match, must start a slow sync
syncml_logger.warning("\tAnchor does not match on server, \
received is %s, stored %s. Will start a slow sync"
%(alert_dict['last_anchor'],
subscriber.getNextAnchor()))
received is %s, stored %s. Will start a slow sync",
alert_dict['last_anchor'],
subscriber.getNextAnchor())
sync_type_validation_code = "command_failed" # Error 500
sync_type = 'slow_sync'
else:
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Mixin Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>SyncMLEngineMixin</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5SyncML.Engine.EngineMixin</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>mixin.erp5.SyncMLEngineMixin</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Mixin Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -42,7 +42,7 @@ class BaseConduit(object):
def generateDiff(self, new_data, former_data):
return None
def getXMLFromObjectWithId(self, object, xml_mapping, context_document=None):
def getXMLFromObjectWithId(self, object, xml_mapping, context_document=None): # pylint: disable=redefined-builtin
"""
return the xml with Id of Object
"""
......@@ -60,7 +60,7 @@ class BaseConduit(object):
return data
def getGidFromObject(self, object):
def getGidFromObject(self, object): # pylint: disable=redefined-builtin
"""
return the Gid composed with the object informations
"""
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Module Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>BaseConduit</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5SyncML.Conduit.BaseConduit</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>module.erp5.BaseConduit</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Module Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -27,15 +27,15 @@
#
##############################################################################
from Products.ERP5SyncML.XMLSyncUtils import XMLSyncUtilsMixin
from Products.ERP5SyncML.XMLSyncUtils import getXupdateObject
from erp5.component.module.XMLSyncUtils import XMLSyncUtilsMixin
from erp5.component.module.XMLSyncUtils import getXupdateObject
from Products.ERP5Type.Utils import deprecated
from Products.ERP5Type.XMLExportImport import MARSHALLER_NAMESPACE_URI
from Products.CMFCore.utils import getToolByName
from Products.ERP5Type.Base import WorkflowMethod
from DateTime.DateTime import DateTime
from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, interfaces
from Products.ERP5Type import Permissions
from Products.ERP5Type.Globals import PersistentMapping
from xml.sax.saxutils import unescape
......@@ -54,8 +54,9 @@ syncml_logger = logging.getLogger('ERP5SyncML')
from hashlib import sha1
from Products.ERP5SyncML.SyncMLConstant import XUPDATE_ELEMENT,\
from erp5.component.module.SyncMLConstant import XUPDATE_ELEMENT,\
XUPDATE_INSERT_OR_ADD_LIST, XUPDATE_DEL, XUPDATE_UPDATE, XUPDATE_INSERT_LIST
from erp5.component.interface.IConduit import IConduit
# Constant
HISTORY_TAG = 'workflow_action'
XML_OBJECT_TAG = 'object'
......@@ -80,11 +81,11 @@ INT_TYPE = 'int'
DATA_TYPE_LIST = ('data', 'object',)
BOOLEAN_TYPE = 'boolean'
HISTORY_EXP = re.compile("/%s\[@id='.*'\]" % HISTORY_TAG)
BAD_HISTORY_EXP = re.compile("/%s\[@id='.*'\]/" % HISTORY_TAG)
HISTORY_EXP = re.compile(r"/%s\[@id='.*'\]" % HISTORY_TAG)
BAD_HISTORY_EXP = re.compile(r"/%s\[@id='.*'\]/" % HISTORY_TAG)
EXTRACT_ID_FROM_XPATH = re.compile(
"(?P<object_block>(?P<property>[^/]+)\[@"\
"(?P<id_of_id>id|gid)='(?P<object_id>[^']+)'\])")
r"(?P<object_block>(?P<property>[^/]+)\[@"\
r"(?P<id_of_id>id|gid)='(?P<object_id>[^']+)'\])")
WORKFLOW_ACTION_NOT_ADDABLE = 0
WORKFLOW_ACTION_ADDABLE = 1
......@@ -128,7 +129,7 @@ class ERP5Conduit(XMLSyncUtilsMixin):
"""
# Declarative interfaces
implements( interfaces.IConduit, )
implements( IConduit, )
# Declarative security
security = ClassSecurityInfo()
......@@ -146,7 +147,7 @@ class ERP5Conduit(XMLSyncUtilsMixin):
#self.args = {}
security.declareProtected(Permissions.ModifyPortalContent, 'addNode')
def addNode(self, xml=None, object=None, sub_object=None, reset=None,
def addNode(self, xml=None, object=None, sub_object=None, reset=None, # pylint: disable=redefined-builtin
simulate=None, **kw):
"""
A node is added
......@@ -203,7 +204,7 @@ class ERP5Conduit(XMLSyncUtilsMixin):
return {'conflict_list':conflict_list, 'object': sub_object}
security.declareProtected(Permissions.ModifyPortalContent, 'deleteNode')
def deleteNode(self, xml=None, object=None, object_id=None, **kw):
def deleteNode(self, xml=None, object=None, object_id=None, **kw): # pylint: disable=redefined-builtin
"""
This method manage the deletion of a node as well as the deletion
of one property
......@@ -257,7 +258,7 @@ class ERP5Conduit(XMLSyncUtilsMixin):
return []
security.declareProtected(Permissions.ModifyPortalContent, 'deleteObject')
def deleteObject(self, object, object_id, **kw):
def deleteObject(self, object, object_id, **kw): # pylint: disable=redefined-builtin
try:
object._delObject(object_id)
except (AttributeError, KeyError):
......@@ -265,7 +266,7 @@ class ERP5Conduit(XMLSyncUtilsMixin):
pass
security.declareProtected(Permissions.ModifyPortalContent, 'updateNode')
def updateNode(self, xml=None, object=None, previous_xml=None, force=False,
def updateNode(self, xml=None, object=None, previous_xml=None, force=False, # pylint: disable=redefined-builtin
simulate=False, reset=False, xpath_expression=None, **kw):
"""
A node is updated with some xupdate
......@@ -278,8 +279,8 @@ class ERP5Conduit(XMLSyncUtilsMixin):
if xml is None:
return []
xml = self.convertToXml(xml)
syncml_logger.debug("updateNode with xml %s"
% (etree.tostring(xml, pretty_print=True)))
syncml_logger.debug("updateNode with xml %s",
etree.tostring(xml, pretty_print=True))
if xml.tag == '{%s}modifications' % xml.nsmap.get('xupdate'):
conflict_list += self.applyXupdate(object=object,
xupdate=xml,
......@@ -371,21 +372,21 @@ class ERP5Conduit(XMLSyncUtilsMixin):
if data_type not in DATA_TYPE_LIST:
conflict.edit(local_value=current_data,
remote_value=data)
syncml_logger.info("Generated a conflict for %s" % (keyword,))
syncml_logger.info("Generated a conflict for %s", keyword)
conflict_list += [conflict]
else:
syncml_logger.info("UpdateNode : no previous xml founds or force")
# We will now apply the argument with the method edit
if args and (not isConflict or force) and (not simulate or reset):
syncml_logger.info("calling updateContent : %s" % (args))
syncml_logger.info("calling updateContent : %s", args)
self._updateContent(object=context, **args)
# It is sometimes required to do something after an edit
if getattr(context, 'manage_afterEdit', None) is not None:
context.manage_afterEdit()
else:
syncml_logger.warning("did not call updateContent on %s" % (context))
syncml_logger.warning("did not call updateContent on %s", context)
else:
syncml_logger.info("UpdateNode : not editable property %s" % (keyword))
syncml_logger.info("UpdateNode : not editable property %s", keyword)
# Specific cases of update
if keyword == 'object':
......@@ -411,7 +412,7 @@ class ERP5Conduit(XMLSyncUtilsMixin):
force=force, simulate=simulate,
reset=reset, **kw)['conflict_list']
else:
syncml_logger.warning("UpdateNode : not a property %s" % (etree.tostring(xml, pretty_print=True),))
syncml_logger.warning("UpdateNode : not a property %s", etree.tostring(xml, pretty_print=True))
return conflict_list
security.declareProtected(Permissions.AccessContentsInformation,
......@@ -575,7 +576,7 @@ class ERP5Conduit(XMLSyncUtilsMixin):
security.declareProtected(Permissions.AccessContentsInformation,
'getXMLFromObjectWithId')
def getXMLFromObjectWithId(self, object, xml_mapping, context_document=None):
def getXMLFromObjectWithId(self, object, xml_mapping, context_document=None): # pylint: disable=redefined-builtin
"""
return the xml with Id of Object
"""
......@@ -593,7 +594,7 @@ class ERP5Conduit(XMLSyncUtilsMixin):
security.declareProtected(Permissions.AccessContentsInformation,
'getXMLFromObjectWithGid')
def getXMLFromObjectWithGid(self, object, gid, xml_mapping, as_string=True, context_document=None):
def getXMLFromObjectWithGid(self, object, gid, xml_mapping, as_string=True, context_document=None): # pylint: disable=redefined-builtin
"""
return the xml with Gid of Object
"""
......@@ -603,7 +604,7 @@ class ERP5Conduit(XMLSyncUtilsMixin):
security.declareProtected(Permissions.AccessContentsInformation,
'getXMLFromObjectWithRid')
def getXMLFromObjectWithRid(self, object, rid, xml_mapping, as_string=True, context_document=None):
def getXMLFromObjectWithRid(self, object, rid, xml_mapping, as_string=True, context_document=None): # pylint: disable=redefined-builtin
"""
return the xml with Rid of Object
"""
......@@ -643,7 +644,7 @@ class ERP5Conduit(XMLSyncUtilsMixin):
return xml.get('type')
security.declareProtected(Permissions.ModifyPortalContent, 'newObject')
def newObject(self, object=None, xml=None, simulate=False,
def newObject(self, object=None, xml=None, simulate=False, # pylint: disable=redefined-builtin
reset_local_roles=True, reset_workflow=True):
"""
modify the object with datas from
......@@ -681,7 +682,7 @@ class ERP5Conduit(XMLSyncUtilsMixin):
security.declareProtected(Permissions.AccessContentsInformation,
'afterNewObject')
def afterNewObject(self, object):
def afterNewObject(self, object): # pylint: disable=redefined-builtin
"""Overloadable method
"""
pass
......@@ -730,15 +731,15 @@ class ERP5Conduit(XMLSyncUtilsMixin):
select_id = select_id[:select_id.find("'",1)+1]
else:
s_place = len(attribute)
property = attribute[:s_place].strip('/')
result += property
property_ = attribute[:s_place].strip('/')
result += property_
if select_id is not None:
result += ' id=%s' % select_id
result += '>'
xml_string = self.nodeToString(xml)
maxi = xml_string.find('>')+1
result += xml_string[maxi:xml_string.find('</%s>' % xml.xpath('name()'))]
result += '</%s>' % (property)
result += '</%s>' % (property_)
#LOG('getElementFromXupdate, result:',0,repr(result))
return self.convertToXml(result)
return xml
......@@ -800,7 +801,7 @@ class ERP5Conduit(XMLSyncUtilsMixin):
security.declareProtected(Permissions.ModifyPortalContent, 'applyXupdate')
def applyXupdate(self, object=None, xupdate=None, previous_xml=None, **kw):
def applyXupdate(self, object=None, xupdate=None, previous_xml=None, **kw): # pylint: disable=redefined-builtin
"""
Parse the xupdate and then it will call the conduit
"""
......@@ -918,7 +919,7 @@ class ERP5Conduit(XMLSyncUtilsMixin):
return addable
security.declareProtected(Permissions.ModifyPortalContent, 'constructContent')
def constructContent(self, object, object_id, portal_type):
def constructContent(self, object, object_id, portal_type): # pylint: disable=redefined-builtin
"""
This allows to specify how to construct a new content.
This is really usefull if you want to write your
......@@ -930,7 +931,7 @@ class ERP5Conduit(XMLSyncUtilsMixin):
return subobject, True, True
security.declareProtected(Permissions.ModifyPortalContent, 'addWorkflowNode')
def addWorkflowNode(self, object, xml, simulate):
def addWorkflowNode(self, object, xml, simulate): # pylint: disable=redefined-builtin
"""
This allows to specify how to handle the workflow information.
This is really usefull if you want to write your own Conduit.
......@@ -963,7 +964,7 @@ class ERP5Conduit(XMLSyncUtilsMixin):
return conflict_list
security.declareProtected(Permissions.ModifyPortalContent, 'addLocalRoleNode')
def addLocalRoleNode(self, object, xml):
def addLocalRoleNode(self, object, xml): # pylint: disable=redefined-builtin
"""
This allows to specify how to handle the local role information.
This is really usefull if you want to write your own Conduit.
......@@ -981,7 +982,7 @@ class ERP5Conduit(XMLSyncUtilsMixin):
object.manage_setLocalGroupRoles(user, roles)
security.declareProtected(Permissions.ModifyPortalContent, 'addLocalPermissionNode')
def addLocalPermissionNode(self, object, xml):
def addLocalPermissionNode(self, object, xml): # pylint: disable=redefined-builtin
"""
This allows to specify how to handle the local permision informations.
This is really usefull if you want to write your own Conduit.
......@@ -1008,16 +1009,16 @@ class ERP5Conduit(XMLSyncUtilsMixin):
# example document_conversion_interaction_workflow defined for _setData())
# making the source and destination XML representation different.
@WorkflowMethod.disable
def editDocument(self, object=None, **kw):
def editDocument(self, object=None, **kw): # pylint: disable=redefined-builtin
"""
This is the default editDocument method. This method
can easily be overwritten.
"""
syncml_logger.debug("editing document %s with %s" % (object, kw))
syncml_logger.debug("editing document %s with %s", object, kw)
object._edit(**kw)
security.declareProtected(Permissions.ModifyPortalContent, 'getProperty')
def getProperty(self, object, kw):
def getProperty(self, object, kw): # pylint: disable=redefined-builtin
"""
This is the default getProperty method. This method
can easily be overwritten.
......@@ -1030,13 +1031,13 @@ class ERP5Conduit(XMLSyncUtilsMixin):
"""
return etree.tostring(node, encoding='utf-8', pretty_print=True)
def getGidFromObject(self, object):
def getGidFromObject(self, object): # pylint: disable=redefined-builtin
"""
return the Gid composed with the object informations
"""
return object.getId()
def _createContent(self, xml=None, object=None, object_id=None,
def _createContent(self, xml=None, object=None, object_id=None, # pylint: disable=redefined-builtin
sub_object=None, reset_local_roles=False,
reset_workflow=False, simulate=False, **kw):
"""
......@@ -1066,13 +1067,13 @@ class ERP5Conduit(XMLSyncUtilsMixin):
reset_workflow=reset_workflow)
return sub_object
def _updateContent(self, object=None, **args):
def _updateContent(self, object=None, **args): # pylint: disable=redefined-builtin
"""
This is the method for update the object
"""
return self.editDocument(object=object, **args)
def _deleteContent(self, object=None, object_id=None, **kw):
def _deleteContent(self, object=None, object_id=None, **kw): # pylint: disable=redefined-builtin
"""
This is the method for delete the object
"""
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Module Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>ERP5Conduit</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5SyncML.Conduit.ERP5Conduit</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>module.erp5.ERP5Conduit</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Module Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -29,7 +29,7 @@
from AccessControl import ClassSecurityInfo
from Products.ERP5SyncML.Conduit.ERP5Conduit import ERP5Conduit
from erp5.component.module.ERP5Conduit import ERP5Conduit
class ERP5ConduitTitleGid(ERP5Conduit):
......@@ -42,7 +42,7 @@ class ERP5ConduitTitleGid(ERP5Conduit):
# Declarative security
security = ClassSecurityInfo()
def getGidFromObject(self, object):
def getGidFromObject(self, object): # pylint: disable=redefined-builtin
"""
return the Gid composed of FirstName and LastName generate with the object
"""
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Module Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>ERP5ConduitTitleGid</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5SyncML.Conduit.ERP5ConduitTitleGid</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>module.erp5.ERP5ConduitTitleGid</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Module Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -27,7 +27,7 @@
#
##############################################################################
from Products.ERP5SyncML.Conduit.ERP5Conduit import ERP5Conduit
from erp5.component.module.ERP5Conduit import ERP5Conduit
from Products.ERP5Type import Permissions
from AccessControl import ClassSecurityInfo
......@@ -49,7 +49,7 @@ class ERP5DocumentConduit(ERP5Conduit):
security = ClassSecurityInfo()
security.declareProtected(Permissions.AccessContentsInformation, 'getGidFromObject')
def getGidFromObject(self, object):
def getGidFromObject(self, object): # pylint: disable=redefined-builtin
"""
return the Gid generate with the reference, object, language of the object
"""
......@@ -70,7 +70,6 @@ class ERP5DocumentConduit(ERP5Conduit):
else:
return WORKFLOW_ACTION_ADDABLE
addable = WORKFLOW_ACTION_ADDABLE
time = status.get('time')
for action in action_list:
this_one = WORKFLOW_ACTION_ADDABLE
# if time <= action.get('time'):
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Module Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>ERP5DocumentConduit</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5SyncML.Conduit.ERP5DocumentConduit</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>module.erp5.ERP5DocumentConduit</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Module Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -34,7 +34,7 @@ from cStringIO import StringIO
from AccessControl import ClassSecurityInfo
from zLOG import LOG
from Products.ERP5SyncML.Conduit.ERP5Conduit import ERP5Conduit
from erp5.component.module.ERP5Conduit import ERP5Conduit
from Products.ERP5Type import Permissions
from Products.CMFCore.utils import getToolByName
......@@ -53,12 +53,11 @@ class ERP5ShopOrderConduit(ERP5Conduit):
random.seed()
security.declareProtected(Permissions.ModifyPortalContent, 'constructContent')
def constructContent(self, object, object_id, docid, portal_type):
def constructContent(self, object, object_id, docid, portal_type): # pylint: disable=redefined-builtin,arguments-differ
"""
This is a redefinition of the original ERP5Conduit.constructContent function to
allow the creation of a ERP5 Sale Order instead of a Storever Shop Order.
"""
portal_types = getToolByName(object, 'portal_types')
subobject = None
new_object_id = object_id
if portal_type == 'Shop Order':
......@@ -283,7 +282,7 @@ class ERP5ShopOrderConduit(ERP5Conduit):
security.declarePrivate('updateObjProperty')
def updateObjProperty(self, object, property, kw, key):
def updateObjProperty(self, object, property, kw, key): # pylint: disable=redefined-builtin
"""
This function update the property of an object with a given value stored in a dictionnary. This function help the Conduit to make decision about the synchronization of values.
......@@ -296,10 +295,10 @@ class ERP5ShopOrderConduit(ERP5Conduit):
if kw.has_key(key):
new_value = kw[key]
if new_value != None:
if type(new_value) is type('s'):
if isinstance(new_value, str):
new_value = new_value.title()
current_value = eval('object.get' + property + '()')
current_value = getattr(object, 'get' + property)()
LOG("I have to run this >>>>>>>> ", 0, 'object.get' + property + '()')
LOG("current_value >>>>>>>> ", 0, repr(current_value))
......@@ -320,7 +319,7 @@ class ERP5ShopOrderConduit(ERP5Conduit):
security.declareProtected(Permissions.ModifyPortalContent, 'editDocument')
def editDocument(self, object=None, **kw):
def editDocument(self, object=None, **kw): # pylint: disable=redefined-builtin
"""
This function use the properties of the object to convert a Storever ShopOrder to an ERP5 SaleOrder.
"""
......@@ -478,7 +477,6 @@ class ERP5ShopOrderConduit(ERP5Conduit):
# We only need to be aware of data fusion between the previous and the current representation
# So we don't need to do something because the information fusion process take place below
LOG("The structure is the same. don't do anything >>>>>>>>",0,'')
pass
LOG("Person object >>>>>>>>",0,repr(person_object))
LOG("Organisation object >>>>>>>>",0,repr(org_object))
......@@ -628,9 +626,9 @@ class ERP5ShopOrderConduit(ERP5Conduit):
erp5_ship_id_word_list = self.str2id(service_id).split("_")
stor_ship_id_word_list = self.str2id(stor_ship_title).split("_")
erp5_ship_title_word_list = self.str2id(erp5_ship_title).split("_")
erp5_ship_id_word_list.sort(key=lambda x: str(x))
stor_ship_id_word_list.sort(key=lambda x: str(x))
erp5_ship_title_word_list.sort(key=lambda x: str(x))
erp5_ship_id_word_list.sort(key=str)
stor_ship_id_word_list.sort(key=str)
erp5_ship_title_word_list.sort(key=str)
if stor_ship_id_word_list in (erp5_ship_id_word_list, erp5_ship_title_word_list):
shipment_id = service_id
LOG("Service found with method 3 ! >>>>>>>>", 0, repr(shipment_id))
......@@ -676,8 +674,6 @@ class ERP5ShopOrderConduit(ERP5Conduit):
# The object is an OrderLine
else:
# Find the product folder
product_path = erp5_site_path + '/product'
product_folder = erp5_site.restrictedTraverse(product_path)
# Find the parent order object
parent_order_object = object.aq_parent
......@@ -787,7 +783,7 @@ class ERP5ShopOrderConduit(ERP5Conduit):
LOG('editDocument, cat_base',0,cat_base)
base_cat_object = portal_cat.resolveCategory(cat_base)
cat_list = base_cat_object.getCategoryChildIdItemList()
for (category, category_bis) in cat_list:
for (category, _) in cat_list:
if self.str2id(option) == category:
customer_product_variation_list[category] = cat_base + '/' + category
if cat_base not in customer_product_base_variation_list:
......@@ -799,7 +795,7 @@ class ERP5ShopOrderConduit(ERP5Conduit):
if option_is_variant == None:
customer_product_option_list[option] = priced_list[option]
if len(customer_product_option_list) + len(customer_product_variation_list) != len(priced_list):
LOG('>>>>>>> Wrong repartition of the customer priced list', 200)
LOG('>>>>>>> Wrong repartition of the customer priced list', 200, '')
LOG('>>>>>> Customer product option priced list: ', 0, repr(customer_product_option_list))
LOG('>>>>>> Customer product variation priced list: ', 0, repr(customer_product_variation_list))
LOG('>>>>>> Customer product base variation list: ', 0, repr(customer_product_base_variation_list))
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Module Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>ERP5ShopOrderConduit</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5SyncML.Conduit.ERP5ShopOrderConduit</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>module.erp5.ERP5ShopOrderConduit</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Module Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -29,9 +29,9 @@
from AccessControl import ClassSecurityInfo
from Products.ERP5SyncML.Conduit.VCardConduit import VCardConduit
from erp5.component.module.VCardConduit import VCardConduit
# pylint: disable=abstract-method
class SharedVCardConduit(VCardConduit):
"""
A conduit is in charge to read data from a particular structure,
......@@ -45,7 +45,7 @@ class SharedVCardConduit(VCardConduit):
# Declarative security
security = ClassSecurityInfo()
def getGidFromObject(self, object):
def getGidFromObject(self, object): # pylint: disable=redefined-builtin
"""
return the Gid composed of FirstName_LastName generate with the object
"""
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Module Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>SharedVCardConduit</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5SyncML.Conduit.SharedVCardConduit</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>module.erp5.SharedVCardConduit</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Module Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -50,4 +50,4 @@ REPLACE_ACTION = 'Replace'
ACTIVITY_PRIORITY = 5
class SynchronizationError(Exception):
pass
pass
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Module Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>SyncMLConstant</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5SyncML.SyncMLConstant</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>module.erp5.SyncMLConstant</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Module Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -27,31 +27,31 @@
from logging import getLogger
from Products.ERP5SyncML.Engine.EngineMixin import EngineMixin
from Products.ERP5SyncML.SyncMLConstant import ACTIVITY_PRIORITY
from erp5.component.mixin.SyncMLEngineMixin import SyncMLEngineMixin
from erp5.component.module.SyncMLConstant import ACTIVITY_PRIORITY
from Products.ERP5.ERP5Site import getSite
syncml_logger = getLogger('ERP5SyncML')
class SyncMLAsynchronousEngine(EngineMixin):
class SyncMLAsynchronousEngine(SyncMLEngineMixin):
""" Implement synchronization engine using activities """
def processClientSynchronization(self, syncml_request, subscription):
""" Global method that process the package 3, 4 & 5 of SyncML DS Protocol """
syncml_logger.info("xxx Client processing data from server (%s) xxx"
% (subscription.getSynchronizationState()))
syncml_logger.info("\tstatus %s, sync %s, final %s"
% (len(syncml_request.status_list),
len(syncml_request.sync_command_list),
syncml_request.isFinal))
syncml_logger.info("xxx Client processing data from server (%s) xxx",
subscription.getSynchronizationState())
syncml_logger.info("\tstatus %s, sync %s, final %s",
len(syncml_request.status_list),
len(syncml_request.sync_command_list),
syncml_request.isFinal)
# We must log in with user defined
subscription._loginUser()
if syncml_request.alert_list:
syncml_logger.warning("Got an alert from server not processed : %s"
% (syncml_request.alert_list,))
syncml_logger.warning("Got an alert from server not processed : %s",
syncml_request.alert_list)
# Must check what server tell about database synchronization
# and update the mode if required
......@@ -98,8 +98,8 @@ class SyncMLAsynchronousEngine(EngineMixin):
self.runApplySyncCommand(subscription=subscription,
syncml_request=syncml_request,
tag=tag)
syncml_logger.info("-> Client apply command in %d activities"
% (len(syncml_request.sync_command_list)))
syncml_logger.info("-> Client apply command in %d activities",
len(syncml_request.sync_command_list))
if syncml_request.isFinal:
if not syncml_response:
syncml_response = subscription.generateBaseResponse()
......@@ -153,10 +153,10 @@ class SyncMLAsynchronousEngine(EngineMixin):
# syncml_response = subscriber.getLastSentMessage("") # XXX
else:
syncml_logger.info("xxx Server processing data from client xxx")
syncml_logger.info("\tstatus %s, sync %s, final %s"
% (len(syncml_request.status_list),
syncml_logger.info("\tstatus %s, sync %s, final %s",
len(syncml_request.status_list),
len(syncml_request.sync_command_list),
syncml_request.isFinal))
syncml_request.isFinal)
# we log the user authenticated to do the synchronization with him
if subscriber.getAuthenticationState() == 'logged_in':
subscriber._loginUser()
......@@ -200,8 +200,8 @@ class SyncMLAsynchronousEngine(EngineMixin):
# First server process sync commands : Pkg 3 of the sync process
self.runApplySyncCommand(subscription=subscriber,
syncml_request=syncml_request, tag=tag)
syncml_logger.info("-> Server apply command in %d activities"
% (len(syncml_request.sync_command_list)))
syncml_logger.info("-> Server apply command in %d activities",
len(syncml_request.sync_command_list))
if syncml_request.isFinal:
# Server then sends its modifications
subscriber.sendModifications()
......@@ -226,7 +226,7 @@ class SyncMLAsynchronousEngine(EngineMixin):
activity_created = self.runGetAndActivate(subscription=subscriber,
after_method_id=after_method_id,
tag=tag)
syncml_logger.info("X--> Server is sending modifications in activities %s" %(activity_created))
syncml_logger.info("X--> Server is sending modifications in activities %s", activity_created)
if not activity_created:
# Server has no modification to send to client, return final message
syncml_logger.info("X-> Server sending final message")
......@@ -281,7 +281,7 @@ class SyncMLAsynchronousEngine(EngineMixin):
id_count=len(syncml_request.sync_command_list))
response_id_list.reverse()
else:
response_id_list = [None for x in
response_id_list = [None for _ in
xrange(len(syncml_request.sync_command_list))]
split = getSite().portal_preferences.getPreferredSyncActionPerActivityCount()
if not split: # We do not use activities
......@@ -306,7 +306,7 @@ class SyncMLAsynchronousEngine(EngineMixin):
"group_method_cost" : 1./float(split),
}
for action in syncml_request.sync_command_list:
syncml_logger.info("---> launch action in activity %s" %(action,))
syncml_logger.info("---> launch action in activity %s", action)
activate(**activate_kw).applySyncCommand(
response_message_id=response_id_list.pop(),
activate_kw=activate_kw,
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Module Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>SyncMLEngineAsynchronous</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5SyncML.Engine.AsynchronousEngine</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>module.erp5.SyncMLEngineAsynchronous</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Module Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -27,12 +27,12 @@
from logging import getLogger
from Products.ERP5SyncML.Engine.EngineMixin import EngineMixin
from Products.ERP5SyncML.SyncMLConstant import SynchronizationError
from erp5.component.mixin.SyncMLEngineMixin import SyncMLEngineMixin
from erp5.component.module.SyncMLConstant import SynchronizationError
syncml_logger = getLogger('ERP5SyncML')
class SyncMLSynchronousEngine(EngineMixin):
class SyncMLSynchronousEngine(SyncMLEngineMixin):
"""
Implement a synchronous engine wait for IO
"""
......@@ -41,16 +41,16 @@ class SyncMLSynchronousEngine(EngineMixin):
""" Global method that process the package 3 of SyncML DS Protocol """
syncml_logger.info("xxx Client processing data from server xxx")
syncml_logger.info("\tstatus %s, sync %s, final %s"
% (len(syncml_request.status_list),
len(syncml_request.sync_command_list),
syncml_request.isFinal))
syncml_logger.info("\tstatus %s, sync %s, final %s",
len(syncml_request.status_list),
len(syncml_request.sync_command_list),
syncml_request.isFinal)
# Process sync logged in
subscription._loginUser()
if syncml_request.alert_list:
syncml_logger.warning("Got an alert from server not processed : %s"
% (syncml_request.alert_list,))
syncml_logger.warning("Got an alert from server not processed : %s",
syncml_request.alert_list)
# Must check what server tell about database synchronization
# and update the mode if required
......@@ -61,8 +61,8 @@ class SyncMLSynchronousEngine(EngineMixin):
self._readStatusList(syncml_request, subscription, syncml_response)
except SynchronizationError:
# Looks like we process an already received message
syncml_logger.error("%s does no process packet due to error"
% (subscription.getRelativeUrl()))
syncml_logger.error("%s does no process packet due to error",
subscription.getRelativeUrl())
return
if syncml_request.isFinal and \
......@@ -88,7 +88,7 @@ class SyncMLSynchronousEngine(EngineMixin):
# Delete message will contain final tag
subscription.getDeletedSyncMLData(syncml_response=syncml_response)
syncml_logger.info("-> Client sendind modification, finished %s" % (finished,))
syncml_logger.info("-> Client sendind modification, finished %s", finished)
if finished:
# Will then start processing sync commands from server
subscription.processSyncRequest()
......@@ -101,8 +101,8 @@ class SyncMLSynchronousEngine(EngineMixin):
syncml_request=syncml_request,
syncml_response=syncml_response,
simulate=False)
syncml_logger.info("-> Client sending %s notification of object synchronized"
% (syncml_response.sync_confirmation_counter))
syncml_logger.info("-> Client sending %s notification of object synchronized",
syncml_response.sync_confirmation_counter)
if syncml_request.isFinal:
# Notify that all modifications were applied
syncml_response.addFinal()
......@@ -137,10 +137,10 @@ class SyncMLSynchronousEngine(EngineMixin):
syncml_response = subscriber.getLastSentMessage("") # XXX
else:
syncml_logger.info("xxx Server processing data from client xxx")
syncml_logger.info("\tstatus %s, sync %s, final %s"
% (len(syncml_request.status_list),
syncml_logger.info("\tstatus %s, sync %s, final %s",
len(syncml_request.status_list),
len(syncml_request.sync_command_list),
syncml_request.isFinal))
syncml_request.isFinal)
# we log the user authenticated to do the synchronization with him
if subscriber.getAuthenticationState() == 'logged_in':
subscriber._loginUser()
......@@ -187,8 +187,8 @@ class SyncMLSynchronousEngine(EngineMixin):
syncml_response=syncml_response,
simulate=True)
syncml_logger.info("-> Server sending %s notification of sync"
% (syncml_response.sync_confirmation_counter))
syncml_logger.info("-> Server sending %s notification of sync",
syncml_response.sync_confirmation_counter)
if syncml_request.isFinal:
# Server will now send its modifications
subscriber.sendModifications()
......@@ -211,7 +211,7 @@ class SyncMLSynchronousEngine(EngineMixin):
# Delete message will contain final tag
subscriber.getDeletedSyncMLData(syncml_response=syncml_response)
syncml_logger.info("-> Server sendind data, finished %s" % (finished,))
syncml_logger.info("-> Server sendind data, finished %s", finished)
if finished:
subscriber.waitNotifications()
# Do not go into finished here as we must wait for
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Module Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>SyncMLEngineSynchronous</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5SyncML.Engine.SynchronousEngine</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>module.erp5.SyncMLEngineSynchronous</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Module Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -29,9 +29,9 @@ from lxml.builder import ElementMaker
from lxml.etree import Element
from lxml import etree
from Products.ERP5SyncML.XMLSyncUtils import resolveSyncmlStatusCode, \
from erp5.component.module.XMLSyncUtils import resolveSyncmlStatusCode, \
encode, resolveSyncmlAlertCode
from Products.ERP5SyncML.SyncMLConstant import SYNCML_NAMESPACE, NSMAP
from erp5.component.module.SyncMLConstant import SYNCML_NAMESPACE, NSMAP
parser = etree.XMLParser(remove_blank_text=True)
E = ElementMaker(namespace=SYNCML_NAMESPACE, nsmap=NSMAP)
......@@ -224,6 +224,7 @@ class SyncMLResponse(object):
receiving a challenge message
"""
raise NotImplementedError("To review")
"""
# create element 'SyncML' with a default namespace
xml = E.SyncML()
# syncml header
......@@ -257,6 +258,7 @@ class SyncMLResponse(object):
xml_string = etree.tostring(xml, encoding='utf-8', xml_declaration=True,
pretty_print=True)
self.data_append(xml_string)
"""
def addPutMessage(self,subscription, markup='Put',
cmd_ref=None, message_id=None):
......@@ -277,6 +279,7 @@ class SyncMLResponse(object):
Both must be able to handle and process these informations
"""
return
"""
# XXX-Aurel : must be reviewed according to specification
# This part can be skipped for now
conduit = subscription.getConduit()
......@@ -330,6 +333,7 @@ class SyncMLResponse(object):
E.SyncType('6')
))
self.data_append(xml)
"""
def addSyncCommand(self, sync_command, gid, data, media_type, more_data):
......@@ -583,8 +587,8 @@ class SyncMLRequest(object):
data = sync_command.xpath('string(.//syncml:Item/syncml:Data)',
namespaces=self.data.nsmap)
if isinstance(data, etree.CDATA):
parser = etree.XMLParser(strip_cdata=False)
cdata = etree.XML(data, parser)
parser_ = etree.XMLParser(strip_cdata=False)
cdata = etree.XML(data, parser_)
data = cdata.text
# XXX this is unicode and can be a problem for activity
sync_command_kw["raw_data"] = data
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Module Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>SyncMLMessage</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5SyncML.SyncMLMessage</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>module.erp5.SyncMLMessage</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Module Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Module Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>SyncMLTransportERP5</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5SyncML.Transport.ERP5</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>module.erp5.SyncMLTransportERP5</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Module Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -25,10 +25,7 @@
#
##############################################################################
from HTTP import ConnectionError
from erp5.component.module.SyncMLTransportHTTP import ConnectionError
class FileTransport:
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Module Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>SyncMLTransportFile</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5SyncML.Transport.File</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>module.erp5.SyncMLTransportFile</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Module Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -63,7 +63,7 @@ class HTTPTransport:
def send(self, to_url, data, sync_id, content_type):
syncml_logger.debug("HTTP.send : %s" %(to_url,))
syncml_logger.debug("HTTP.send : %s", to_url)
data = {
'text' : data,
'sync_id': sync_id
......@@ -72,5 +72,5 @@ class HTTPTransport:
headers=self.getHeaders(content_type, data),
timeout=60,
proxies=self.getProxyMapping())
syncml_logger.debug("Status code : %s - %s" %(r.status_code, r.headers))
syncml_logger.debug("Status code : %s - %s", r.status_code, r.headers)
r.raise_for_status()
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Module Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>SyncMLTransportHTTP</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5SyncML.Transport.HTTP</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>module.erp5.SyncMLTransportHTTP</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Module Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -25,11 +25,9 @@
#
##############################################################################
from HTTP import ConnectionError
from erp5.component.module.SyncMLTransportHTTP import ConnectionError
from Products.ERP5.ERP5Site import getSite
class MailTransport:
def send(self, from_url, to_url, xml, sync_id, content_type):
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Module Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>SyncMLTransportMail</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5SyncML.Transport.Mail</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>module.erp5.SyncMLTransportMail</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Module Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -68,20 +68,20 @@ class PdataHelper(persistent.Persistent):
n = self._max_len
if isinstance(value, (str, unicode)):
if isinstance(value, unicode):
value = value.encode('utf-8')
size=len(value)
if size < n:
return Pdata(value), size
# Big string: cut it into smaller chunks
value = StringIO(value)
if isinstance(value, unicode):
value = value.encode('utf-8')
size=len(value)
if size < n:
return Pdata(value), size
# Big string: cut it into smaller chunks
value = StringIO(value)
if isinstance(value, FileUpload) and not value:
raise ValueError, 'File not specified'
raise ValueError, 'File not specified'
if isinstance(value, Pdata):
size = self._read_size_from_pdata(value)
return value, size
size = self._read_size_from_pdata(value)
return value, size
# Clear md5sum to force refreshing
self.md5sum = None
......@@ -93,66 +93,66 @@ class PdataHelper(persistent.Persistent):
size=end=value.tell()
if size <= 2*n:
seek(0)
return Pdata(read(size)), size
seek(0)
return Pdata(read(size)), size
# Make sure we have an _p_jar, even if we are a new object, by
# doing a sub-transaction commit.
transaction.savepoint(optimistic=True)
if persistent_object._p_jar is None:
# Ugh
seek(0)
return Pdata(read(size)), size
# Ugh
seek(0)
return Pdata(read(size)), size
# Now we're going to build a linked list from back
# to front to minimize the number of database updates
# and to allow us to get things out of memory as soon as
# possible.
next = None
next_ = None
while end > 0:
pos = end-n
if pos < n:
pos = 0 # we always want at least n bytes
seek(pos)
# Create the object and assign it a next pointer
# in the same transaction, so that there is only
# a single database update for it.
data = Pdata(read(end-pos))
persistent_object._p_jar.add(data)
data.next = next
# Save the object so that we can release its memory.
transaction.savepoint(optimistic=True)
data._p_deactivate()
# The object should be assigned an oid and be a ghost.
assert data._p_oid is not None
assert data._p_state == -1
next = data
end = pos
return next, size
pos = end-n
if pos < n:
pos = 0 # we always want at least n bytes
seek(pos)
# Create the object and assign it a next pointer
# in the same transaction, so that there is only
# a single database update for it.
data = Pdata(read(end-pos))
persistent_object._p_jar.add(data)
data.next = next_
# Save the object so that we can release its memory.
transaction.savepoint(optimistic=True)
data._p_deactivate()
# The object should be assigned an oid and be a ghost.
assert data._p_oid is not None
assert data._p_state == -1
next_ = data
end = pos
return next_, size
def _digest_md5_hash_from_pdata(self, pdata):
"""Compute hash part by part
"""
md5_hash = md5()
next = pdata
while next is not None:
md5_hash.update(next.data)
next = next.next
next_ = pdata
while next_ is not None:
md5_hash.update(next_.data)
next_ = next_.next
return md5_hash.hexdigest()
def _read_size_from_pdata(self, pdata):
"""Compute size part by part
"""
size = 0
next = pdata
while next is not None:
size += len(next.data)
next = next.next
next_ = pdata
while next_ is not None:
size += len(next_.data)
next_ = next_.next
return size
def __len__(self):
......@@ -186,9 +186,9 @@ class PdataHelper(persistent.Persistent):
of a Pdata chains
"""
pdata = self._data
next = pdata.next
next_ = pdata.next
while next is not None:
pdata = next
next = pdata.next
while next_ is not None:
pdata = next_
next_ = pdata.next
return pdata
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Module Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>SyncMLUtils</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5SyncML.Utils</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>module.erp5.SyncMLUtils</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Module Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -27,7 +27,7 @@
#
##############################################################################
from Products.ERP5SyncML.Conduit.ERP5Conduit import ERP5Conduit
from erp5.component.module.ERP5Conduit import ERP5Conduit
from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions
import difflib
......@@ -48,7 +48,7 @@ class VCardConduit(ERP5Conduit):
security.declareProtected(Permissions.ModifyPortalContent, 'addNode')
def addNode(self, xml=None, object=None, previous_xml=None,
def addNode(self, xml=None, object=None, previous_xml=None, # pylint: disable=redefined-builtin
object_id=None, sub_object=None, force=0, simulate=0, **kw):
"""
add a new person corresponding to the vcard
......@@ -61,8 +61,7 @@ class VCardConduit(ERP5Conduit):
portal_type = 'Person' #the VCard can just use Person
if sub_object is None:
new_object, reset_local_roles, reset_workflow =\
ERP5Conduit.constructContent(self, object, object_id, portal_type)
new_object, _, _ = ERP5Conduit.constructContent(self, object, object_id, portal_type)
else: #if the object exist, it juste must be update
new_object = sub_object
#LOG('addNode', 0, 'new_object:%s, sub_object:%s' % (new_object, sub_object))
......@@ -75,7 +74,7 @@ class VCardConduit(ERP5Conduit):
return {'conflict_list':[], 'object': new_object}
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, # pylint: disable=redefined-builtin
simulate=0, **kw):
"""
A node is deleted
......@@ -88,7 +87,7 @@ class VCardConduit(ERP5Conduit):
return []
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, # pylint: disable=redefined-builtin
simulate=0, **kw):
"""
A node is updated
......@@ -165,12 +164,12 @@ class VCardConduit(ERP5Conduit):
vcard_list = vcard.split('\n')
for vcard_line in vcard_list:
if ':' in vcard_line:
property, property_value = vcard_line.split(':')
property_, property_value = vcard_line.split(':')
property_value_list = property_value.split(';')
property_parameters_list = []
property_name = ''
if ';' in property:
property_list = property.split(';')
if ';' in property_:
property_list = property_.split(';')
property_name = property_list[0] #the property name is the 1st element
if len(property_list) > 1 and property_list[1] != '':
property_parameters_list = property_list[1:len(property_list)]
......@@ -192,7 +191,7 @@ class VCardConduit(ERP5Conduit):
property_value_list)
else:
property_name=property
property_name=property_
if isinstance(property_name, unicode):
property_name = property_name.encode('utf-8')
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Module Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>VCardConduit</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5SyncML.Conduit.VCardConduit</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>module.erp5.VCardConduit</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Module Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -37,7 +37,7 @@ from zLOG import LOG, INFO
from ERP5Diff import ERP5Diff
from DateTime import DateTime
from SyncMLConstant import SYNCML_NAMESPACE, NSMAP, MAX_LEN
from erp5.component.module.SyncMLConstant import SYNCML_NAMESPACE, NSMAP, MAX_LEN
from Products.ERP5.ERP5Site import getSite
E = ElementMaker(namespace=SYNCML_NAMESPACE, nsmap=NSMAP)
......@@ -51,7 +51,7 @@ def buildAnchorFromDate(date):
return date
def encode(format, string_to_encode):
def encode(format, string_to_encode): # pylint: disable=redefined-builtin
"""
return the string_to_encode encoded with format format
"""
......@@ -65,7 +65,7 @@ def encode(format, string_to_encode):
raise ValueError, "Sorry, the server ask for the format %s but \
it's unknow or not implemented" % format
def decode(format, string_to_decode):
def decode(format, string_to_decode): # pylint: disable=redefined-builtin
"""
return the string_to_decode decoded with format format
"""
......@@ -80,7 +80,7 @@ def decode(format, string_to_decode):
raise ValueError, "Sorry, the format %s is unknow or \
not implemented" % format
def isDecodeEncodeTheSame(string_encoded, string_decoded, format):
def isDecodeEncodeTheSame(string_encoded, string_decoded, format): # pylint: disable=redefined-builtin
"""
return True if the string_encoded is equal to string_decoded encoded
in format
......@@ -121,7 +121,7 @@ def getConduitByName(conduit_name):
Get Conduit Object by given name.
The Conduit can be located in Any Products according to naming Convention
Products.<Product Name>.Conduit.<Conduit Module> ,if conduit_name equal module's name.
By default Conduit must be defined in Products.ERP5SyncML.Conduit.<Conduit Module>
By default Conduit must be defined as ZODB Components (erp5.component.module.<Conduit Module>)
Conduit can also be defined as Extension to have it editable through the web, in this
case its definition must be Extensions.<Conduit Module>
"""
......@@ -136,9 +136,7 @@ def getConduitByName(conduit_name):
conduit_module = __import__("erp5.component."+conduit_name, globals(), locals(), [''])
conduit_name = conduit_name.split('.')[-1]
else:
from Products.ERP5SyncML import Conduit
conduit_module = __import__('.'.join([Conduit.__name__, conduit_name]),
globals(), locals(), [''])
conduit_module = __import__('erp5.component.module.'+conduit_name, globals(), locals(), [''])
conduit_instance = getattr(conduit_module, conduit_name)()
return conduit_instance
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Module Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>XMLSyncUtils</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5SyncML.XMLSyncUtils</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>module.erp5.XMLSyncUtils</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Module Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -26,7 +26,7 @@
#
##############################################################################
from Products.ERP5SyncML.XMLSyncUtils import XMLSyncUtilsMixin
from erp5.component.module.XMLSyncUtils import XMLSyncUtilsMixin
from xml.dom.ext.reader.Sax2 import FromXml
class XupdateUtils(XMLSyncUtilsMixin):
......@@ -35,7 +35,7 @@ class XupdateUtils(XMLSyncUtilsMixin):
this is the place where we should parse xupdate data.
"""
def applyXupdate(self, object=None, xupdate=None, conduit=None, force=0, **kw):
def applyXupdate(self, object=None, xupdate=None, conduit=None, force=0, **kw): # pylint: disable=redefined-builtin
"""
Parse the xupdate and then it will call the conduit
"""
......@@ -44,7 +44,6 @@ class XupdateUtils(XMLSyncUtilsMixin):
xupdate = FromXml(xupdate)
for subnode in xupdate:
selection_name = ''
if subnode.xpath('name()') in self.XUPDATE_INSERT_OR_ADD:
conflict_list.extend(conduit.addNode(xml=subnode, object=object, \
force=force, **kw))
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Module Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>XupdateUtils</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5SyncML.XupdateUtils</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>module.erp5.XupdateUtils</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Module Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -99,5 +99,4 @@ class TestERP5SyncMLMixin(ERP5TypeTestCase):
portal_type="SyncML Subscription")
for subscription in subscription_list:
if self.portal.portal_workflow.isTransitionPossible(subscription, 'validate'):
subscription.validate()
subscription.validate()
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Module Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>testERP5SyncMLMixin</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5SyncML.tests.testERP5SyncMLMixin</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>module.erp5.testERP5SyncMLMixin</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Module Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -36,11 +36,12 @@ from AccessControl.SecurityManagement import newSecurityManager
from Products.ERP5Type.tests.runUnitTest import tests_home
from Products.ERP5Type.tests.utils import FileUpload
from Products.ERP5SyncML.Tool import SynchronizationTool
from Products.ERP5SyncML.tests.testERP5SyncML import TestERP5SyncMLMixin
from Products.ERP5SyncML.Document import SyncMLSubscription
from erp5.component.tool import SynchronizationTool
from erp5.component.test.testERP5SyncML import TestERP5SyncMLMixin
from erp5.component.document import SyncMLSubscription
test_files = os.path.join(os.path.dirname(__file__), 'test_document')
import Products.ERP5.tests
test_files = os.path.join(os.path.dirname(Products.ERP5.tests.__file__), 'test_data')
FILENAME_REGULAR_EXPRESSION = "(?P<reference>[A-Z]{3,10})-\
(?P<language>[a-z]{2})-(?P<version>[0-9]{3})"
REFERENCE_REGULAR_EXPRESSION = "(?P<reference>[A-Z]{3,10})(-\
......@@ -138,12 +139,12 @@ class TestERP5DocumentSyncMLMixin(TestERP5SyncMLMixin):
def clearFiles(self):
# reset files, because we do sync by files
for filename in self.subscription_url.values():
file = open(filename[len('file:/'):], 'w')
file.write('')
file.close()
file = open(self.publication_url[len('file:/'):], 'w')
file.write('')
file.close()
file_ = open(filename[len('file:/'):], 'w')
file_.write('')
file_.close()
file_ = open(self.publication_url[len('file:/'):], 'w')
file_.write('')
file_.close()
def setSystemPreferences(self):
......@@ -253,16 +254,16 @@ class TestERP5DocumentSyncMLMixin(TestERP5SyncMLMixin):
self.createDocumentModules()
document_server = self.getDocumentServer()
#plain text document
for id in self.ids[:self.id_max_text]:
reference = "Test-Text-%s" % (id,)
self.createDocument(id=id, file_name=self.filename_text, reference=reference)
for id_ in self.ids[:self.id_max_text]:
reference = "Test-Text-%s" % (id_,)
self.createDocument(id=id_, file_name=self.filename_text, reference=reference)
self.commit()
nb_document = len(document_server.objectValues())
self.assertEqual(nb_document, len(self.ids[:self.id_max_text]))
#binary document
for id in self.ids[self.id_max_text:]:
reference = "Test-Odt-%s" % (id, )
self.createDocument(id=id, file_name=self.filename_odt, reference=reference)
for id_ in self.ids[self.id_max_text:]:
reference = "Test-Odt-%s" % (id_, )
self.createDocument(id=id_, file_name=self.filename_odt, reference=reference)
self.tic()
nb_document = len(document_server.objectValues())
self.assertEqual(nb_document, len(self.ids))
......@@ -279,22 +280,22 @@ class TestERP5DocumentSyncMLMixin(TestERP5SyncMLMixin):
kw = {'reference': self.reference1, 'Version': self.version1,
'Language': self.language1, 'Description': self.description1}
document_text.edit(**kw)
file = makeFileUpload(self.filename_text)
document_text.edit(file=file)
file_ = makeFileUpload(self.filename_text)
document_text.edit(file=file_)
self.tic()
document_pdf = document_server.newContent(id=self.id2,
portal_type='PDF')
kw = {'reference': self.reference2, 'Version': self.version2,
'Language': self.language2, 'Description': self.description2}
document_pdf.edit(**kw)
file = makeFileUpload(self.filename_pdf)
document_pdf.edit(file=file)
file_ = makeFileUpload(self.filename_pdf)
document_pdf.edit(file=file_)
self.tic()
nb_document = len(document_server)
self.assertEqual(nb_document, 2)
return nb_document
def createDocument(self, id, file_name=None, portal_type='Text',
def createDocument(self, id, file_name=None, portal_type='Text', # pylint: disable=redefined-builtin
reference='P-SYNCML.Text', version='001', language='en'):
"""
Create a text document
......@@ -304,8 +305,8 @@ class TestERP5DocumentSyncMLMixin(TestERP5SyncMLMixin):
kw = {'reference': reference, 'version': version, 'language': language}
doc_text.edit(**kw)
if file_name is not None:
file = makeFileUpload(file_name)
doc_text.edit(file=file)
file_ = makeFileUpload(file_name)
doc_text.edit(file=file_)
return doc_text
def checkSynchronizationStateIsSynchronized(self):
......@@ -330,39 +331,39 @@ class TestERP5DocumentSyncMLMixin(TestERP5SyncMLMixin):
for m in sub.contentValues():
self.assertEqual(m.getPartialData(), None)
def checkFirstSynchronization(self, nb_document=0):
portal_sync = self.getSynchronizationTool()
subscription1 = portal_sync[self.sub_id1]
self.assertEqual(len(subscription1), nb_document)
document_server = self.getDocumentServer() # We also check we don't
# modify initial ob
doc1_s = document_server._getOb(self.id1)
self.assertEqual(doc1_s.getId(), self.id1)
self.assertEqual(doc1_s.getReference(), self.reference1)
self.assertEqual(doc1_s.getVersion(), self.version1)
self.assertEqual(doc1_s.getLanguage(), self.language1)
self.assertEqual(doc1_s.getFilename(), self.filename_text)
self.assertEqual(self.size_filename_text, doc1_s.get_size())
doc2_s = document_server._getOb(self.id2)
self.assertEqual(doc2_s.getReference(), self.reference2)
self.assertEqual(doc2_s.getVersion(), self.version2)
self.assertEqual(doc2_s.getLanguage(), self.language2)
self.assertEqual(doc2_s.getFilename(), self.filename_pdf)
self.assertEqual(self.size_filename_pdf, doc2_s.get_size())
document_client1 = self.getDocumentClient1()
document_c = document_client1._getOb(self.id1)
self.assertEqual(document_c.getId(), self.id1)
self.assertEqual(document_c.getReference(), self.reference1)
self.assertEqual(document_c.getVersion(), self.version1)
self.assertEqual(document_c.getLanguage(), self.language1)
self.assertEqual(document_c.getFilename(), self.filename_text)
self.assertEqual(self.size_filename_text, document_c.get_size())
self.assertXMLViewIsEqual(self.sub_id1, doc1_s, document_c)
self.assertXMLViewIsEqual(self.sub_id1, doc2_s,
document_client1._getOb(self.id2))
def checkDocument(self, id, document, filename=None,
def checkFirstSynchronization(self, nb_document=0): # pylint: disable=arguments-differ
portal_sync = self.getSynchronizationTool()
subscription1 = portal_sync[self.sub_id1]
self.assertEqual(len(subscription1), nb_document)
document_server = self.getDocumentServer() # We also check we don't
# modify initial ob
doc1_s = document_server._getOb(self.id1)
self.assertEqual(doc1_s.getId(), self.id1)
self.assertEqual(doc1_s.getReference(), self.reference1)
self.assertEqual(doc1_s.getVersion(), self.version1)
self.assertEqual(doc1_s.getLanguage(), self.language1)
self.assertEqual(doc1_s.getFilename(), self.filename_text)
self.assertEqual(self.size_filename_text, doc1_s.get_size())
doc2_s = document_server._getOb(self.id2)
self.assertEqual(doc2_s.getReference(), self.reference2)
self.assertEqual(doc2_s.getVersion(), self.version2)
self.assertEqual(doc2_s.getLanguage(), self.language2)
self.assertEqual(doc2_s.getFilename(), self.filename_pdf)
self.assertEqual(self.size_filename_pdf, doc2_s.get_size())
document_client1 = self.getDocumentClient1()
document_c = document_client1._getOb(self.id1)
self.assertEqual(document_c.getId(), self.id1)
self.assertEqual(document_c.getReference(), self.reference1)
self.assertEqual(document_c.getVersion(), self.version1)
self.assertEqual(document_c.getLanguage(), self.language1)
self.assertEqual(document_c.getFilename(), self.filename_text)
self.assertEqual(self.size_filename_text, document_c.get_size())
self.assertXMLViewIsEqual(self.sub_id1, doc1_s, document_c)
self.assertXMLViewIsEqual(self.sub_id1, doc2_s,
document_client1._getOb(self.id2))
def checkDocument(self, id, document, filename=None, # pylint: disable=redefined-builtin
size_filename=None, reference='P-SYNCML.Text',
portal_type='Text', version='001', language='en',
description=''):
......@@ -384,9 +385,9 @@ class TestERP5DocumentSyncMLMixin(TestERP5SyncMLMixin):
def checkXMLsSynchronized(self):
document_server = self.getDocumentServer()
document_client1 = self.getDocumentClient1()
for id in self.ids:
doc_s = document_server._getOb(str(id))
doc_c = document_client1._getOb(str(id))
for id_ in self.ids:
doc_s = document_server._getOb(str(id_))
doc_c = document_client1._getOb(str(id_))
self.assertXMLViewIsEqual(self.sub_id1, doc_s, doc_c)
......@@ -395,17 +396,17 @@ class TestERP5DocumentSyncMLMixin(TestERP5SyncMLMixin):
subscription1 = portal_sync[self.sub_id1]
self.assertEqual(len(subscription1.getDocumentList()), nb_document)
document_server = self.getDocumentServer()
id = str(self.ids[0])
doc_text_s = document_server._getOb(id)
reference = 'Test-Text-%s' % id
self.checkDocument(id=id, document=doc_text_s,
id_ = str(self.ids[0])
doc_text_s = document_server._getOb(id_)
reference = 'Test-Text-%s' % id_
self.checkDocument(id=id_, document=doc_text_s,
reference=reference,
filename=self.filename_text,
size_filename=self.size_filename_text)
id = str(self.ids[self.id_max_text])
doc_odt_s = document_server._getOb(id)
reference = 'Test-Odt-%s' % id
self.checkDocument(id=id, document=doc_odt_s,
id_ = str(self.ids[self.id_max_text])
doc_odt_s = document_server._getOb(id_)
reference = 'Test-Odt-%s' % id_
self.checkDocument(id=id_, document=doc_odt_s,
reference=reference,
filename=self.filename_odt,
size_filename=self.size_filename_odt)
......@@ -479,8 +480,8 @@ class TestERP5DocumentSyncML(TestERP5DocumentSyncMLMixin):
# Then we do only modification on a client (the gid) of client => add a object
kw = {'reference':self.reference1,'version':self.version3}
document_c.edit(**kw)
file = makeFileUpload(self.filename_odt)
document_c.edit(file=file)
file_ = makeFileUpload(self.filename_odt)
document_c.edit(file=file_)
self.tic()
self.synchronize(self.sub_id1)
self.checkSynchronizationStateIsSynchronized()
......@@ -590,15 +591,15 @@ class TestERP5DocumentSyncML(TestERP5DocumentSyncMLMixin):
doc_s = document_server._getOb(id_text)
kw = {'description':self.description1}
doc_s.edit(**kw)
file = makeFileUpload(self.filename_odt)
doc_s.edit(file=file)
file_ = makeFileUpload(self.filename_odt)
doc_s.edit(file=file_)
# Side client modification gid of a odt document
id_odt = str(self.ids[self.id_max_text+1])
doc_c = document_client1._getOb(id_odt)
kw = {'description':self.description3}
doc_c.edit(**kw)
file = makeFileUpload(self.filename_text)
doc_c.edit(file=file)
file_ = makeFileUpload(self.filename_text)
doc_c.edit(file=file_)
self.tic()
self.synchronize(self.sub_id1)
self.checkSynchronizationStateIsSynchronized()
......@@ -691,8 +692,8 @@ class TestERP5DocumentSyncML(TestERP5DocumentSyncMLMixin):
document_s = document_server._getOb(self.id1)
kw = {'description': self.description2, 'short_title': self.short_title2 }
document_s.edit(**kw)
file = makeFileUpload(self.filename_ppt)
document_s.edit(file=file)
file_ = makeFileUpload(self.filename_ppt)
document_s.edit(file=file_)
self.tic()
# Modify on client side
......@@ -700,8 +701,8 @@ class TestERP5DocumentSyncML(TestERP5DocumentSyncMLMixin):
document_c1 = document_client1._getOb(self.id1)
kw = {'description': self.description3, 'short_title': self.short_title3 }
document_c1.edit(**kw)
file = makeFileUpload(self.filename_odt)
document_c1.edit(file=file)
file_ = makeFileUpload(self.filename_odt)
document_c1.edit(file=file_)
self.tic()
self.synchronize(self.sub_id1)
......@@ -821,8 +822,8 @@ class TestERP5DocumentSyncML(TestERP5DocumentSyncMLMixin):
self.assertXMLViewIsEqual(self.sub_id_from_server, document_s, document_c, force=1)
# Then we change things on both sides and we look if there
# is synchronization from only one way
file = makeFileUpload(self.filename_odt)
document_c.edit(file=file)
file_ = makeFileUpload(self.filename_odt)
document_c.edit(file=file_)
kw = {'short_title' : self.short_title2}
document_s.edit(**kw)
......@@ -854,6 +855,6 @@ class TestERP5DocumentSyncML(TestERP5DocumentSyncMLMixin):
ignore_processing_status_workflow=True)
def test_suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestERP5DocumentSyncML))
return suite
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestERP5DocumentSyncML))
return suite
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Test Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>testERP5DocumentSyncML</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5SyncML.tests.testERP5DocumentSyncML</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>test.erp5.testERP5DocumentSyncML</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Test Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -35,14 +35,13 @@ from unittest import expectedFailure
from AccessControl.SecurityManagement import newSecurityManager
from ERP5Diff import ERP5Diff
from Products.ERP5Type.tests.runUnitTest import tests_home
from Products.ERP5SyncML.Conduit.ERP5Conduit import ERP5Conduit
from Products.ERP5SyncML.XMLSyncUtils import encode, decode,\
from erp5.component.module.ERP5Conduit import ERP5Conduit
from erp5.component.module.XMLSyncUtils import encode, decode,\
isDecodeEncodeTheSame
from Products.ERP5SyncML.XMLSyncUtils import getConduitByName
from Products.ERP5SyncML.SyncMLConstant import MAX_LEN
from Products.ERP5SyncML.Document import SyncMLSubscription
from Products.ERP5SyncML.tests.testERP5SyncMLMixin import TestERP5SyncMLMixin \
from erp5.component.module.XMLSyncUtils import getConduitByName
from erp5.component.module.SyncMLConstant import MAX_LEN
from erp5.component.document import SyncMLSubscription
from erp5.component.module.testERP5SyncMLMixin import TestERP5SyncMLMixin \
as TestMixin
class TestERP5SyncMLMixin(TestMixin):
......@@ -83,12 +82,6 @@ class TestERP5SyncMLMixin(TestMixin):
nb_synchronization = 3
nb_message_first_synchronization = 6
nb_message_first_sync_max_lines = 16
_subscription_url1 = tests_home + '/sync_client1'
_subscription_url2 = tests_home + '/sync_client2'
_publication_url = tests_home + '/sync_server'
subscription_url1 = 'file:/' + _subscription_url1
subscription_url2 = 'file:/' + _subscription_url2
publication_url = 'file:/' + _publication_url
activity_enabled = False
......@@ -104,6 +97,14 @@ class TestERP5SyncMLMixin(TestMixin):
# allow anything inside Person (we'll cleanup on teardown)
self.getTypesTool().getTypeInfo('Person').filter_content_types = 0
from Products.ERP5Type.tests.runUnitTest import tests_home
self._subscription_url1 = tests_home + '/sync_client1'
self._subscription_url2 = tests_home + '/sync_client2'
self._publication_url = tests_home + '/sync_server'
self.subscription_url1 = 'file:/' + self._subscription_url1
self.subscription_url2 = 'file:/' + self._subscription_url2
self.publication_url = 'file:/' + self._publication_url
def beforeTearDown(self):
"""Clean up."""
self.getTypesTool().getTypeInfo('Person').filter_content_types = 1
......@@ -132,7 +133,7 @@ class TestERP5SyncMLMixin(TestMixin):
def getPersonClient2(self):
return getattr(self.getPortalObject(), 'person_client2', None)
def login(self):
def login(self, *args, **kw):
uf = self.getPortal().acl_users
uf._doAddUser('fab', 'myPassword', ['Manager'], [])
uf._doAddUser('ERP5TypeTestCase', '', ['Manager'], [])
......@@ -180,9 +181,9 @@ class TestERP5SyncMLMixin(TestMixin):
self.initPersonModule()
person_client = self.getPersonClient1()
number_of_object = 60
for id in range(1, number_of_object+1):
for id_ in range(1, number_of_object+1):
person_client.newContent(portal_type='Person',
id=id,
id=id_,
first_name=self.first_name1,
last_name=self.last_name1,
description=self.description1)
......@@ -193,17 +194,17 @@ class TestERP5SyncMLMixin(TestMixin):
def clearFiles(self):
# reset files, because we do sync by files
file = open(self._subscription_url1, 'w')
file.write('')
file.close()
file = open(self._subscription_url2, 'w')
file.write('')
file.close()
file = open(self._publication_url, 'w')
file.write('')
file.close()
def synchronize(self, id):
file_ = open(self._subscription_url1, 'w')
file_.write('')
file_.close()
file_ = open(self._subscription_url2, 'w')
file_.write('')
file_.close()
file_ = open(self._publication_url, 'w')
file_.write('')
file_.close()
def synchronize(self, id): # pylint: disable=redefined-builtin
"""
This just define how we synchronize, we have
to define it here because it is specific to the unit testing
......@@ -233,7 +234,7 @@ class TestERP5SyncMLMixin(TestMixin):
self.tic()
return nb_message
def synchronizeWithBrokenMessage(self, id):
def synchronizeWithBrokenMessage(self, id): # pylint: disable=redefined-builtin
"""
This just define how we synchronize, we have
to define it here because it is specific to the unit testing
......@@ -254,7 +255,7 @@ class TestERP5SyncMLMixin(TestMixin):
# only first call will return an answer
result = portal_sync.processServerSynchronization(publication.getPath())
self.tic()
for x in xrange(2):
for _ in xrange(2):
portal_sync.processServerSynchronization(publication.getPath())
self.tic()
nb_message += 1
......@@ -262,7 +263,7 @@ class TestERP5SyncMLMixin(TestMixin):
break
result = portal_sync.processClientSynchronization(subscription.getPath())
self.tic()
for x in xrange(2):
for _ in xrange(2):
portal_sync.processClientSynchronization(subscription.getPath())
self.tic()
nb_message += 1
......@@ -365,7 +366,7 @@ class TestERP5SyncMLMixin(TestMixin):
self.assertEqual(person_client.getFirstName(), first_name)
self.assertEqual(person_client.getLastName(), last_name)
def checkFirstSynchronization(self, id=None, nb_person=0):
def checkFirstSynchronization(self, id=None, nb_person=0): # pylint: disable=redefined-builtin
portal_sync = self.getSynchronizationTool()
subscription1 = portal_sync[self.sub_id1]
......@@ -451,7 +452,7 @@ class TestERP5SyncMLMixin(TestMixin):
def deletePublicationAndSubscriptionList(self):
portal_sync = self.getSynchronizationTool()
id_list = [id for id in portal_sync.objectIds()]
id_list = [id_ for id_ in portal_sync.objectIds()]
portal_sync.manage_delObjects(id_list)
class TestERP5SyncML(TestERP5SyncMLMixin):
......@@ -1153,13 +1154,13 @@ return [context[%r]]
for conflict in conflict_list :
subscriber = conflict.getSubscriber()
property = conflict.getPropertyId()
property_id = conflict.getPropertyId()
resolve = 0
if property == 'language':
if property_id == 'language':
if subscriber.getUrlString() == self.subscription_url1:
resolve = 1
conflict.applySubscriberValue()
if property == 'format':
if property_id == 'format':
if subscriber.getUrlString() == self.subscription_url2:
resolve = 1
conflict.applySubscriberValue()
......@@ -1261,7 +1262,7 @@ return [context[%r]]
If we want to make this test more intersting, it is
better to split messages
"""
from Products.ERP5SyncML import SyncMLConstant
from erp5.component.module import SyncMLConstant
previous_max_lines = SyncMLConstant.MAX_LEN
try:
SyncMLConstant.MAX_LEN = 1 << 8
......@@ -1875,15 +1876,15 @@ wuIFtde33Dp3NkZl9fc2Rmw6fDp8OnX2RmX19fJibDqV1dXcKwwrDCsMKwwrDCsA=="
self.assertEqual(nb_person, len(person_client1.objectValues()))
self.assertEqual(nb_person, len(person_client2.objectValues()))
for id in range(1, 60):
person_s = person_server._getOb(str(id))
person_c1 = person_client1._getOb(str(id))
person_c2 = person_client2._getOb(str(id))
for id_ in range(1, 60):
person_s = person_server._getOb(str(id_))
person_c1 = person_client1._getOb(str(id_))
person_c2 = person_client2._getOb(str(id_))
self.assertXMLViewIsEqual(self.sub_id1, person_s, person_c1)
self.assertXMLViewIsEqual(self.sub_id1, person_s, person_c2)
def test_suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestERP5SyncML))
return suite
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestERP5SyncML))
return suite
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Test Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>testERP5SyncML</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5SyncML.tests.testERP5SyncML</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>test.erp5.testERP5SyncML</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Test Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -28,7 +28,7 @@
#
##############################################################################
from testERP5SyncML import TestERP5SyncMLMixin
from erp5.component.test.testERP5SyncML import TestERP5SyncMLMixin
class TestERP5SyncMLVCard(TestERP5SyncMLMixin):
......@@ -43,10 +43,6 @@ class TestERP5SyncMLVCard(TestERP5SyncMLMixin):
"""
return ('erp5_base', 'erp5_syncml',)
def afterSetUp(self):
self.portal.z_drop_syncml()
self.portal.z_create_syncml()
def getTitle(self):
return 'testERP5SyncMLVCard'
......@@ -106,7 +102,6 @@ class TestERP5SyncMLVCard(TestERP5SyncMLMixin):
def test_04_FirstVCardSynchronization(self):
# We will try to populate the folder person_client1
# with the data form person_server
self.login()
self.deletePublicationAndSubscriptionList()
if 'person_server' in self.portal.objectIds():
self.portal._delObject('person_server')
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Test Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>testERP5SyncMLVCard</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5SyncML.tests.testERP5SyncMLVCard</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>test.erp5.testERP5SyncMLVCard</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Test Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -33,11 +33,11 @@ from AccessControl import ClassSecurityInfo
from Products.ERP5Type.Tool.BaseTool import BaseTool
from Products.ERP5Type import Permissions
from Products.ERP5Type.Globals import InitializeClass
from Products.ERP5SyncML.SyncMLConstant import ACTIVITY_PRIORITY, \
from erp5.component.module.SyncMLConstant import ACTIVITY_PRIORITY, \
SynchronizationError
from Products.ERP5SyncML.SyncMLMessage import SyncMLRequest
from Products.ERP5SyncML.Engine.SynchronousEngine import SyncMLSynchronousEngine
from Products.ERP5SyncML.Engine.AsynchronousEngine import SyncMLAsynchronousEngine
from erp5.component.module.SyncMLMessage import SyncMLRequest
from erp5.component.module.SyncMLEngineSynchronous import SyncMLSynchronousEngine
from erp5.component.module.SyncMLEngineAsynchronous import SyncMLAsynchronousEngine
from Products.ERP5.ERP5Site import getSite
synchronous_engine = SyncMLSynchronousEngine()
......@@ -211,7 +211,7 @@ class SynchronizationTool(BaseTool):
We will look at the url and we will see if we need to send mail, http
response, or just copy to a file.
"""
syncml_logger.info('readResponse sync_id %s, text %s' % (sync_id, text))
syncml_logger.info('readResponse sync_id %s, text %s', sync_id, text)
if text:
# we are still anonymous at this time, use unrestrictedSearchResults
# to fetch the Subcribers
......@@ -270,7 +270,7 @@ class SynchronizationTool(BaseTool):
else:
xml = stream.read()
stream.close()
syncml_logger.debug('readResponse xml from file is %s' % (xml,))
syncml_logger.debug('readResponse xml from file is %s', xml)
if xml:
return xml
#
......@@ -313,8 +313,8 @@ class SynchronizationTool(BaseTool):
if subscriber and subscriber.getSynchronizationState() not in \
("not_running", "initializing", "finished"):
syncml_logger.error(
'Trying to start a synchronization on server side : %s although synchronisation is already running'
% (subscriber.getPath(),))
'Trying to start a synchronization on server side : %s although synchronisation is already running',
subscriber.getPath())
# Prevent initilisation if sync already running
return
syncml_response = engine.processServerInitialization(
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Tool Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>SynchronizationTool</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5SyncML.Tool.SynchronizationTool</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>tool.erp5.SynchronizationTool</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Tool Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
document.erp5.SyncMLConflict
document.erp5.SyncMLPublication
document.erp5.SyncMLSignature
document.erp5.SyncMLSubscription
\ No newline at end of file
interface.erp5.IConduit
\ No newline at end of file
mixin.erp5.SyncMLEngineMixin
\ No newline at end of file
module.erp5.SyncMLEngineAsynchronous
module.erp5.BaseConduit
module.erp5.ERP5Conduit
module.erp5.ERP5ConduitTitleGid
module.erp5.ERP5DocumentConduit
module.erp5.ERP5ShopOrderConduit
module.erp5.SyncMLTransportERP5
module.erp5.SyncMLTransportFile
module.erp5.SyncMLTransportHTTP
module.erp5.SyncMLTransportMail
module.erp5.SharedVCardConduit
module.erp5.SyncMLConstant
module.erp5.SyncMLMessage
module.erp5.SyncMLUtils
module.erp5.SyncMLEngineSynchronous
module.erp5.VCardConduit
module.erp5.XMLSyncUtils
module.erp5.XupdateUtils
module.erp5.testERP5SyncMLMixin
\ No newline at end of file
test.erp5.testERP5DocumentSyncML
test.erp5.testERP5SyncML
test.erp5.testERP5SyncMLVCard
\ No newline at end of file
tool.erp5.SynchronizationTool
\ No newline at end of file
erp5_full_text_mroonga_catalog
erp5_core_proxy_field_legacy
erp5_base
erp5_ingestion
erp5_ingestion_mysql_innodb_catalog
erp5_web
erp5_dms
\ No newline at end of file
......@@ -26,7 +26,7 @@
##############################################################################
from Products.ERP5SyncML.tests.testERP5SyncMLMixin import TestERP5SyncMLMixin
from erp5.component.module.testERP5SyncMLMixin import TestERP5SyncMLMixin
class testSyncMLAsynchronousEngine(TestERP5SyncMLMixin):
......
......@@ -28,11 +28,11 @@
#
##############################################################################
from Products.ERP5SyncML.SyncMLConstant import XUPDATE_INSERT_OR_ADD_LIST, \
from erp5.component.module.SyncMLConstant import XUPDATE_INSERT_OR_ADD_LIST, \
XUPDATE_DEL, XUPDATE_UPDATE
from Products.ERP5Type.XMLExportImport import MARSHALLER_NAMESPACE_URI
from zLOG import LOG, INFO
from Products.ERP5SyncML.Conduit.ERP5Conduit import ERP5Conduit
from erp5.component.module.ERP5Conduit import ERP5Conduit
from lxml import etree
from copy import deepcopy
parser = etree.XMLParser(remove_blank_text=True)
......
......@@ -26,7 +26,7 @@
#
##############################################################################
from Products.ERP5TioSafe.Conduit.TioSafeBaseConduit import TioSafeBaseConduit
from erp5.component.module.TioSafeBaseConduit import TioSafeBaseConduit
class TioSafeDoNothingConduit(TioSafeBaseConduit):
"""
......
......@@ -27,8 +27,8 @@
#
##############################################################################
from Products.ERP5TioSafe.Conduit.TioSafeBaseConduit import TioSafeBaseConduit
from Products.ERP5SyncML.Document.SyncMLConflict import SyncMLConflict as Conflict
from erp5.component.module.TioSafeBaseConduit import TioSafeBaseConduit
from erp5.component.document.SyncMLConflict import SyncMLConflict as Conflict
from lxml import etree
class TioSafeNodeConduit(TioSafeBaseConduit):
......
......@@ -28,8 +28,8 @@
##############################################################################
from Products.ERP5Type.Utils import cartesianProduct
from Products.ERP5TioSafe.Conduit.TioSafeBaseConduit import TioSafeBaseConduit
from Products.ERP5SyncML.Document.SyncMLConflict import SyncMLConflict as Conflict
from erp5.component.module.TioSafeBaseConduit import TioSafeBaseConduit
from erp5.component.document.SyncMLConflict import SyncMLConflict as Conflict
from lxml import etree
from zLOG import LOG
class TioSafeResourceConduit(TioSafeBaseConduit):
......
......@@ -26,7 +26,7 @@
##############################################################################
from lxml import etree
from Products.ERP5SyncML.XMLSyncUtils import getConduitByName
from erp5.component.module.XMLSyncUtils import getConduitByName
from difflib import unified_diff
from Products.ERP5Type.DiffUtils import DiffFile
......
......@@ -25,7 +25,7 @@
#
##############################################################################
from Products.ERP5TioSafe.Conduit.TioSafeBaseConduit import TioSafeBaseConduit
from erp5.component.module.TioSafeBaseConduit import TioSafeBaseConduit
class AccountERP5IntegrationConduit(TioSafeBaseConduit):
"""
......@@ -34,7 +34,7 @@ class AccountERP5IntegrationConduit(TioSafeBaseConduit):
def __init__(self):
self.xml_object_tag = 'node'
def getGidFromObject(self, object):
def getGidFromObject(self, object): # pylint: disable=redefined-builtin
"""
Return the Account GID of the object.
"""
......@@ -46,7 +46,7 @@ class AccountERP5IntegrationConduit(TioSafeBaseConduit):
"""
return 'Account'
def _createContent(self, xml=None, object=None, object_id=None, sub_object=None,
def _createContent(self, xml=None, object=None, object_id=None, sub_object=None, # pylint: disable=redefined-builtin
reset_local_roles=0, reset_workflow=0, simulate=0, **kw):
"""
This is the method calling to create an object
......@@ -73,7 +73,7 @@ class AccountERP5IntegrationConduit(TioSafeBaseConduit):
# Browse the list of arrows and movements
for node in xml.getchildren():
# Only works on right tags, and no on the comments, ...
if type(node.tag) is not str:
if not isinstance(node.tag, str):
continue
# Build the split list of a tag to test the namespace
split_tag = node.tag.split('}')
......@@ -101,15 +101,15 @@ class AccountERP5IntegrationConduit(TioSafeBaseConduit):
)
return sub_object
def updateNode(self, xml=None, object=None, previous_xml=None, force=0,
def updateNode(self, xml=None, object=None, previous_xml=None, force=0, # pylint: disable=redefined-builtin
simulate=0, **kw):
raise Exception("updateNode: Impossible to update Account")
def deleteNode(self, xml=None, object=None, previous_xml=None, force=0,
def deleteNode(self, xml=None, object=None, previous_xml=None, force=0, # pylint: disable=redefined-builtin
simulate=0, **kw):
raise Exception("deleteNode: Impossible to delete Account")
def editDocument(self, object=None, **kw):
def editDocument(self, object=None, **kw): # pylint: disable=redefined-builtin
"""
This is the editDocument method inherit of ERP5Conduit. This method
is used to save the information of a Account.
......@@ -119,9 +119,8 @@ class AccountERP5IntegrationConduit(TioSafeBaseConduit):
mapping = {'title': 'title',
'description': 'description'}
# Translate kw with the PropertySheet
property = {}
property_ = {}
for k, v in kw.items():
k = mapping.get(k, k)
property[k] = v
object._edit(**property)
property_[k] = v
object._edit(**property_)
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Module Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>AccountERP5IntegrationConduit</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5TioSafe.Conduit.AccountERP5IntegrationConduit</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>module.erp5.AccountERP5IntegrationConduit</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Module Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -27,7 +27,7 @@
from base64 import b16encode
from Products.ERP5TioSafe.Conduit.TioSafeBaseConduit import TioSafeBaseConduit
from erp5.component.module.TioSafeBaseConduit import TioSafeBaseConduit
class AccountingERP5IntegrationConduit(TioSafeBaseConduit):
"""
......@@ -36,7 +36,7 @@ class AccountingERP5IntegrationConduit(TioSafeBaseConduit):
def __init__(self):
self.xml_object_tag = 'transaction'
def getGidFromObject(self, object):
def getGidFromObject(self, object): # pylint: disable=redefined-builtin
"""
Return the Accounting GID of the object.
"""
......@@ -66,7 +66,7 @@ class AccountingERP5IntegrationConduit(TioSafeBaseConduit):
# Browse the list of categories
for node in categories:
if 'Journal' in node.text:
journal = node.text.split('/')[1]
journal = node.text.split('/')[1]
# Check by the name which portal type must be returns
if journal in ('JC', 'JD'):
return 'Accounting Transaction'
......@@ -79,9 +79,8 @@ class AccountingERP5IntegrationConduit(TioSafeBaseConduit):
return 'Payment Transaction'
else:
raise "getObjectType: ERROR journal code unknow"
return
def constructContent(self, object, object_id, portal_type):
def constructContent(self, object, object_id, portal_type): # pylint: disable=redefined-builtin
"""
This allows to specify how to construct a new content.
This is really usefull if you want to write your own Conduit.
......@@ -95,7 +94,7 @@ class AccountingERP5IntegrationConduit(TioSafeBaseConduit):
subobject = object._getOb(object_id)
return subobject, 1, 1
def _createContent(self, xml=None, object=None, object_id=None,
def _createContent(self, xml=None, object=None, object_id=None, # pylint: disable=redefined-builtin
sub_object=None, reset_local_roles=0, reset_workflow=0, simulate=0,
**kw):
"""
......@@ -126,7 +125,7 @@ class AccountingERP5IntegrationConduit(TioSafeBaseConduit):
# Browse the list to work on categories
for node in xml.getchildren():
# Only works on right tags, and no on the comments, ...
if type(node.tag) is not str:
if not isinstance(node.tag, str):
continue
# Build the split list of the tag
split_tag = node.tag.split('}')
......@@ -221,7 +220,7 @@ class AccountingERP5IntegrationConduit(TioSafeBaseConduit):
# Browse the XML subnode
for subnode in xml.getchildren():
# Only works on right tags, and no on the comments, ...
if type(subnode.tag) is not str:
if not isinstance(subnode.tag, str):
continue
tag = subnode.tag.split('}')[index]
# Check the usefull of the different elements
......@@ -236,7 +235,6 @@ class AccountingERP5IntegrationConduit(TioSafeBaseConduit):
else:
if subnode.text:
# Retrieve the object to bind
instance = document.getPortalObject()
subscriber = arrow_dict[tag]['sync']
# Encode to the output type
link_gid = subnode.text
......@@ -280,7 +278,7 @@ class AccountingERP5IntegrationConduit(TioSafeBaseConduit):
# Browse the XML subnode
for subnode in xml.getchildren():
# Only works on right tags, and no on the comments, ...
if type(subnode.tag) is not str:
if not isinstance(subnode.tag, str):
continue
tag = subnode.tag.split('}')[index]
# Check the usefull of the different elements
......@@ -298,15 +296,15 @@ class AccountingERP5IntegrationConduit(TioSafeBaseConduit):
elif tag == "quantity":
accounting_line.setQuantity(subnode.text)
def updateNode(self, xml=None, object=None, previous_xml=None, force=0,
def updateNode(self, xml=None, object=None, previous_xml=None, force=0, # pylint: disable=redefined-builtin
simulate=0, **kw):
raise Exception("updateNode: Impossible to delete Accounting")
def deleteNode(self, xml=None, object=None, previous_xml=None, force=0,
def deleteNode(self, xml=None, object=None, previous_xml=None, force=0, # pylint: disable=redefined-builtin
simulate=0, **kw):
raise Exception("deleteNode: Impossible to delete Accounting")
def editDocument(self, object=None, **kw):
def editDocument(self, object=None, **kw): # pylint: disable=redefined-builtin
"""
This is the editDocument method inherit of ERP5Conduit. This method
is used to save the information of a Accounting.
......@@ -322,9 +320,8 @@ class AccountingERP5IntegrationConduit(TioSafeBaseConduit):
'reference': 'reference',
}
# Translate kw with the PropertySheet
property = {}
property_ = {}
for k, v in kw.items():
k = mapping.get(k, k)
property[k] = v
object._edit(**property)
property_[k] = v
object._edit(**property_)
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Module Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>AccountingERP5IntegrationConduit</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5TioSafe.Conduit.AccountingERP5IntegrationConduit</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>module.erp5.AccountingERP5IntegrationConduit</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Module Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -27,7 +27,7 @@
#
##############################################################################
from Products.ERP5TioSafe.Conduit.TioSafeBaseConduit import TioSafeBaseConduit, \
from erp5.component.module.TioSafeBaseConduit import TioSafeBaseConduit, \
ADDRESS_TAG_LIST
from DateTime import DateTime
from lxml import etree
......@@ -45,10 +45,10 @@ class ERP5NodeConduit(TioSafeBaseConduit):
def __init__(self):
self.xml_object_tag = 'node'
def getObjectAsXML(self, object, domain):
def getObjectAsXML(self, object, domain): # pylint: disable=redefined-builtin
return object.Node_asTioSafeXML(context_document=domain)
def _createSaleTradeCondition(self, object, **kw):
def _createSaleTradeCondition(self, object, **kw): # pylint: disable=redefined-builtin
""" Link person to a sale trade condition so that
we can filter person based on the plugin they came from
"""
......@@ -64,7 +64,7 @@ class ERP5NodeConduit(TioSafeBaseConduit):
version=001)
stc.validate()
def _updateSaleTradeCondition(self, object, **kw):
def _updateSaleTradeCondition(self, object, **kw): # pylint: disable=redefined-builtin
""" Link person to a sale trade condition so that
we can filter person based on the plugin they came from
"""
......@@ -86,7 +86,7 @@ class ERP5NodeConduit(TioSafeBaseConduit):
destination_decision=object.getRelativeUrl(),
destination_administration=object.getRelativeUrl(),)
def _deleteSaleTradeCondition(self, object, **kw):
def _deleteSaleTradeCondition(self, object, **kw): # pylint: disable=redefined-builtin
""" Unvalidate sale trade condition so that
we can filter person based on the plugin they came from
"""
......@@ -96,7 +96,7 @@ class ERP5NodeConduit(TioSafeBaseConduit):
stc = stc_list[0].getObject()
stc.invalidate()
def afterCreateMethod(self, object, **kw):
def afterCreateMethod(self, object, **kw): # pylint: disable=redefined-builtin
""" This method is for actions that has to be done just after object
creation and which required to have synchronization parameters
......@@ -105,7 +105,7 @@ class ERP5NodeConduit(TioSafeBaseConduit):
"""
self._createSaleTradeCondition(object, **kw)
def afterUpdateMethod(self, object, **kw):
def afterUpdateMethod(self, object, **kw): # pylint: disable=redefined-builtin
""" This method is for actions that has to be done just after object
update and which required to have synchronization parameters
......@@ -114,7 +114,7 @@ class ERP5NodeConduit(TioSafeBaseConduit):
"""
self._updateSaleTradeCondition(object, **kw)
def afterDeleteMethod(self, object, **kw):
def afterDeleteMethod(self, object, **kw): # pylint: disable=redefined-builtin
""" This method is for actions that has to be done just after object
has been deleted and which required to have synchronization parameters
......@@ -123,7 +123,7 @@ class ERP5NodeConduit(TioSafeBaseConduit):
"""
self._deleteSaleTradeCondition(object, **kw)
def afterNewObject(self, object):
def afterNewObject(self, object): # pylint: disable=redefined-builtin
""" Realise actions after new object creation. """
object.validate()
object.updateLocalRolesOnSecurityGroups()
......@@ -159,7 +159,7 @@ class ERP5NodeConduit(TioSafeBaseConduit):
document.reindexObject()
return []
def _createContent(self, xml=None, object=None, object_id=None, sub_object=None,
def _createContent(self, xml=None, object=None, object_id=None, sub_object=None, # pylint: disable=redefined-builtin
reset_local_roles=0, reset_workflow=0, simulate=0, **kw):
""" This is the method calling to create an object. """
# if DEBUG:
......@@ -187,14 +187,13 @@ class ERP5NodeConduit(TioSafeBaseConduit):
relation = None
category_list = []
role_list =[]
relation_data_dict = {}
address_tag_mapping = {"street" : "street_address",
"zip" : "zip_code",
"country" : "region",}
address_int_index = 0
for node in xml.getchildren():
# works on tags, no on comments
if type(node.tag) is not str:
if not isinstance(node.tag, str):
continue
tag = node.tag.split('}')[index]
......@@ -216,7 +215,7 @@ class ERP5NodeConduit(TioSafeBaseConduit):
# Build dict of address properties
address_data_dict = {}
for element in node.getchildren():
if type(element.tag) is not str:
if not isinstance(element.tag, str):
continue
element_tag = element.tag.split('}')[index]
address_data_dict[address_tag_mapping.get(element_tag, element_tag)] = element.text
......@@ -291,11 +290,11 @@ class ERP5NodeConduit(TioSafeBaseConduit):
return sub_object
def _deleteContent(self, object=None, object_id=None, **kw):
def _deleteContent(self, object=None, object_id=None, **kw): # pylint: disable=redefined-builtin
""" We do not delete nodes """
self.afterDeleteMethod(object[object_id])
def editDocument(self, object=None, **kw):
def editDocument(self, object=None, **kw): # pylint: disable=redefined-builtin
""" This editDocument method allows to set attributes of the object. """
# if DEBUG:
# LOG("ERP5NodeConduit.editDocument", INFO, "object = %s with %s" %(object.getPath(), kw))
......@@ -320,11 +319,11 @@ class ERP5NodeConduit(TioSafeBaseConduit):
'country': 'region',
}
# translate kw with the good PropertySheet
property = {}
property_ = {}
for k, v in kw.items():
k = mapping.get(k, k)
property[k] = v
object._edit(**property)
property_[k] = v
object._edit(**property_)
def checkAddressConflict(self, document, tag, xml, previous_value, new_value, signature):
"""
......@@ -390,7 +389,6 @@ class ERP5NodeConduit(TioSafeBaseConduit):
xpath_expression = xml.get('select')
tag = xpath_expression.split('/')[-1]
new_value = xml.text.encode('utf-8')
keyword = {}
# retrieve the previous xml etree through xpath
selected_previous_xml = previous_xml.xpath(xpath_expression)
......@@ -417,7 +415,6 @@ class ERP5NodeConduit(TioSafeBaseConduit):
tag = xml.get('select').split('/')[-1]
# this variable is used to retrieve the id of address and to not remove the
# orginal tag (address, street, zip, city or country)
keyword = {}
# retrieve the previous xml etree through xpath
xpath_expression = xml.get('select')
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Module Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>ERP5NodeConduit</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5TioSafe.Conduit.ERP5NodeConduit</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>module.erp5.ERP5NodeConduit</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Module Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -29,12 +29,9 @@
#
##############################################################################
from Products.ERP5TioSafe.Conduit.TioSafeBaseConduit import TioSafeBaseConduit
from Products.ERP5TioSafe.Conduit.ERP5TransactionConduit import ERP5TransactionConduit
from Products.ERP5SyncML.SyncMLConstant import XUPDATE_INSERT_OR_ADD_LIST
from base64 import b16encode
from zLOG import LOG, WARNING
from copy import deepcopy
from erp5.component.module.TioSafeBaseConduit import TioSafeBaseConduit
from erp5.component.module.SyncMLConstant import XUPDATE_INSERT_OR_ADD_LIST
from zLOG import LOG
class ERP5PaymentTransactionConduit(TioSafeBaseConduit):
"""
......@@ -44,18 +41,18 @@ class ERP5PaymentTransactionConduit(TioSafeBaseConduit):
# Define the object_tag element to add object
self.xml_object_tag = 'transaction'
def getObjectAsXML(self, object, domain):
def getObjectAsXML(self, object, domain): # pylint: disable=redefined-builtin
return object.PaymentTransaction_asTioSafeXML(context_document=domain)
def updateNode(self, xml=None, object=None, previous_xml=None, force=0,
def updateNode(self, xml=None, object=None, previous_xml=None, force=0, # pylint: disable=redefined-builtin
simulate=0, **kw):
raise Exception('updateNode: Impossible to update transaction')
def deleteNode(self, xml=None, object=None, previous_xml=None, force=0,
def deleteNode(self, xml=None, object=None, previous_xml=None, force=0, # pylint: disable=redefined-builtin
simulate=0, **kw):
raise Exception('deleteNode: Impossible to delete transaction')
def _createSaleTradeCondition(self, object, **kw):
def _createSaleTradeCondition(self, object, **kw): # pylint: disable=redefined-builtin
""" Link payment transaction to a sale trade condition so that
we can filter payment transaction based on the plugin they came from
"""
......@@ -74,7 +71,7 @@ class ERP5PaymentTransactionConduit(TioSafeBaseConduit):
simulation_state="confirmed"):
transaction = payment_transaction.getObject()
transaction.cancel()
transaction.cancel()
#Invalidate the STC
sale_trade_cond.invalidate()
......@@ -86,7 +83,7 @@ class ERP5PaymentTransactionConduit(TioSafeBaseConduit):
return stc
def _deleteSaleTradeCondition(self, object, **kw):
def _deleteSaleTradeCondition(self, object, **kw): # pylint: disable=redefined-builtin
""" Unvalidate sale trade condition so that
we can filter payment transaction based on the plugin they came from
"""
......@@ -95,7 +92,7 @@ class ERP5PaymentTransactionConduit(TioSafeBaseConduit):
for stc in stc_list:
stc.getObject().invalidate()
def _createContent(self, xml=None, object=None, object_id=None, sub_object=None,
def _createContent(self, xml=None, object=None, object_id=None, sub_object=None, # pylint: disable=redefined-builtin
reset_local_roles=0, reset_workflow=0, simulate=0, **kw):
"""
This is the method calling to create an object
......@@ -130,7 +127,7 @@ class ERP5PaymentTransactionConduit(TioSafeBaseConduit):
sub_object.setPriceCurrencyValue(link_object)
bank_account_object = integration_site.getDefaultSourcePaymentValue()
sub_object.setDefaultSourcePaymentValue(bank_account_object)
sub_object.setSourceSectionValue(bank_account_object.getParent())
sub_object.setSourceSectionValue(bank_account_object.getParent())
# Mapping between tag and element
node_dict = {
......@@ -145,10 +142,8 @@ class ERP5PaymentTransactionConduit(TioSafeBaseConduit):
# Browse the list of arrows and movements
for node in xml.getchildren():
# Only works on right tags, and no on the comments, ...
if type(node.tag) is not str:
if not isinstance(node.tag, str):
continue
# Build the slipt list of a tag to test
split_tag = node.tag.split('}')
# Build the tag (without is Namespace)
tag = node.tag.split('}')[index]
# Treat sub-element
......@@ -178,7 +173,7 @@ class ERP5PaymentTransactionConduit(TioSafeBaseConduit):
return sub_object
def afterNewObject(self, object, **kw):
def afterNewObject(self, object, **kw): # pylint: disable=redefined-builtin
""" Confirm the payment transaction and, add the grants on this one. """
if object.getPortalType() in ['Payment Transaction',]:
## first delete default generated accounting transaction line: bank,
......@@ -200,9 +195,6 @@ class ERP5PaymentTransactionConduit(TioSafeBaseConduit):
# dictionary of the value of a movement
movement_dict_value = {'category': []}
# marker for checking property existency
MARKER = object()
# if exist namespace retrieve only the tag
index = 0
if xml.nsmap not in [None, {}]:
......@@ -215,7 +207,7 @@ class ERP5PaymentTransactionConduit(TioSafeBaseConduit):
# browse the xml and save the sale order line values
for subnode in xml.getchildren():
# only works on tags, no on the comments or other kind of tag
if type(subnode.tag) is not str:
if not isinstance(subnode.tag, str):
continue
tag = subnode.tag.split('}')[index]
# set line values in the dict
......@@ -241,11 +233,11 @@ class ERP5PaymentTransactionConduit(TioSafeBaseConduit):
elif key == "price":
price =float(movement_dict_value[key])
if price > 0:
payment_transaction_line.setSourceCredit(price)
payment_transaction_line.setSourceCredit(price)
else:
payment_transaction_line.setSourceDebit(-price)
payment_transaction_line.setSourceDebit(-price)
def editDocument(self, object=None, **kw):
def editDocument(self, object=None, **kw): # pylint: disable=redefined-builtin
"""
This is the default editDocument method. This method
can easily be overwritten.
......@@ -258,10 +250,10 @@ class ERP5PaymentTransactionConduit(TioSafeBaseConduit):
'reference': 'reference',
'causality': 'comment',
}
property = {}
property_ = {}
# Translate kw with the good PropertySheet
for k, v in kw.items():
k = mapping.get(k, k)
property[k] = v
object._edit(**property)
property_[k] = v
object._edit(**property_)
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Module Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>ERP5PaymentTransactionConduit</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5TioSafe.Conduit.ERP5PaymentTransactionConduit</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>module.erp5.ERP5PaymentTransactionConduit</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Module Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -28,10 +28,9 @@
##############################################################################
from Products.CMFCore.WorkflowCore import WorkflowException
from Products.ERP5TioSafe.Conduit.TioSafeBaseConduit import TioSafeBaseConduit
from erp5.component.module.TioSafeBaseConduit import TioSafeBaseConduit
from lxml import etree
parser = etree.XMLParser(remove_blank_text=True)
from zLOG import LOG
class ERP5ResourceConduit(TioSafeBaseConduit):
"""
......@@ -42,10 +41,10 @@ class ERP5ResourceConduit(TioSafeBaseConduit):
self.xml_object_tag = 'resource'
self.system_pref = None
def getObjectAsXML(self, object, domain):
def getObjectAsXML(self, object, domain): # pylint: disable=redefined-builtin
return object.Resource_asTioSafeXML(context_document=domain)
def _createContent(self, xml=None, object=None, object_id=None,
def _createContent(self, xml=None, object=None, object_id=None, # pylint: disable=redefined-builtin
sub_object=None, reset_local_roles=0, reset_workflow=0, simulate=0,
**kw):
"""
......@@ -84,10 +83,8 @@ class ERP5ResourceConduit(TioSafeBaseConduit):
for node in xml.getchildren():
# Only works on right tags, and no on the comments, ...
if type(node.tag) is not str:
if not isinstance(node.tag, str):
continue
# Build the split list of the tag
split_tag = node.tag.split('}')
# Build the tag (without is Namespace)
tag = node.tag.split('}')[index]
# Treat sub-element
......@@ -134,7 +131,6 @@ class ERP5ResourceConduit(TioSafeBaseConduit):
# build mapping list here
mapping_dict = {'category' : [],}
for item in node.getchildren():
split_tag = item.tag.split('}')
# Build the tag (without is Namespace)
tag = item.tag.split('}')[index]
if tag == "category":
......@@ -274,11 +270,11 @@ class ERP5ResourceConduit(TioSafeBaseConduit):
cat_list.append(base_category)
self.system_pref.edit(preferred_product_variation_base_category_list = cat_list)
def afterNewObject(self, object):
def afterNewObject(self, object): # pylint: disable=redefined-builtin
object.validate()
object.updateLocalRolesOnSecurityGroups()
def _deleteContent(self, object=None, object_id=None, **kw):
def _deleteContent(self, object=None, object_id=None, **kw): # pylint: disable=redefined-builtin
""" Move the product into "invalidated" state. """
document = object.product_module._getOb(object_id)
# dict which provides the list of transition to move into invalidated state
......@@ -306,7 +302,7 @@ class ERP5ResourceConduit(TioSafeBaseConduit):
if sale_supply.getTitle() == sync_name:
sale_supply.manage_delObjects(ids=[sale_supply_line.getId(),])
def editDocument(self, object=None, **kw):
def editDocument(self, object=None, **kw): # pylint: disable=redefined-builtin
"""
This is the editDocument method inherit of ERP5Conduit. This method
is used to save the information of a Product.
......@@ -319,11 +315,11 @@ class ERP5ResourceConduit(TioSafeBaseConduit):
'description': 'description',
}
# Translate kw with the PropertySheet
property = {}
property_ = {}
for k, v in kw.items():
k = mapping.get(k, k)
property[k] = v
object._edit(**property)
property_[k] = v
object._edit(**property_)
def _getPropertyMappingCell(self, resource, prop, index):
......@@ -404,7 +400,7 @@ class ERP5ResourceConduit(TioSafeBaseConduit):
shared_variation = True
try:
# Try to access the category
category = document.getPortalObject().portal_categories.restrictedTraverse(new_value)
document.getPortalObject().portal_categories.restrictedTraverse(new_value)
except KeyError:
# This is an individual variation
shared_variation = False
......@@ -595,12 +591,12 @@ class ERP5ResourceConduit(TioSafeBaseConduit):
current_value = getter()
if isinstance(current_value, unicode):
current_value = current_value.encode('utf-8')
if current_value not in [new_value, previous_value]:
if current_value not in [new_value, previous_value]: # pylint: disable=undefined-variable
conflict_list.append(self._generateConflict(document.getPhysicalPath(),
base_tag+'/'+tag,
etree.tostring(xml, encoding='utf-8'),
current_value,
new_value,
new_value, # pylint: disable=undefined-variable
kw['signature']))
else:
setter_id = "set%s" %(tag.capitalize(),)
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Module Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>ERP5ResourceConduit</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5TioSafe.Conduit.ERP5ResourceConduit</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>module.erp5.ERP5ResourceConduit</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Module Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -29,8 +29,8 @@
from base64 import b16encode
from copy import deepcopy
from Products.ERP5TioSafe.Conduit.TioSafeBaseConduit import TioSafeBaseConduit
from Products.ERP5SyncML.SyncMLConstant import XUPDATE_INSERT_OR_ADD_LIST
from erp5.component.module.TioSafeBaseConduit import TioSafeBaseConduit
from erp5.component.module.SyncMLConstant import XUPDATE_INSERT_OR_ADD_LIST
class ERP5TransactionConduit(TioSafeBaseConduit):
"""
......@@ -40,20 +40,20 @@ class ERP5TransactionConduit(TioSafeBaseConduit):
# Define the object_tag element to add object
self.xml_object_tag = 'transaction'
def getObjectAsXML(self, object, domain):
def getObjectAsXML(self, object, domain): # pylint: disable=redefined-builtin
return object.Transaction_asTioSafeXML(context_document=domain)
def updateNode(self, xml=None, object=None, previous_xml=None, force=0,
def updateNode(self, xml=None, object=None, previous_xml=None, force=0, # pylint: disable=redefined-builtin
simulate=0, **kw):
raise Exception('updateNode: Impossible to update transaction')
def deleteNode(self, xml=None, object=None, previous_xml=None, force=0,
def deleteNode(self, xml=None, object=None, previous_xml=None, force=0, # pylint: disable=redefined-builtin
simulate=0, **kw):
raise Exception('deleteNode: Impossible to delete transaction')
def _createContent(self, xml=None, object=None, object_id=None, sub_object=None,
def _createContent(self, xml=None, object=None, object_id=None, sub_object=None, # pylint: disable=redefined-builtin
reset_local_roles=0, reset_workflow=0, simulate=0, **kw):
"""
This is the method calling to create an object
......@@ -96,10 +96,9 @@ class ERP5TransactionConduit(TioSafeBaseConduit):
# Browse the list of arrows and movements
for node in xml.getchildren():
# Only works on right tags, and no on the comments, ...
if type(node.tag) is not str:
if not isinstance(node.tag, str):
continue
# Build the slipt list of a tag to test
split_tag = node.tag.split('}')
# Build the tag (without is Namespace)
tag = node.tag.split('}')[index]
# Treat sub-element
......@@ -131,7 +130,7 @@ class ERP5TransactionConduit(TioSafeBaseConduit):
return sub_object
def afterNewObject(self, object):
def afterNewObject(self, object): # pylint: disable=redefined-builtin
""" Confirm the sale order and, add the grants on this one. """
if object.getPortalType() in ['Sale Order',]:
object.confirm()
......@@ -217,11 +216,10 @@ class ERP5TransactionConduit(TioSafeBaseConduit):
default_source = integration_site.getSourceAdministrationValue()
default_org_gid = integration_site.organisation_module.getSourceSectionValue().getGidFromObject(default_source, encoded=False)
default_node = integration_site.getDestinationValue()
default_node_gid = integration_site.person_module.getSourceSectionValue().getGidFromObject(default_node, encoded=False)
for subnode in xml.getchildren():
# only works on tags, no on the comments or other kind of tag
if type(subnode.tag) is not str:
if not isinstance(subnode.tag, str):
continue
tag = subnode.tag.split('}')[index]
......@@ -255,9 +253,6 @@ class ERP5TransactionConduit(TioSafeBaseConduit):
# dictionary of the value of a movement
movement_dict_value = {'category': []}
# marker for checking property existency
MARKER = object()
# if exist namespace retrieve only the tag
index = 0
if xml.nsmap not in [None, {}]:
......@@ -270,7 +265,7 @@ class ERP5TransactionConduit(TioSafeBaseConduit):
# browse the xml and save the sale order line values
for subnode in xml.getchildren():
# only works on tags, no on the comments or other kind of tag
if type(subnode.tag) is not str:
if not isinstance(subnode.tag, str):
continue
tag = subnode.tag.split('}')[index]
if tag == 'resource':
......@@ -362,7 +357,7 @@ class ERP5TransactionConduit(TioSafeBaseConduit):
mapping_of_setter[key](movement_dict_value[key])
def editDocument(self, object=None, **kw):
def editDocument(self, object=None, **kw): # pylint: disable=redefined-builtin
"""
This is the default editDocument method. This method
can easily be overwritten.
......@@ -375,9 +370,9 @@ class ERP5TransactionConduit(TioSafeBaseConduit):
'reference': 'reference',
'causality': 'comment',
}
property = {}
property_ = {}
# Translate kw with the good PropertySheet
for k, v in kw.items():
k = mapping.get(k, k)
property[k] = v
object._edit(**property)
property_[k] = v
object._edit(**property_)
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Module Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>ERP5TransactionConduit</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5TioSafe.Conduit.ERP5TransactionConduit</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>module.erp5.ERP5TransactionConduit</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Module Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -25,8 +25,7 @@
#
##############################################################################
from Products.ERP5TioSafe.Conduit.TioSafeBaseConduit import TioSafeBaseConduit
from lxml import etree
from erp5.component.module.TioSafeBaseConduit import TioSafeBaseConduit
class OrganisationERP5IntegrationConduit(TioSafeBaseConduit):
"""
......@@ -35,7 +34,7 @@ class OrganisationERP5IntegrationConduit(TioSafeBaseConduit):
def __init__(self):
self.xml_object_tag = 'node'
def getGidFromObject(self, object):
def getGidFromObject(self, object): # pylint: disable=redefined-builtin
"""
Return the Organisation GID of the object.
"""
......@@ -47,15 +46,15 @@ class OrganisationERP5IntegrationConduit(TioSafeBaseConduit):
"""
return 'Organisation'
def updateNode(self, xml=None, object=None, previous_xml=None, force=0,
def updateNode(self, xml=None, object=None, previous_xml=None, force=0, # pylint: disable=redefined-builtin
simulate=0, **kw):
raise Exception("updateNode: Impossible to update Organisation")
def deleteNode(self, xml=None, object=None, previous_xml=None, force=0,
def deleteNode(self, xml=None, object=None, previous_xml=None, force=0, # pylint: disable=redefined-builtin
simulate=0, **kw):
raise Exception("deleteNode: Impossible to delete Organisation")
def editDocument(self, object=None, **kw):
def editDocument(self, object=None, **kw): # pylint: disable=redefined-builtin
"""
This is the editDocument method inherit of ERP5Conduit. This method
is used to save the information of an Organisation.
......@@ -67,9 +66,8 @@ class OrganisationERP5IntegrationConduit(TioSafeBaseConduit):
'description': 'description',
}
# Translate kw with the PropertySheet
property = {}
property_ = {}
for k, v in kw.items():
k = mapping.get(k, k)
property[k] = v
object._edit(**property)
property_[k] = v
object._edit(**property_)
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Module Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>OrganisationERP5IntegrationConduit</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5TioSafe.Conduit.OrganisationERP5IntegrationConduit</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>module.erp5.OrganisationERP5IntegrationConduit</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Module Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -28,11 +28,11 @@
#
##############################################################################
from Products.ERP5SyncML.SyncMLConstant import XUPDATE_INSERT_OR_ADD_LIST, \
from erp5.component.module.SyncMLConstant import XUPDATE_INSERT_OR_ADD_LIST, \
XUPDATE_DEL, XUPDATE_UPDATE
from Products.ERP5Type.XMLExportImport import MARSHALLER_NAMESPACE_URI
from zLOG import LOG, INFO, WARNING
from Products.ERP5SyncML.Conduit.ERP5Conduit import ERP5Conduit
from erp5.component.module.ERP5Conduit import ERP5Conduit
from lxml import etree
from copy import deepcopy
parser = etree.XMLParser(remove_blank_text=True)
......@@ -83,7 +83,7 @@ class TioSafeBaseConduit(ERP5Conduit):
)
return conflict
def addNode(self, xml=None, object=None, sub_object=None, reset=None,
def addNode(self, xml=None, object=None, sub_object=None, reset=None, # pylint: disable=redefined-builtin
simulate=None, **kw):
"""
A node is added
......@@ -132,7 +132,7 @@ class TioSafeBaseConduit(ERP5Conduit):
return {'conflict_list':conflict_list, 'object': sub_object}
def applyXupdate(self, object=None, object_xml=None, xupdate=None, previous_xml=None, **kw):
def applyXupdate(self, object=None, object_xml=None, xupdate=None, previous_xml=None, **kw): # pylint: disable=redefined-builtin
""" Parse the xupdate and then it will call the conduit. """
conflict_list = []
if isinstance(xupdate, unicode):
......@@ -191,7 +191,7 @@ class TioSafeBaseConduit(ERP5Conduit):
return result_list
def getObjectAsXML(self, object, domain):
def getObjectAsXML(self, object, domain): # pylint: disable=redefined-builtin
"""
This method must be implemented by subclasses as the way to generate the
XML is specific to each side
......@@ -202,7 +202,7 @@ class TioSafeBaseConduit(ERP5Conduit):
"""
raise NotImplementedError
def updateNode(self, xml=None, object=None, object_xml=None, previous_xml=None, force=False,
def updateNode(self, xml=None, object=None, object_xml=None, previous_xml=None, force=False, # pylint: disable=redefined-builtin
simulate=False, reset=False, xpath_expression=None, **kw):
"""
This method browse the xml which allows to update data and update the
......@@ -230,7 +230,7 @@ class TioSafeBaseConduit(ERP5Conduit):
# we may have only the part of an xupdate
else:
# previous_xml is required as an etree type
if type(previous_xml) == str:
if isinstance(previous_xml, str):
previous_xml = etree.XML(previous_xml, parser=parser)
if self.isProperty(xml):
......@@ -265,7 +265,7 @@ class TioSafeBaseConduit(ERP5Conduit):
self.afterUpdateMethod(object, **kw)
return conflict_list
def afterUpdateMethod(self, object, **kw):
def afterUpdateMethod(self, object, **kw): # pylint: disable=redefined-builtin
""" This method is for actions that has to be done just after object
update and which required to have synchronization parameters
"""
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Module Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>TioSafeBaseConduit</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5TioSafe.Conduit.TioSafeBaseConduit</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>module.erp5.TioSafeBaseConduit</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Module Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -27,7 +27,7 @@
#
##############################################################################
from Products.ERP5TioSafe.Conduit.TioSafeBaseConduit import TioSafeBaseConduit
from erp5.component.module.TioSafeBaseConduit import TioSafeBaseConduit
class TioSafeNodeConduit(TioSafeBaseConduit):
......@@ -37,10 +37,10 @@ class TioSafeNodeConduit(TioSafeBaseConduit):
def __init__(self):
self.xml_object_tag = 'node'
def getObjectAsXML(self, object, domain):
def getObjectAsXML(self, object, domain): # pylint: disable=redefined-builtin
return object.asXML()
def _createContent(self, xml=None, object=None, object_id=None, sub_object=None,
def _createContent(self, xml=None, object=None, object_id=None, sub_object=None, # pylint: disable=redefined-builtin
reset_local_roles=0, reset_workflow=0, simulate=0, **kw):
# if exist namespace retrieve only the tag
index = 0
......@@ -52,7 +52,7 @@ class TioSafeNodeConduit(TioSafeBaseConduit):
# browse the xml
for node in xml:
# works on tags, no on comments
if type(node.tag) is not str:
if not isinstance(node.tag, str):
continue
# Retrieve the tag
tag = node.tag.split('}')[index]
......@@ -84,7 +84,7 @@ class TioSafeNodeConduit(TioSafeBaseConduit):
return object.person_module(person_id=new_id)[0]
def _deleteContent(self, object=None, object_id=None, **kw):
def _deleteContent(self, object=None, object_id=None, **kw): # pylint: disable=redefined-builtin
""" We do not delete nodes """
pass
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Module Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>TioSafeNodeConduit</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5TioSafe.Conduit.TioSafeNodeConduit</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>module.erp5.TioSafeNodeConduit</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Module Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -28,7 +28,7 @@
##############################################################################
from Products.ERP5Type.Utils import cartesianProduct
from Products.ERP5TioSafe.Conduit.TioSafeBaseConduit import TioSafeBaseConduit
from erp5.component.module.TioSafeBaseConduit import TioSafeBaseConduit
from lxml import etree
from zLOG import LOG
......@@ -39,10 +39,10 @@ class TioSafeResourceConduit(TioSafeBaseConduit):
def __init__(self):
self.xml_object_tag = 'resource'
def getObjectAsXML(self, object, domain):
def getObjectAsXML(self, object, domain): # pylint: disable=redefined-builtin
return object.asXML()
def _createContent(self, xml=None, object=None, object_id=None, sub_object=None,
def _createContent(self, xml=None, object=None, object_id=None, sub_object=None, # pylint: disable=redefined-builtin
reset_local_roles=0, reset_workflow=0, simulate=0, **kw):
LOG("TioSafeNodeConduit._createConten", 300, "xml = %s" %(etree.tostring(xml, pretty_print=1),))
......@@ -52,7 +52,6 @@ class TioSafeResourceConduit(TioSafeBaseConduit):
index = -1
# init the new_id of the product and the checker of the creation
new_id = None
product_created = False
# this dict contains the element to set to the product
keyword = {}
# this dict will contains a list of tuple (base_category, vairiation)
......@@ -63,7 +62,7 @@ class TioSafeResourceConduit(TioSafeBaseConduit):
# browse the xml
for node in xml:
# works on tags, not on comments
if type(node.tag) is not str:
if not isinstance(node.tag, str):
continue
tag = node.tag.split('}')[index]
LOG("browsing tag %s, value %s" %(tag, node.text), 300, "keyword = %s" %(keyword,))
......@@ -121,7 +120,7 @@ class TioSafeResourceConduit(TioSafeBaseConduit):
return object[new_id]
def _deleteContent(self, object=None, object_id=None, **kw):
def _deleteContent(self, object=None, object_id=None, **kw): # pylint: disable=redefined-builtin
""" This method allows to remove a product in the integration site """
delete_method_id = "deleteProduct" # XXX-AUREL : must find a way to fix this
delete_method = getattr(object, delete_method_id, None)
......@@ -139,7 +138,6 @@ class TioSafeResourceConduit(TioSafeBaseConduit):
conflict_list = []
xpath_expression = xml.get('select')
tag = xpath_expression.split('/')[-1]
integration_site = document.context.getParentValue()
new_value = xml.text
# retrieve the previous xml etree through xpath
......@@ -174,7 +172,7 @@ class TioSafeResourceConduit(TioSafeBaseConduit):
# create and fill a conflict when the integration site value, the erp5
# value and the previous value are differents
current_value = getter_value_dict[tag]
if type(current_value) == float:
if isinstance(current_value, float):
current_value = '%.6f' % current_value
if isinstance(current_value, unicode):
current_value = current_value.encode('utf-8')
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Module Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>default_reference</string> </key>
<value> <string>TioSafeResourceConduit</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value> <string>Products.ERP5TioSafe.Conduit.TioSafeResourceConduit</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>module.erp5.TioSafeResourceConduit</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Module Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
erp5_accounting
erp5_syncml
erp5_trade
erp5_web_service
\ No newline at end of file
module.erp5.AccountERP5IntegrationConduit
module.erp5.AccountingERP5IntegrationConduit
module.erp5.ERP5NodeConduit
module.erp5.ERP5PaymentTransactionConduit
module.erp5.ERP5ResourceConduit
module.erp5.ERP5TransactionConduit
module.erp5.OrganisationERP5IntegrationConduit
module.erp5.TioSafeBaseConduit
module.erp5.TioSafeNodeConduit
module.erp5.TioSafeResourceConduit
\ No newline at end of file
......@@ -35,7 +35,6 @@ From ERP5 subversion repository:
* ERP5Form
* ERP5OOo
* ERP5Security
* ERP5SyncML
* ERP5Type
* ZSQLCatalog
......
#!/usr/bin/python
# coding=UTF-8
import urllib,urllib2
import socket
import time
from optparse import OptionParser
from lxml import etree
parser = etree.XMLParser(remove_blank_text=True)
class OptionParser(OptionParser):
def check_required (self, opt):
option = self.get_option(opt)
# Assumes the option's 'default' is set to None!
if getattr(self.values, option.dest) is None:
self.error("%s option not supplied" % option)
cmd_parser = OptionParser()
cmd_parser.add_option("--host", help="address of this small server (typically, it's the ip of this computer)")
cmd_parser.add_option("--publication", help="address of the publication (e.g. http://localhost:9080/erp5Serv)")
cmd_parser.add_option("-p", "--port", type="int", help="port used by this server (default is 1234)", default=1234)
(options, args) = cmd_parser.parse_args()
cmd_parser.check_required("--publication")
cmd_parser.check_required("--host")
#CONFIGURATION SECTION
#address of this small server :
#Host = '192.168.242.247'
Host = options.host
#address of the publication :
#publication_url = 'http://localhost:9080/erp5Serv'
publication_url = options.publication
#address use to transmit the message received from the external client :
to_url = publication_url+"/portal_synchronizations/readResponse"
#port of this server :
#Port = 1234
Port = options.port
#address of the this server :
syncml_server_url = 'http://%s:%s' % (Host, Port)
#socket :
sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # reuse the same socket
# if already open
#END CONFIGURATION SECTION
CRLF = "\015\012"
#in unix, it's the same as \r\n, and on windows, it's the same as \n (\r on mac)
#this octal constant just increase a little this application portability
def nodeToString(node):
"""
return an xml string corresponding to the node
"""
return etree.tostring(node, encoding='utf-8')
def xml2wbxml(xml):
"""
convert xml string to wbxml using a temporary file
"""
import os
# XXX we must check at the begining if xml2wbxml is installed
# it seems that now there is a python biding for this : pywbxml
f = open('/tmp/xml2wbxml', 'w')
f.write(xml)
f.close()
os.system('/usr/bin/xml2wbxml -o /tmp/xml2wbxml /tmp/xml2wbxml')
f = open('/tmp/xml2wbxml', 'r')
wbxml = f.read()
f.close()
return wbxml
def wbxml2xml(wbxml):
"""
convert wbxml string to xml using a temporary file
"""
import os
f = open('/tmp/wbxml2xml', 'w')
f.write(wbxml)
f.close()
os.system('/usr/bin/wbxml2xml -o /tmp/wbxml2xml /tmp/wbxml2xml')
f = open('/tmp/wbxml2xml', 'r')
xml = f.read()
f.close()
return xml
def hexdump(raw=''):
"""
print raw in readable format without broke the terminal output !
"""
buf = ""
line = ""
start = 0
done = False
while not done:
end = start + 16
max = len(raw)
if end > max:
end = max
done = True
chunk = raw[start:end]
for i in xrange(len(chunk)):
if i > 0:
spacing = " "
else:
spacing = ""
buf += "%s%02x" % (spacing, ord(chunk[i]))
if done:
for i in xrange(16 - (end % 16)):
buf += " "
buf += " "
for c in chunk:
val = ord(c)
if val >= 33 and val <= 126:
buf += c
else:
buf += "."
buf += "\n"
start += 16
return buf
def getClientUrl(text):
"""
find the client url in the text and return it
"""
document = etree.XML(text, parser=parser)
# XXX this xpath expression have to be rewrited in a generic way to handle
# namspace
client_url = '%s' % document.xpath('string(//SyncHdr/Source/LocURI)')
# client_url = '%s' % document.xpath('string(//syncml:SyncHdr/syncml:Source/syncml:LocURI)', namespaces={'syncml':'SYNCML:SYNCML1.2'})
return client_url
def sendResponse(text, to_url, client_url):
"""
send the message receive from the external client to erp5 server
"""
result = None
opener = urllib2.build_opener()
urllib2.install_opener(opener)
to_encode = {}
print '\nsendResponse...'
text = wbxml2xml(text)
text = text.replace(syncml_server_url, publication_url)
text = text.replace(client_url, syncml_server_url)
print "text = ",text
to_encode['text'] = text
to_encode['sync_id'] = 'Person'
headers = {'Content-type': 'application/vnd.syncml+xml'}
encoded = urllib.urlencode(to_encode)
data=encoded
request = urllib2.Request(url=to_url, data=data)
try:
result = urllib2.urlopen(request).read()
except socket.error, msg:
print 'error, url:%s ,data : %s'%(to_url, data)
except urllib2.URLError, msg:
print "sendResponse, can't open url : %s" % to_url
return result
def main():
sock.bind((Host,Port))
# we just listen to one and unique connection
sock.listen(1)
text = ''
# the script stop here until a client connect to him
print 'wait for a client connection...'
client, address = sock.accept()
print "the host ",address," is connected."
while 1:
print('\n\nwait for message ...')
msg = client.recv(1024) # we receive 1024 caracter max
if not msg: # if we receive nothing
break
elif not msg.startswith('POST'):
text = text + msg
if text.endswith('\x01\x01'):
client_url = getClientUrl(wbxml2xml(text))
response = sendResponse(text=text, to_url=to_url, client_url=client_url)
if response:
response = response.replace(syncml_server_url, client_url)
response = response.replace(publication_url, syncml_server_url)
print "\nresponse = \n",response
response = xml2wbxml(response)
print "response send to the phone :\n", hexdump(response)
date_to_print = time.strftime("%a, %d %b %Y %H:%M:%S GMT")
head = CRLF.join((
"HTTP/1.1 200 OK",
"Date: %s GMT" % date_to_print,
"Server: myPythonServer",
"Content-Length: %s" % len(response),
"Content-Type: application/vnd.syncml+wbxml",
))
message = "%s%s%s%s" % (head, CRLF, CRLF, response)
#here it's necessary to have 2 CRLF, for more details
#see http://www.w3.org/Protocols/rfc2616/rfc2616.html
client.send(message)
text=''
else:
print "this message is a POST header."
sock.close()
if __name__ == "__main__":
main()
Problem
General
It's really difficult to synchronise different zope databases systems.
(there is a product by Zope Corp which does that but is
very expensive and not so public)
There are two different problems
- synchronising the same ODB (object database) on multiple servers / sites
- synchronising some data stored on different ODB on multiple servers / sites
The first case is the case of one company with a global ODB
The second case is the case of 2 companies who want to share their
mutual orders but not other orders
If case 2 is solved, then case 1 too. We shall solve case 2
by using an intermediate XML format specific to each application
Specific problems
Most of synchronisations systems needs a database wich acts like a master, and
all slaves are like a copy of the main database (case 1)
Thoses systems don't allow to copy only a part of the data, they copy all
objects from the master database to all slaves databases.
Proposed Solution
<img src="simple_schema.jpg">
This project proposes to create a Zope Product that have to synchronise
databases. This synchronisation have to update only the part of the database
needed.
Specifically we want to achieve the following goals :
o manage a list of subscribers who can take a subscription to a query.
o manage queries applied to a database of objects.
o generate XML in order to communicate with several databases.
o use filters, so that generated XML only contains part of the attributes of
objects in the ODB (1 XML file per Zope Objet / Document (ex. 1 XML file per
order)). For example, private comments should not be exported in the generated
XML file
o synchronise databases with the content of the XML.
There's already a generic synchronisation system for Zope : ZSyncer. But this system
is too limited for all our needs.
Details
Objects
All objects will have the following attributes
- id : the standard object id
- uid : a global object id wich is unique to each ZODB
- rid : the standard object id in the master ODB the object
was subscribed from (remote id).
- sid : the id of the subsription/synchronisation object wich this
object was generated from.
A mapping from id to rid and rid to id is available through the
subscription sid
First step : initialisation :
<img src="steps.jpg">
1 We create a subscription inside portal_synchronisations in the slave.
We define for that subscription
- id, title, description
- the URL of the master (which contains an index of all
files we can sync) - this URL defines a public
synchronisation handle in the master server
- a local query (SQL Method) to define the local realm of
synchronisation
- an import Conduit in order to validate data,
calculate differences and import differences. This is where
we define the format of the data we receive from the master
- a local PageTemplate/DTML to converte local objects to XML.
This is where we define both the format we send to the master
and the realm of attributes we synchronise (ie. the mapping)
2 The slave sends the "initialisation package" (SyncML specification), in this package,
appears several elements :
- the SynchHdr element with several informations about the protocol used. We will
put the query in this element, and also authentification informations.
- the Alert element, in order to specify what kind of synchronisation we want,
for us it will be the Alert 200 wich specifies a client-initiated, two way
synchronisation.
3 We create a publication in the master database. We define
- id, title, description
- a local query (SQL Method) to define the local realm of
publication (which objects do we publish)
- a local PageTemplate/DTML to convert local objects to XML
(what do we publish in each object and with what format)
- an import Conduit in order to be able to commit changes
sent by subscribed databases into the master database (OPTION)
A this step, we produce all XML files from master ODB
4 The master sends the "Initialisation package" to the client with :
- the SynchHdr element with several informations about the protocol used,
and also authentification informations.
- the Status element, in order to respond to the alert command sent by the client.
A code for the status is returned, it will be typically 212 if the authentification
is fine for the client.
- differences between the two databases.
- the Alert element, in order to specify what kind of synchronisation we want,
for us it will be 201 wich specifies a client-initiated, two-way slow-synchronisation.
This just means that both the server and the client sends all their data. Each
data must specify the DTD used.
At this step, we may eventually record the subscriber in the publication
of the master database for... (OPTION). This is like
the subscribtion is becoming member of mail list to be informed of
changes of a publication
//- if the slave already have some data (for example an addressbook) corresponding
//to the query (for example all people from the company Nexedi), then thoses data
//must be sent by the same time. Each data must specify the DTD used.
//6 Finally the slave import in his databases all objects from the master.
Second step : synchronisation :
General idea
M master
S slave
C conflicts
t continuous time
tn discrete time
1 calculate the difference on the slave DS(tn) = S(tn) - S(tn-1)
1 upload the differences to the master or send by email or whatever
1 calculate the difference on the master DM(tn) = M(tn) - M(tn-1)
1 update the master with differences from the slave M(tn) <- M(tn) + DS(tn)
1 Manage conflicts and if possible solve them on the master C(tn)
1 upload the differences and conflicts resolution to the slave
1 update the slave S(tn) <- S(tn) + DM(tn) + C(tn)
Detail implementation
blabla
References
XMLDiff - http://www.garshol.priv.no/download/xmltools/prod/xmldiff.html
SyncML - http://www.syncml.org
ZSyncer - http://www.zope.org/Members/andym/ZSyncer
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2002-2010 Nexedi SA and Contributors. All Rights Reserved.
# Jean-Paul Smets-Solanes <jp@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# 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.
#
##############################################################################
"""
ERP5Catalog provides an extended catalog based on ZSQLCatalog
and extended local roles management
"""
import sys, Permissions, os
from App.Common import package_home
this_module = sys.modules[ __name__ ]
product_path = package_home( globals() )
this_module._dtmldir = os.path.join( product_path, 'dtml' )
# Update ERP5 Globals
from Products.ERP5Type.Utils import initializeProduct, updateGlobals
document_classes = updateGlobals(this_module, globals(),
permissions_module=Permissions)
def initialize( context ):
# Import Product Components
from Tool import SynchronizationTool
import Document
# Define documents, classes, constructors and tools
object_classes = ()
content_constructors = ()
content_classes = ()
portal_tools = (SynchronizationTool.SynchronizationTool,)
# Do initialization step
initializeProduct(context, this_module, globals(),
document_module=Document,
document_classes=document_classes,
object_classes=object_classes,
portal_tools=portal_tools,
content_constructors=content_constructors,
content_classes=content_classes)
Conflict management with n clients, n >= 2
Description :
- We have 4 boxes, a server A et three clients : B, C and D
- first, A, B,C et D are synchronized
- B change the title of /w/x/truc
- C change the title of /w/x/truc
- D change the title of /w/x/truc
- We do the synchronization in this order : B, D and D
- The server A takes the value of B (because nothing was changed on A)
- there is a conflict between A and C
- there is a conflict between A and D
- So we get on the server A 2 Conflict objets and 1 local object, so that
we can retrieve 3 different versions of the object
- Clients C and D must know that there is a conflict from /w/x
The SyncML protocol doesn't allow us to tell to the client that the
conflict is on /w/x/truc
- We have to be able to get on the server the 3 different objects
- getSynchronizationState should return CONFLICT for each subscription
in conflict.
- for each Conflict object, we should have a getRemoteObject method wich
returns the /w/x/truc object from C and the next Conflict should returns
the object from D
Result of getSynchronizationState :
- In the case of a client with only one subscription, this is quite easy,
we should returns the state of the subscription
- In the case of the server, it is more complicated, we can have by the
same time depending on subscribers the following states : CONFLICT,
NOT_SYNCHRONIZED, SYNCHRONIZED...
- So we have to give the state associated with the subscriber, so we should
not returns only a state, but a mapping between subscribers and states
- So we can deduce that we should have a result like this :
[ [subscriber1,state1], [subscriber2,state2]...]
Howto store conflicts :
- We should take again the example with the server and the 3 clients
- A, B, C et D are synchronized
- B, C et D change the title and description of /w/x/truc
and also the title and description of /w/x/machin
- We do the synchronization in this order : B, D and D
- The server A takes the value of B (because nothing was changed on A)
- there is a conflict between A and C
- there is a conflict between A and D
- So we have on the server 2 local objects and 8 Conflict objects (DEPRECATED):
- Conflict for /w/x/truc : title for subscription C (DEPRECATED)
- Conflict for /w/x/truc : title for subscription D (DEPRECATED)
- Conflict for /w/x/truc : description for subscription C (DEPRECATED)
- Conflict for /w/x/truc : description for subscription D (DEPRECATED)
- Conflict for /w/x/machin : title for subscription C (DEPRECATED)
- Conflict for /w/x/machin : title for subscription D (DEPRECATED)
- Conflict for /w/x/machin : description for subscription C (DEPRECATED)
- Conflict for /w/x/machin : description for subscription D (DEPRECATED)
- This is bad, we can do a getRemoteObject because in this case we get
only a part of the remote object, we should have only 4 Conflicts
- XXX I have to change immediatly the way of storing conflict in order to
have the following list :
- Conflict1 for /w/x/truc : title and description for subscription C
- Conflict2 for /w/x/truc : title and description for subscription D
- Conflict3 for /w/x/machin : title and description for subscription C
- Conflict4 for /w/x/machin : title and description for subscription D
- The good way is to store a list of xupdate on each Conflict
Howto solve conflicts :
- Let's says that we take the object given by Conflict 2 for /w/x/truc and
we take the version given by the server for the object /w/x/machin
- Do we have to solve conflict one by one or when we choose one version for
one Conflict, it will remove other versions ???
I guess the best way is to just solve conflict one by one, then we are still
free to make another method wich solve for all versions by the same time.
- So we have to do :
Conflict2.setRemoteObject()
Conflict1.setLocalObject() # wich is the version of D because of the previous call
Conflict3.setLocalObject()
Conflict4.setLocalObject()
- May be we can do a global method, like :
Conflict2.setGlobalRemoteObject() wich implicitly call
Conflict1.setLocalObject()
and Conflict3.setGlobalLocalObject() wich implicitly call
Conflict4.setLocalObject()
- Conflict2.setRemoteObject() have to apply all xupdate strings stored
in Conflict2. Then it have to set the status as CONFLICT_CLIENT_WIN.
- Conflict3.setLocalObject() have to set the status as CONFLICT_MERGE. How ??
- Probably the best way is to call the synchronizationTool wich know everything
about subscription and subscriber.
- synchronizationtool.setLocalObject should have as parameter: the conflict (wich
store the subscriber), that's all
- then we can look at the signature of the object, delete the corresponding
Conflict, and if there is no conflict left, then we can set the signature
as CONFLICT_MERGE
- At this state, we do have the /w/x/truc of D, and the /w/x/machin of B, and
there is no conflict left, at least on the server side.
#- at the time of the next synchronization, the server should send is new version
of /w/x/truc and /w/x/machin to B, C and D, so that everyone is synchronized
without conflict.
# -*- coding: utf-8 -*-
from conduit import IConduit
......@@ -104,7 +104,7 @@ class XMLObject( Folder ):
"""
Replace the content of this object by providing an xml content
"""
from Products.ERP5SyncML.Conduit.ERP5Conduit import ERP5Conduit
from erp5.component.module.ERP5Conduit import ERP5Conduit
conduit = ERP5Conduit()
conduit.addNode(object=self, xml=xml)
......
......@@ -10,7 +10,7 @@ class _ERP5(ERP5TypeTestSuite):
realtime_output = False
enabled_product_list = ('CMFActivity', 'CMFCategory', 'ERP5', 'ERP5Catalog',
'ERP5Form',
'ERP5OOo', 'ERP5Security', 'ERP5SyncML', 'ERP5Type',
'ERP5OOo', 'ERP5Security', 'ERP5Type',
'Formulator', 'ERP5Workflow',
'HBTreeFolder2', 'MailTemplates',
'PortalTransforms', 'TimerService', 'ZLDAPConnection',
......@@ -80,9 +80,7 @@ class ERP5(_ERP5):
or test_case in ('testERP5LdapCatalog', # XXX (Ivan), until LDAP server is available this test will alway fail
# tests reading selenium tables from erp5.com
# not maintained
'testAccounting_l10n_fr_m9',
# Not a test
'testERP5SyncMLMixin'
'testAccounting_l10n_fr_m9'
):
continue
test_list.append(full_test_case)
......
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