GH-95822: Need _PyType_Lookup() in descriptor howto code equivalent. (GH-95967)

This commit is contained in:
Raymond Hettinger 2022-08-18 23:56:58 -05:00 committed by GitHub
parent b6d88b7225
commit 6740680b57
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 21 additions and 1 deletions

View File

@ -582,11 +582,18 @@ a pure Python equivalent:
.. 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):
"Emulate PyObject_GenericGetAttr() in Objects/object.c"
null = object()
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)
if descr_get is not null:
if (hasattr(type(cls_var), '__set__')
@ -663,6 +670,15 @@ a pure Python equivalent:
def __getattr__(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::
:hide:
@ -696,6 +712,10 @@ a pure Python equivalent:
>>> b.g == b['g'] == ('getattr_hook', b, 'g')
True
>>> u2 = U2()
>>> object_getattribute(u2, 'x') == u2.x == (D1, u2, U2)
True
Note, there is no :meth:`__getattr__` hook in the :meth:`__getattribute__`
code. That is why calling :meth:`__getattribute__` directly or with
``super().__getattribute__`` will bypass :meth:`__getattr__` entirely.