Author: Eli Stevens <[email protected]>
Branch: numpypy_pickle_compat
Changeset: r85722:cbe05cb6c942
Date: 2016-06-25 20:11 -0700
http://bitbucket.org/pypy/pypy/changeset/cbe05cb6c942/

Log:    Changes reported location of _reconstruct function to allow pypy
        pickles of ndarrays to be unpickled on cpython.

diff --git a/pypy/module/micronumpy/app_numpy.py 
b/pypy/module/micronumpy/app_numpy.py
--- a/pypy/module/micronumpy/app_numpy.py
+++ b/pypy/module/micronumpy/app_numpy.py
@@ -1,9 +1,44 @@
 from __future__ import absolute_import
 
 import math
+import pickle
+import struct
+import types
 
 import _numpypy
-from _numpypy.multiarray import set_docstring
+from _numpypy.multiarray import set_docstring, _reconstruct
+from copy_reg import _extension_registry
+
+
+def _save_global_reconstruct(self, obj, name=None, pack=struct.pack):
+    """
+    This function is responsible for essentially lying about the origins of the
+    numpy _reconstruct function so that pickles of numpy ndarrays can be
+    pickled in pypy and unpickled in cpython. Going in the other direction
+    worked without needing a change.
+
+    :param self: Pickler (or subclass) instance.
+    :param obj: Object to pickle; in this case always a BuiltinFunctionType.
+    :param name: Ignored in the _reconstruct case.
+    :param pack: Ignored in the _reconstruct case.
+    :return: None
+    """
+    if obj is _reconstruct:
+        module = 'numpy.core.multiarray'
+        name = '_reconstruct'
+
+        # It's not clear how to handle this properly. Perhaps fall back to
+        # original implementation?
+        assert not _extension_registry.get((module, name))
+        assert not _extension_registry.get(('_numpypy.multiarray', name))
+
+        self.write(pickle.GLOBAL + module + '\n' + name + '\n')
+        self.memoize(obj)
+    else:
+        self.save_global(obj, name, pack)
+
+pickle.Pickler.dispatch[types.BuiltinFunctionType] = _save_global_reconstruct
+
 
 def arange(start, stop=None, step=1, dtype=None):
     '''arange([start], stop[, step], dtype=None)
diff --git a/pypy/module/micronumpy/test/test_pickling_app.py 
b/pypy/module/micronumpy/test/test_pickling_app.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/test/test_pickling_app.py
@@ -0,0 +1,43 @@
+"""App-level tests for support.py"""
+import sys
+import py
+
+from pypy.module.micronumpy.test.test_base import BaseNumpyAppTest
+from pypy.conftest import option
+
+class AppTestPicklingNumpy(BaseNumpyAppTest):
+    spaceconfig = dict(usemodules=["micronumpy", "struct", "binascii"])
+
+    def setup_class(cls):
+        if option.runappdirect and '__pypy__' not in sys.builtin_module_names:
+            py.test.skip("pypy only test")
+        BaseNumpyAppTest.setup_class.im_func(cls)
+
+    def test_pickle_module(self):
+        import pickle
+        import numpy as np
+
+        pkl_str = pickle.dumps(np.array([1,2,3], dtype=np.int8))
+
+        # print repr(pkl_str)
+
+        assert '_numpypy' not in pkl_str
+        assert 'numpy.core.multiarray' in pkl_str
+
+        # with open('ndarray-pypy-compat-cpython.pkl', 'w') as f:
+        #     pickle.dump(np.array([1,2,3], dtype=np.int8), f)
+
+    def test_cPickle_module(self):
+        import cPickle as pickle
+        import numpy as np
+
+        pkl_str = pickle.dumps(np.array([1,2,3], dtype=np.int8))
+
+        # print repr(pkl_str)
+
+        assert '_numpypy' not in pkl_str
+        assert 'numpy.core.multiarray' in pkl_str
+
+        # with open('ndarray-pypy-compat-cpython.pkl', 'w') as f:
+        #     pickle.dump(np.array([1,2,3], dtype=np.int8), f)
+
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to