summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaymond Hettinger <rhettinger@users.noreply.github.com>2022-08-19 04:56:58 (GMT)
committerGitHub <noreply@github.com>2022-08-19 04:56:58 (GMT)
commit6740680b575249e498e3ca2b55d262baf9db6521 (patch)
treef4ff91101d6d91188336a43ce8b7299964c85071
parentb6d88b7225c36821845d4ba1312a6d6b2f7f65c8 (diff)
downloadcpython-6740680b575249e498e3ca2b55d262baf9db6521.zip
cpython-6740680b575249e498e3ca2b55d262baf9db6521.tar.gz
cpython-6740680b575249e498e3ca2b55d262baf9db6521.tar.bz2
GH-95822: Need _PyType_Lookup() in descriptor howto code equivalent. (GH-95967)
-rw-r--r--Doc/howto/descriptor.rst22
1 files changed, 21 insertions, 1 deletions
diff --git a/Doc/howto/descriptor.rst b/Doc/howto/descriptor.rst
index 5e9b110..91a6c31 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.