From 23b7a95f41674fa949e1b415f82e4b8858db47ae Mon Sep 17 00:00:00 2001 From: "Miss Islington (bot)" <31488909+miss-islington@users.noreply.github.com> Date: Sun, 10 Aug 2025 22:05:28 +0200 Subject: [PATCH] [3.13] gh-136914: Fix support of cached functions and properties in DocTest's lineno computation (GH-136930) (GH-137615) 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(). (cherry picked from commit fece15d29f28e89f1231afa80508c80ed28dc37d) Co-authored-by: Denis Laxalde --- Lib/doctest.py | 5 +++- Lib/test/test_doctest/doctest_lineno.py | 29 +++++++++++++++++++ Lib/test/test_doctest/test_doctest.py | 4 +++ ...-07-21-15-40-00.gh-issue-136914.-GNG-d.rst | 2 ++ 4 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2025-07-21-15-40-00.gh-issue-136914.-GNG-d.rst diff --git a/Lib/doctest.py b/Lib/doctest.py index 05ed6835c1df..ecac54ad5a5d 100644 --- a/Lib/doctest.py +++ b/Lib/doctest.py @@ -94,6 +94,7 @@ __all__ = [ import __future__ import difflib +import functools import inspect import linecache import os @@ -1140,7 +1141,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: diff --git a/Lib/test/test_doctest/doctest_lineno.py b/Lib/test/test_doctest/doctest_lineno.py index 0dbcd9a11eab..0bd402e98288 100644 --- a/Lib/test/test_doctest/doctest_lineno.py +++ b/Lib/test/test_doctest/doctest_lineno.py @@ -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 diff --git a/Lib/test/test_doctest/test_doctest.py b/Lib/test/test_doctest/test_doctest.py index 46e90f98d478..2a1ffe887609 100644 --- a/Lib/test/test_doctest/test_doctest.py +++ b/Lib/test/test_doctest/test_doctest.py @@ -680,6 +680,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 @@ -689,6 +691,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 diff --git a/Misc/NEWS.d/next/Library/2025-07-21-15-40-00.gh-issue-136914.-GNG-d.rst b/Misc/NEWS.d/next/Library/2025-07-21-15-40-00.gh-issue-136914.-GNG-d.rst new file mode 100644 index 000000000000..78ec8025fbc0 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-07-21-15-40-00.gh-issue-136914.-GNG-d.rst @@ -0,0 +1,2 @@ +Fix retrieval of :attr:`doctest.DocTest.lineno` for objects decorated with +:func:`functools.cache` or :class:`functools.cached_property`. -- 2.47.2