[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