From: <pj...@us...> - 2009-04-17 03:44:56
|
Revision: 6235 http://jython.svn.sourceforge.net/jython/?rev=6235&view=rev Author: pjenvey Date: 2009-04-17 03:44:35 +0000 (Fri, 17 Apr 2009) Log Message: ----------- o fix memoization with cyclic structures: http://bugs.python.org/issue998998 o cleanup persistent_id/load handling, allow persistent_load as a list Modified Paths: -------------- trunk/jython/Lib/test/test_cpickle_jy.py trunk/jython/src/org/python/modules/cPickle.java Modified: trunk/jython/Lib/test/test_cpickle_jy.py =================================================================== --- trunk/jython/Lib/test/test_cpickle_jy.py 2009-04-17 01:38:24 UTC (rev 6234) +++ trunk/jython/Lib/test/test_cpickle_jy.py 2009-04-17 03:44:35 UTC (rev 6235) @@ -7,13 +7,34 @@ import unittest from test import test_support +class MyClass(object): + pass + + class CPickleTestCase(unittest.TestCase): def test_zero_long(self): self.assertEqual(cPickle.loads(cPickle.dumps(0L, 2)), 0L) self.assertEqual(cPickle.dumps(0L, 2), pickle.dumps(0L, 2)) + def test_cyclic_memoize(self): + # http://bugs.python.org/issue998998 - cPickle shouldn't fail + # this, though pickle.py still does + m = MyClass() + m2 = MyClass() + s = set([m]) + m.foo = set([m2]) + m2.foo = s + + s2 = cPickle.loads(cPickle.dumps(s)) + self.assertEqual(len(s2), 1) + m3 = iter(s2).next() + self.assertEqual(len(m3.foo), 1) + m4 = iter(m3.foo).next() + self.assertEqual(m4.foo, s2) + + def test_main(): test_support.run_unittest(CPickleTestCase) Modified: trunk/jython/src/org/python/modules/cPickle.java =================================================================== --- trunk/jython/src/org/python/modules/cPickle.java 2009-04-17 01:38:24 UTC (rev 6234) +++ trunk/jython/src/org/python/modules/cPickle.java 2009-04-17 03:44:35 UTC (rev 6235) @@ -770,14 +770,8 @@ private void save(PyObject object, boolean pers_save) { - if (!pers_save) { - if (persistent_id != null) { - PyObject pid = persistent_id.__call__(object); - if (pid != Py.None) { - save_pers(pid); - return; - } - } + if (!pers_save && persistent_id != null && save_pers(object, persistent_id)) { + return; } int d = get_id(object); @@ -801,12 +795,8 @@ if (save_type(object, t)) return; - if (inst_persistent_id != null) { - PyObject pid = inst_persistent_id.__call__(object); - if (pid != Py.None) { - save_pers(pid); - return; - } + if (!pers_save && inst_persistent_id != null && save_pers(object, inst_persistent_id)) { + return; } if (Py.isSubClass(t, PyType.TYPE)) { @@ -859,13 +849,20 @@ "Second element of tupe returned by " + reduce.__repr__() + " must be a tuple"); } - save_reduce(callable, arg_tup, state, listitems, dictitems, putMemo(d, object)); - + save_reduce(callable, arg_tup, state, listitems, dictitems, object); } - final private void save_pers(PyObject pid) { + final private boolean save_pers(PyObject object, PyObject pers_func) { + PyObject pid = pers_func.__call__(object); + if (pid == Py.None) { + return false; + } + if (protocol == 0) { + if (!Py.isInstance(pid, PyString.TYPE)) { + throw new PyException(PicklingError, "persistent id must be string"); + } file.write(PERSID); file.write(pid.toString()); file.write("\n"); @@ -873,10 +870,12 @@ save(pid, true); file.write(BINPERSID); } + return true; } final private void save_reduce(PyObject callable, PyObject arg_tup, - PyObject state, PyObject listitems, PyObject dictitems, int memoId) + PyObject state, PyObject listitems, PyObject dictitems, + PyObject object) { PyObject callableName = callable.__findattr__("__name__"); if(protocol >= 2 && callableName != null @@ -894,7 +893,10 @@ save(arg_tup); file.write(REDUCE); } - put(memoId); + + // Memoize + put(putMemo(get_id(object), object)); + if (listitems != Py.None) { batch_appends(listitems); } @@ -1697,17 +1699,30 @@ final private void load_persid() { - String pid = file.readlineNoNl(); - push(persistent_load.__call__(new PyString(pid))); + load_persid(new PyString(file.readlineNoNl())); } final private void load_binpersid() { - PyObject pid = pop(); - push(persistent_load.__call__(pid)); + load_persid(pop()); } + final private void load_persid(PyObject pid) { + if (persistent_load == null) { + throw new PyException(UnpicklingError, + "A load persistent id instruction was encountered,\n" + + "but no persistent_load function was specified."); + } + if (persistent_load instanceof PyList) { + ((PyList)persistent_load).append(pid); + } else { + pid = persistent_load.__call__(pid); + } + push(pid); + } + + final private void load_none() { push(Py.None); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |