[Python-checkins] GH-95822: Need _PyType_Lookup() in descriptor howto code equivalent. (GH-95967)

rhettinger webhook-mailer at python.org
Fri Aug 19 00:57:12 EDT 2022


https://github.com/python/cpython/commit/6740680b575249e498e3ca2b55d262baf9db6521
commit: 6740680b575249e498e3ca2b55d262baf9db6521
branch: main
author: Raymond Hettinger <rhettinger at users.noreply.github.com>
committer: rhettinger <rhettinger at users.noreply.github.com>
date: 2022-08-18T23:56:58-05:00
summary:

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

files:
M Doc/howto/descriptor.rst

diff --git a/Doc/howto/descriptor.rst b/Doc/howto/descriptor.rst
index 5e9b110f0fe2..91a6c31c33b8 100644
--- a/Doc/howto/descriptor.rst
+++ b/Doc/howto/descriptor.rst
@@ -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.



More information about the Python-checkins mailing list