[pypy-commit] pypy default: Issue #2464: give an __objclass__ to the __dict__ and __weakref__

arigo pypy.commits at gmail.com
Wed Jan 11 11:53:44 EST 2017


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r89495:308258847565
Date: 2017-01-11 16:26 +0100
http://bitbucket.org/pypy/pypy/changeset/308258847565/

Log:	Issue #2464: give an __objclass__ to the __dict__ and __weakref__
	descriptors that are added to user-defined classes

diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py
--- a/pypy/interpreter/typedef.py
+++ b/pypy/interpreter/typedef.py
@@ -221,10 +221,6 @@
     exec source.compile() in miniglobals
     return miniglobals['descr_typecheck_%s' % func.__name__]
 
-def unknown_objclass_getter(space):
-    # NB. this is an AttributeError to make inspect.py happy
-    raise oefmt(space.w_AttributeError, "generic property has no __objclass__")
-
 @specialize.arg(0)
 def make_objclass_getter(tag, func, cls):
     if func and hasattr(func, 'im_func'):
@@ -235,7 +231,7 @@
 @specialize.memo()
 def _make_objclass_getter(cls):
     if not cls:
-        return unknown_objclass_getter, cls
+        return None, cls
     miniglobals = {}
     if isinstance(cls, str):
         assert cls.startswith('<'), "pythontype typecheck should begin with <"
@@ -257,7 +253,7 @@
 
     @specialize.arg(7)
     def __init__(self, fget, fset=None, fdel=None, doc=None,
-                 cls=None, use_closure=False, tag=None):
+                 cls=None, use_closure=False, tag=None, w_type=None):
         objclass_getter, cls = make_objclass_getter(tag, fget, cls)
         fget = make_descr_typecheck_wrapper((tag, 0), fget,
                                             cls=cls, use_closure=use_closure)
@@ -272,6 +268,7 @@
         self.reqcls = cls
         self.name = '<generic property>'
         self.objclass_getter = objclass_getter
+        self.w_type = w_type
         self.use_closure = use_closure
 
     @unwrap_spec(w_cls = WrappedDefault(None))
@@ -322,7 +319,14 @@
                                                space.wrap(self.name)]))
 
     def descr_get_objclass(space, property):
-        return property.objclass_getter(space)
+        if property.w_type is not None:
+            return property.w_type
+        if property.objclass_getter is not None:
+            return property.objclass_getter(space)
+        # NB. this is an AttributeError to make inspect.py happy
+        raise oefmt(space.w_AttributeError,
+                    "generic property has no __objclass__")
+
 
 def interp_attrproperty(name, cls, doc=None):
     "NOT_RPYTHON: initialization-time only"
@@ -466,9 +470,13 @@
         return space.w_None
     return lifeline.get_any_weakref(space)
 
-dict_descr = GetSetProperty(descr_get_dict, descr_set_dict, descr_del_dict,
-                            doc="dictionary for instance variables (if defined)")
-dict_descr.name = '__dict__'
+def make_dict_descr_for_type(w_type):
+    descr = GetSetProperty(descr_get_dict, descr_set_dict, descr_del_dict,
+                           w_type=w_type,
+                           doc="dictionary for instance variables")
+    descr.name = '__dict__'
+    return descr
+dict_descr = make_dict_descr_for_type(None)
 
 
 def generic_ne(space, w_obj1, w_obj2):
@@ -498,9 +506,12 @@
     w_docstring = code.getdocstring(space)
     return space.newtuple([w_docstring])
 
-weakref_descr = GetSetProperty(descr_get_weakref,
-                    doc="list of weak references to the object (if defined)")
-weakref_descr.name = '__weakref__'
+def make_weakref_descr_for_type(w_type):
+    descr = GetSetProperty(descr_get_weakref, w_type=w_type,
+                           doc="list of weak references to the object")
+    descr.name = '__weakref__'
+    return descr
+weakref_descr = make_weakref_descr_for_type(None)
 
 def make_weakref_descr(cls):
     """Make instances of the W_Root subclass 'cls' weakrefable.
diff --git a/pypy/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py
--- a/pypy/objspace/std/typeobject.py
+++ b/pypy/objspace/std/typeobject.py
@@ -4,7 +4,8 @@
 from pypy.interpreter.error import OperationError, oefmt
 from pypy.interpreter.function import Function, StaticMethod
 from pypy.interpreter.typedef import (
-    weakref_descr, GetSetProperty, dict_descr, Member, TypeDef)
+    make_weakref_descr_for_type, GetSetProperty, weakref_descr,
+    make_dict_descr_for_type, Member, TypeDef)
 from pypy.interpreter.astcompiler.misc import mangle
 from pypy.module.__builtin__ import abstractinst
 
@@ -1117,12 +1118,14 @@
 
 def create_dict_slot(w_self):
     if not w_self.hasdict:
+        dict_descr = make_dict_descr_for_type(w_self)
         w_self.dict_w.setdefault('__dict__',
                                  w_self.space.wrap(dict_descr))
         w_self.hasdict = True
 
 def create_weakref_slot(w_self):
     if not w_self.weakrefable:
+        weakref_descr = make_weakref_descr_for_type(w_self)
         w_self.dict_w.setdefault('__weakref__',
                                  w_self.space.wrap(weakref_descr))
         w_self.weakrefable = True


More information about the pypy-commit mailing list