mirror of https://github.com/python/cpython
GH-95822: Need _PyType_Lookup() in descriptor howto code equivalent. (GH-95967)
This commit is contained in:
parent
b6d88b7225
commit
6740680b57
|
@ -582,11 +582,18 @@ a pure Python equivalent:
|
||||||
|
|
||||||
.. testcode::
|
.. testcode::
|
||||||
|
|
||||||
|
def find_name_in_mro(cls, name, default):
|
||||||
|
"Emulate _PyType_Lookup() in Objects/typeobject.c"
|
||||||
|
for base in cls.__mro__:
|
||||||
|
if name in vars(base):
|
||||||
|
return vars(base)[name]
|
||||||
|
return default
|
||||||
|
|
||||||
def object_getattribute(obj, name):
|
def object_getattribute(obj, name):
|
||||||
"Emulate PyObject_GenericGetAttr() in Objects/object.c"
|
"Emulate PyObject_GenericGetAttr() in Objects/object.c"
|
||||||
null = object()
|
null = object()
|
||||||
objtype = type(obj)
|
objtype = type(obj)
|
||||||
cls_var = getattr(objtype, name, null)
|
cls_var = find_name_in_mro(objtype, name, null)
|
||||||
descr_get = getattr(type(cls_var), '__get__', null)
|
descr_get = getattr(type(cls_var), '__get__', null)
|
||||||
if descr_get is not null:
|
if descr_get is not null:
|
||||||
if (hasattr(type(cls_var), '__set__')
|
if (hasattr(type(cls_var), '__set__')
|
||||||
|
@ -663,6 +670,15 @@ a pure Python equivalent:
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
return ('getattr_hook', self, name)
|
return ('getattr_hook', self, name)
|
||||||
|
|
||||||
|
class D1:
|
||||||
|
def __get__(self, obj, objtype=None):
|
||||||
|
return type(self), obj, objtype
|
||||||
|
|
||||||
|
class U1:
|
||||||
|
x = D1()
|
||||||
|
|
||||||
|
class U2(U1):
|
||||||
|
pass
|
||||||
|
|
||||||
.. doctest::
|
.. doctest::
|
||||||
:hide:
|
:hide:
|
||||||
|
@ -696,6 +712,10 @@ a pure Python equivalent:
|
||||||
>>> b.g == b['g'] == ('getattr_hook', b, 'g')
|
>>> b.g == b['g'] == ('getattr_hook', b, 'g')
|
||||||
True
|
True
|
||||||
|
|
||||||
|
>>> u2 = U2()
|
||||||
|
>>> object_getattribute(u2, 'x') == u2.x == (D1, u2, U2)
|
||||||
|
True
|
||||||
|
|
||||||
Note, there is no :meth:`__getattr__` hook in the :meth:`__getattribute__`
|
Note, there is no :meth:`__getattr__` hook in the :meth:`__getattribute__`
|
||||||
code. That is why calling :meth:`__getattribute__` directly or with
|
code. That is why calling :meth:`__getattribute__` directly or with
|
||||||
``super().__getattribute__`` will bypass :meth:`__getattr__` entirely.
|
``super().__getattribute__`` will bypass :meth:`__getattr__` entirely.
|
||||||
|
|
Loading…
Reference in New Issue