diff options
author | Raymond Hettinger <rhettinger@users.noreply.github.com> | 2022-08-19 04:56:58 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-08-19 04:56:58 (GMT) |
commit | 6740680b575249e498e3ca2b55d262baf9db6521 (patch) | |
tree | f4ff91101d6d91188336a43ce8b7299964c85071 | |
parent | b6d88b7225c36821845d4ba1312a6d6b2f7f65c8 (diff) | |
download | cpython-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.rst | 22 |
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. |