Skip to content

Commit

Permalink
GH-95822: Need _PyType_Lookup() in descriptor howto code equivalent. (G…
Browse files Browse the repository at this point in the history
  • Loading branch information
miss-islington authored Aug 19, 2022
1 parent eb182fe commit b6e8304
Showing 1 changed file with 21 additions and 1 deletion.
22 changes: 21 additions & 1 deletion Doc/howto/descriptor.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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__')
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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.
Expand Down

0 comments on commit b6e8304

Please sign in to comment.