mirror of
https://github.com/python/cpython.git
synced 2025-10-09 16:34:44 +00:00
Close #18929: inspect.classify_class_attrs will now search the metaclasses (last) to find where an attr was defined.
This commit is contained in:
parent
2131a4a2fc
commit
668dede7e9
2 changed files with 9 additions and 3 deletions
|
@ -173,8 +173,9 @@ attributes:
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
:func:`getmembers` does not return metaclass attributes when the argument
|
:func:`getmembers` will only return metaclass attributes when the
|
||||||
is a class (this behavior is inherited from the :func:`dir` function).
|
argument is a class and those attributes have been listed in a custom
|
||||||
|
:meth:`__dir__`.
|
||||||
|
|
||||||
|
|
||||||
.. function:: getmoduleinfo(path)
|
.. function:: getmoduleinfo(path)
|
||||||
|
|
|
@ -308,9 +308,14 @@ def classify_class_attrs(cls):
|
||||||
data attributes: C.data is just a data object, but
|
data attributes: C.data is just a data object, but
|
||||||
C.__dict__['data'] may be a data descriptor with additional
|
C.__dict__['data'] may be a data descriptor with additional
|
||||||
info, like a __doc__ string.
|
info, like a __doc__ string.
|
||||||
|
|
||||||
|
If one of the items in dir(cls) is stored in the metaclass it will now
|
||||||
|
be discovered and not have None be listed as the class in which it was
|
||||||
|
defined.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
mro = getmro(cls)
|
mro = getmro(cls)
|
||||||
|
metamro = getmro(type(cls)) # for attributes stored in the metaclass
|
||||||
names = dir(cls)
|
names = dir(cls)
|
||||||
result = []
|
result = []
|
||||||
for name in names:
|
for name in names:
|
||||||
|
@ -321,7 +326,7 @@ def classify_class_attrs(cls):
|
||||||
# getattr(). This is the case with some descriptors (bug #1785).
|
# getattr(). This is the case with some descriptors (bug #1785).
|
||||||
# Thus, we only use getattr() as a last resort.
|
# Thus, we only use getattr() as a last resort.
|
||||||
homecls = None
|
homecls = None
|
||||||
for base in (cls,) + mro:
|
for base in (cls,) + mro + metamro:
|
||||||
if name in base.__dict__:
|
if name in base.__dict__:
|
||||||
obj = base.__dict__[name]
|
obj = base.__dict__[name]
|
||||||
homecls = base
|
homecls = base
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue