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