gh-136914: Fix support of cached functions and properties in DocTest's lineno computation (GH-136930)
Some checks are pending
Tests / Sanitizers (push) Blocked by required conditions
Tests / Windows MSI (push) Blocked by required conditions
Tests / Change detection (push) Waiting to run
Tests / Docs (push) Blocked by required conditions
Tests / Check if Autoconf files are up to date (push) Blocked by required conditions
Tests / Check if generated files are up to date (push) Blocked by required conditions
Tests / (push) Blocked by required conditions
Tests / Ubuntu SSL tests with OpenSSL (push) Blocked by required conditions
Tests / Ubuntu SSL tests with AWS-LC (push) Blocked by required conditions
Tests / WASI (push) Blocked by required conditions
Tests / Hypothesis tests on Ubuntu (push) Blocked by required conditions
Tests / Address sanitizer (push) Blocked by required conditions
Tests / Cross build Linux (push) Blocked by required conditions
Tests / CIFuzz (push) Blocked by required conditions
Tests / All required checks pass (push) Blocked by required conditions
Lint / lint (push) Waiting to run
mypy / Run mypy on Lib/_pyrepl (push) Waiting to run
mypy / Run mypy on Lib/test/libregrtest (push) Waiting to run
mypy / Run mypy on Lib/tomllib (push) Waiting to run
mypy / Run mypy on Tools/build (push) Waiting to run
mypy / Run mypy on Tools/cases_generator (push) Waiting to run
mypy / Run mypy on Tools/clinic (push) Waiting to run
mypy / Run mypy on Tools/jit (push) Waiting to run
mypy / Run mypy on Tools/peg_generator (push) Waiting to run

Previously, DocTest's lineno of functions and methods decorated with
functools.cache(), functools.lru_cache() and functools.cached_property()
was not properly returned (None was returned) because the
computation relied on inspect.isfunction() which does not consider the
decorated result as a function.

We now use the more generic inspect.isroutine(), as elsewhere
in doctest's logic.

Also, added a special case for functools.cached_property().
This commit is contained in:
Denis Laxalde 2025-07-25 11:46:12 +02:00 committed by GitHub
parent d5e75c0768
commit fece15d29f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 39 additions and 1 deletions

View file

@ -94,6 +94,7 @@ __all__ = [
import __future__
import difflib
import functools
import inspect
import linecache
import os
@ -1141,7 +1142,9 @@ class DocTestFinder:
if inspect.ismethod(obj): obj = obj.__func__
if isinstance(obj, property):
obj = obj.fget
if inspect.isfunction(obj) and getattr(obj, '__doc__', None):
if isinstance(obj, functools.cached_property):
obj = obj.func
if inspect.isroutine(obj) and getattr(obj, '__doc__', None):
# We don't use `docstring` var here, because `obj` can be changed.
obj = inspect.unwrap(obj)
try:

View file

@ -76,3 +76,32 @@ from test.test_doctest.decorator_mod import decorator
@decorator
def func_with_docstring_wrapped():
"""Some unrelated info."""
# https://github.com/python/cpython/issues/136914
import functools
@functools.cache
def cached_func_with_doctest(value):
"""
>>> cached_func_with_doctest(1)
-1
"""
return -value
@functools.cache
def cached_func_without_docstring(value):
return value + 1
class ClassWithACachedProperty:
@functools.cached_property
def cached(self):
"""
>>> X().cached
-1
"""
return 0

View file

@ -678,6 +678,8 @@ It used to be broken for quite some time until `bpo-28249`.
>>> for t in tests:
... print('%5s %s' % (t.lineno, t.name))
None test.test_doctest.doctest_lineno
None test.test_doctest.doctest_lineno.ClassWithACachedProperty
102 test.test_doctest.doctest_lineno.ClassWithACachedProperty.cached
22 test.test_doctest.doctest_lineno.ClassWithDocstring
30 test.test_doctest.doctest_lineno.ClassWithDoctest
None test.test_doctest.doctest_lineno.ClassWithoutDocstring
@ -687,6 +689,8 @@ It used to be broken for quite some time until `bpo-28249`.
45 test.test_doctest.doctest_lineno.MethodWrapper.method_with_doctest
None test.test_doctest.doctest_lineno.MethodWrapper.method_without_docstring
61 test.test_doctest.doctest_lineno.MethodWrapper.property_with_doctest
86 test.test_doctest.doctest_lineno.cached_func_with_doctest
None test.test_doctest.doctest_lineno.cached_func_without_docstring
4 test.test_doctest.doctest_lineno.func_with_docstring
77 test.test_doctest.doctest_lineno.func_with_docstring_wrapped
12 test.test_doctest.doctest_lineno.func_with_doctest

View file

@ -0,0 +1,2 @@
Fix retrieval of :attr:`doctest.DocTest.lineno` for objects decorated with
:func:`functools.cache` or :class:`functools.cached_property`.