From e43a4a616858fbf747c79774b37a8e13a9521428 Mon Sep 17 00:00:00 2001
From: Yusei Tahara <yusei@nexedi.com>
Date: Thu, 10 Jan 2008 17:37:47 +0000
Subject: [PATCH] Support reduce type object.

git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@18653 20353a03-c40f-0410-a6d1-a30d3c3de9de
---
 product/ERP5Type/patches/ppml.py        | 22 +++++++
 product/ERP5Type/tests/testXMLPickle.py | 88 +++++++++++++++++++++++++
 2 files changed, 110 insertions(+)
 create mode 100644 product/ERP5Type/tests/testXMLPickle.py

diff --git a/product/ERP5Type/patches/ppml.py b/product/ERP5Type/patches/ppml.py
index 09f2b7277e..bdeab926bc 100644
--- a/product/ERP5Type/patches/ppml.py
+++ b/product/ERP5Type/patches/ppml.py
@@ -662,6 +662,28 @@ def save_unicode(self, tag, data):
 
 ppml.save_unicode = save_unicode
 
+def save_object(self, tag, data):
+    if len(data)==5:
+        #OBJECT
+        v='('+data[2]
+        x=data[3][1:]
+        stop=string.rfind(x,'t')  # This seems
+        if stop>=0: x=x[:stop]    # wrong!
+        v=save_put(self, v+x+'o', data[1])
+        v=v+data[4]+'b' # state
+        return v
+    else:
+        #REDUCE
+        #data does not contain state.(See Object.__setstate__ definition)
+        #So, we can assume that this is a reduce. (Yusei)
+        v='('+data[2]
+        v=save_put(self, data[2]+data[3], data[1])
+        v=v+'R'
+        return v
+
+ppml.save_object = save_object
+
+
 class xmlPickler(NoBlanks, xyap):
     # XXX fix a bug in xyap.
     def unknown_endtag(self, tag):
diff --git a/product/ERP5Type/tests/testXMLPickle.py b/product/ERP5Type/tests/testXMLPickle.py
new file mode 100644
index 0000000000..f22af31851
--- /dev/null
+++ b/product/ERP5Type/tests/testXMLPickle.py
@@ -0,0 +1,88 @@
+##############################################################################
+#
+# Copyright (c) 2008 Nexedi SARL and Contributors. All Rights Reserved.
+#                    TAHARA Yusei <yusei@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.
+#
+##############################################################################
+
+import unittest
+import pickle
+import re
+import xml.parsers.pyexpat
+from StringIO import StringIO
+from Shared.DC.xml import ppml
+
+
+class DummyClass:
+  """
+  A dummy data class
+  """
+
+  def __init__(self):
+    self.data = []
+
+
+class TestXMLPickle(unittest.TestCase):
+
+  def test_reduce(self):
+    """
+    Make sure that a object which uses reduce for pickling can be pickled by xml pickler.
+    """
+    obj = DummyClass()
+    obj.data.append(1)
+    obj.data.append(obj)
+    obj.data.append(obj.data)
+
+    pattern = re.compile('WAA') # regex pattern object uses reduce.(See sre.py)
+    obj.data.append(pattern)
+
+    pickled_string = pickle.dumps(obj)
+    xmldata = str(ppml.ToXMLloads(pickled_string))
+
+    output = StringIO()
+
+    F=ppml.xmlPickler()
+    F.file = output
+    F.binary = 1
+
+    p=xml.parsers.pyexpat.ParserCreate()
+    p.CharacterDataHandler=F.handle_data
+    p.StartElementHandler=F.unknown_starttag
+    p.EndElementHandler=F.unknown_endtag
+
+    r = p.Parse(xmldata)
+
+    reconstructed_pickled_data = F._stack[0][0]
+    reconstructed_obj = pickle.loads(reconstructed_pickled_data)
+
+    self.assert_(reconstructed_obj.__class__ is DummyClass)
+    self.assert_(type(getattr(reconstructed_obj, 'data', None)) is list)
+    self.assertEqual(reconstructed_obj.data[0], 1)
+    self.assert_(reconstructed_obj.data[1] is reconstructed_obj)
+    self.assert_(reconstructed_obj.data[2] is reconstructed_obj.data)
+    self.assert_(type(reconstructed_obj.data[3]) is type(pattern))
+    self.assertEqual(reconstructed_obj.data[3].pattern, 'WAA')
+
+if __name__ == '__main__':
+  unittest.main()
-- 
2.30.9