[pypy-commit] pypy cpyext-pickle: minimal fixes to enable pickling a PyCFunction object

mattip pypy.commits at gmail.com
Wed May 25 14:36:34 EDT 2016


Author: Matti Picus <matti.picus at gmail.com>
Branch: cpyext-pickle
Changeset: r84689:024c98fad224
Date: 2016-05-25 21:35 +0300
http://bitbucket.org/pypy/pypy/changeset/024c98fad224/

Log:	minimal fixes to enable pickling a PyCFunction object

diff --git a/lib-python/2.7/pickle.py b/lib-python/2.7/pickle.py
--- a/lib-python/2.7/pickle.py
+++ b/lib-python/2.7/pickle.py
@@ -285,7 +285,10 @@
         if f:
             f(self, obj) # Call unbound method with explicit self
             return
-
+        elif 'builtin' in str(t):
+            # specifically cpyext builtin types
+            self.save_global(obj)
+            return
         # Check copy_reg.dispatch_table
         reduce = dispatch_table.get(t)
         if reduce:
diff --git a/pypy/module/cpyext/methodobject.py b/pypy/module/cpyext/methodobject.py
--- a/pypy/module/cpyext/methodobject.py
+++ b/pypy/module/cpyext/methodobject.py
@@ -44,8 +44,8 @@
                    dealloc=cfunction_dealloc)
 
 def cfunction_attach(space, py_obj, w_obj):
+    assert isinstance(w_obj, W_PyCFunctionObject)
     py_func = rffi.cast(PyCFunctionObject, py_obj)
-    assert isinstance(w_obj, W_PyCFunctionObject)
     py_func.c_m_ml = w_obj.ml
     py_func.c_m_self = make_ref(space, w_obj.w_self)
     py_func.c_m_module = make_ref(space, w_obj.w_module)
diff --git a/pypy/module/cpyext/test/test_arraymodule.py b/pypy/module/cpyext/test/test_arraymodule.py
--- a/pypy/module/cpyext/test/test_arraymodule.py
+++ b/pypy/module/cpyext/test/test_arraymodule.py
@@ -73,5 +73,6 @@
         module = self.import_module(name='array')
         arr = module.array('i', [1,2,3,4])
         s = pickle.dumps(arr)
+        assert s == "carray\n_reconstruct\np0\n(S'i'\np1\n(lp2\nI1\naI2\naI3\naI4\natp3\nRp4\n."
         rra = pickle.loads(s) # rra is arr backwards
         assert arr.tolist() == rra.tolist()
diff --git a/pypy/objspace/std/objectobject.py b/pypy/objspace/std/objectobject.py
--- a/pypy/objspace/std/objectobject.py
+++ b/pypy/objspace/std/objectobject.py
@@ -182,7 +182,13 @@
     if w_reduce is not None:
         w_cls = space.getattr(w_obj, space.wrap('__class__'))
         w_cls_reduce_meth = space.getattr(w_cls, w_st_reduce)
-        w_cls_reduce = space.getattr(w_cls_reduce_meth, space.wrap('im_func'))
+        try:
+            w_cls_reduce = space.getattr(w_cls_reduce_meth, space.wrap('im_func'))
+        except OperationError as e:
+            # i.e. PyCFunction from cpyext
+            if not e.match(space, space.w_AttributeError):
+                raise
+            w_cls_reduce = space.w_None
         w_objtype = space.w_object
         w_obj_dict = space.getattr(w_objtype, space.wrap('__dict__'))
         w_obj_reduce = space.getitem(w_obj_dict, w_st_reduce)


More information about the pypy-commit mailing list