[pypy-commit] pypy py3.5: add variable_sized property to TypeDef (similar to the tp_itemsize property in cpython), use it to filter types from pickle properly (partly reverts the last commit)

plan_rich pypy.commits at gmail.com
Tue Feb 21 09:40:57 EST 2017


Author: Richard Plangger <planrichi at gmail.com>
Branch: py3.5
Changeset: r90270:3a002d0cdb81
Date: 2017-02-21 15:39 +0100
http://bitbucket.org/pypy/pypy/changeset/3a002d0cdb81/

Log:	add variable_sized property to TypeDef (similar to the tp_itemsize
	property in cpython), use it to filter types from pickle properly
	(partly reverts the last commit)

diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py
--- a/pypy/interpreter/typedef.py
+++ b/pypy/interpreter/typedef.py
@@ -14,7 +14,8 @@
 
 class TypeDef(object):
     def __init__(self, __name, __base=None, __total_ordering__=None,
-                 __buffer=None, __confirm_applevel_del__=False, **rawdict):
+                 __buffer=None, __confirm_applevel_del__=False,
+                 variable_sized=False, **rawdict):
         "NOT_RPYTHON: initialization-time only"
         self.name = __name
         if __base is None:
@@ -44,6 +45,7 @@
         assert __total_ordering__ in (None, 'auto'), "Unknown value for __total_ordering"
         if __total_ordering__ == 'auto':
             self.auto_total_ordering()
+        self.variable_sized = variable_sized
 
     def add_entries(self, **rawdict):
         # xxx fix the names of the methods to match what app-level expects
diff --git a/pypy/objspace/std/memoryobject.py b/pypy/objspace/std/memoryobject.py
--- a/pypy/objspace/std/memoryobject.py
+++ b/pypy/objspace/std/memoryobject.py
@@ -689,9 +689,6 @@
             bytes = self.as_str()
             return _array_to_hexstring(space, StringBuffer(bytes), 0, 1, len(bytes))
 
-    def descr___getstate__(self, space):
-        raise oefmt(space.w_TypeError, "cannot pickle memoryview objects")
-
 def is_byte_format(char):
     return char == 'b' or char == 'B' or char == 'c'
 
@@ -699,7 +696,7 @@
     return flags & (MEMORYVIEW_SCALAR|MEMORYVIEW_C)
 
 W_MemoryView.typedef = TypeDef(
-    "memoryview", None, None, "read-write",
+    "memoryview", None, None, "read-write", variable_sized=True,
     __doc__ = """\
 Create a new memoryview object which references the given object.
 """,
@@ -714,7 +711,6 @@
     __enter__   = interp2app(W_MemoryView.descr_enter),
     __exit__    = interp2app(W_MemoryView.descr_exit),
     __weakref__ = make_weakref_descr(W_MemoryView),
-    __getstate__= interp2app(W_MemoryView.descr___getstate__),
     cast        = interp2app(W_MemoryView.descr_cast),
     hex         = interp2app(W_MemoryView.descr_hex),
     tobytes     = interp2app(W_MemoryView.descr_tobytes),
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
@@ -24,9 +24,8 @@
     try:
         getstate = obj.__getstate__
     except AttributeError:
-        # TODO restrict pickling of variable sized objects
-        # tp_itemsize != 0, for now e.g. memoryview is handled
-        # by raising a TypeError in __getstate__
+        # and raises a TypeError if the condition holds true, this is done
+        # just before reduce_2 is called in pypy
         state = getattr(obj, "__dict__", None)
         names = slotnames(cls) # not checking for list
         if names is not None:
@@ -176,6 +175,7 @@
     w_proto = space.newint(proto)
     if proto >= 2:
         w_descr = space.lookup(w_obj, '__getnewargs_ex__')
+        hasargs = True
         if w_descr is not None:
             w_result = space.get_and_call_function(w_descr, w_obj)
             w_args, w_kwargs = space.fixedview(w_result, 2)
@@ -184,8 +184,17 @@
             if w_descr is not None:
                 w_args = space.get_and_call_function(w_descr, w_obj)
             else:
+                hasargs = False
                 w_args = space.newtuple([])
             w_kwargs = space.w_None
+        w_getstate = space.lookup(w_obj, '__get_state__')
+        if w_getstate is None:
+            required = not hasargs and \
+                       not space.isinstance_w(w_obj, space.w_list) and \
+                       not space.isinstance_w(w_obj, space.w_dict)
+            w_obj_type = space.type(w_obj)
+            if required and w_obj_type.layout.typedef.variable_sized:
+                raise oefmt(space.w_TypeError, "cannot pickle %N objects", w_obj_type)
         return reduce_2(space, w_obj, w_proto, w_args, w_kwargs)
     return reduce_1(space, w_obj, w_proto)
 


More information about the pypy-commit mailing list