Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-122102: Fix/improve docs of descriptor-related tools in inspect #122104

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
39 changes: 25 additions & 14 deletions Doc/library/inspect.rst
Original file line number Diff line number Diff line change
Expand Up @@ -555,19 +555,18 @@ attributes (see :ref:`import-mod-attrs` for module attributes):
.. function:: ismethoddescriptor(object)

Return ``True`` if the object is a method descriptor, but not if
:func:`ismethod`, :func:`isclass`, :func:`isfunction` or :func:`isbuiltin`
are true.
:func:`isclass`, :func:`ismethod` or :func:`isfunction` are true.

This, for example, is true of ``int.__add__``. An object passing this test
has a :meth:`~object.__get__` method, but not a :meth:`~object.__set__`
method or a :meth:`~object.__delete__` method. Beyond that, the set of
attributes varies. A :attr:`~definition.__name__` attribute is usually
sensible, and :attr:`~definition.__doc__` often is.

Methods implemented via descriptors that also pass one of the other tests
return ``False`` from the :func:`ismethoddescriptor` test, simply because the
other tests promise more -- you can, e.g., count on having the
:attr:`~method.__func__` attribute (etc) when an object passes
Method descriptors that also pass any of the other tests (:func:`isclass`,
:func:`ismethod` or :func:`isfunction`) make this function return ``False``,
simply because those other tests promise more -- you can, e.g., count on
having the :attr:`~method.__func__` attribute when an object passes
:func:`ismethod`.

.. versionchanged:: 3.13
Expand All @@ -578,16 +577,28 @@ attributes (see :ref:`import-mod-attrs` for module attributes):

.. function:: isdatadescriptor(object)

Return ``True`` if the object is a data descriptor.
Return ``True`` if the object is a data descriptor, but not if
:func:`isclass`, :func:`ismethod` or :func:`isfunction` are true.

Data descriptors have a :attr:`~object.__set__` or a :attr:`~object.__delete__` method.
Examples are properties (defined in Python), getsets, and members. The
latter two are defined in C and there are more specific tests available for
those types, which is robust across Python implementations. Typically, data
descriptors will also have :attr:`~definition.__name__` and :attr:`!__doc__` attributes
(properties, getsets, and members have both of these attributes), but this is
not guaranteed.
Data descriptors always have a :meth:`~object.__set__` method and/or
a :meth:`~object.__delete__` method. Optionally, they may also have a
:meth:`~object.__get__` method.

Examples of data descriptors are :func:`properties <property>`, getsets and
member descriptors. Note that for the latter two (defined only in C extension
modules) more specific tests are available: :func:`isgetsetdescriptor` and
:func:`ismemberdescriptor`, respectively.

While data descriptors may have also :attr:`~definition.__name__` and
:attr:`!__doc__` attributes (as properties, getsets and member descriptors
do), this is not necessarily the case in general.

.. versionchanged:: 3.8
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was it really fixed since 3.8?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, with the PR gh-1959.

This function now reports objects with only a :meth:`~object.__set__` method
as being data descriptors (the presence of :meth:`~object.__get__` is no
longer required for that). Moreover, objects with :meth:`~object.__delete__`,
but not :meth:`~object.__set__`, are now properly recognized as data
descriptors as well, which was not the case previously.

.. function:: isgetsetdescriptor(object)

Expand Down
14 changes: 10 additions & 4 deletions Lib/inspect.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,9 +205,10 @@ def ismethoddescriptor(object):
often is.

Methods implemented via descriptors that also pass one of the other
tests return false from the ismethoddescriptor() test, simply because
the other tests promise more -- you can, e.g., count on having the
__func__ attribute (etc) when an object passes ismethod()."""
tests (ismethod(), isclass(), isfunction()) make this function return
false, simply because those other tests promise more -- you can, e.g.,
count on having the __func__ attribute when an object passes
ismethod()."""
if isclass(object) or ismethod(object) or isfunction(object):
# mutual exclusion
return False
Expand All @@ -219,8 +220,13 @@ def ismethoddescriptor(object):
def isdatadescriptor(object):
"""Return true if the object is a data descriptor.

But not if ismethod() or isclass() or isfunction() are true.

Data descriptors have a __set__ or a __delete__ attribute. Examples are
properties (defined in Python) and getsets and members (defined in C).
properties, getsets, and members. For the latter two (defined only in C
extension modules) more specific tests are available as well:
isgetsetdescriptor() and ismemberdescriptor(), respectively.

Typically, data descriptors will also have __name__ and __doc__ attributes
(properties, getsets, and members have both of these attributes), but this
is not guaranteed."""
Expand Down
Loading