https://github.com/python/cpython/commit/fece15d29f28e89f1231afa80508c80ed28dc37d
commit: fece15d29f28e89f1231afa80508c80ed28dc37d
branch: main
author: Denis Laxalde <de...@laxalde.org>
committer: serhiy-storchaka <storch...@gmail.com>
date: 2025-07-25T12:46:12+03:00
summary:

gh-136914: Fix support of cached functions and properties in DocTest's lineno 
computation (GH-136930)

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().

files:
A Misc/NEWS.d/next/Library/2025-07-21-15-40-00.gh-issue-136914.-GNG-d.rst
M Lib/doctest.py
M Lib/test/test_doctest/doctest_lineno.py
M Lib/test/test_doctest/test_doctest.py

diff --git a/Lib/doctest.py b/Lib/doctest.py
index e77823f64b67e4..92a2ab4f7e66f8 100644
--- a/Lib/doctest.py
+++ b/Lib/doctest.py
@@ -94,6 +94,7 @@ def _test():
 
 import __future__
 import difflib
+import functools
 import inspect
 import linecache
 import os
@@ -1141,7 +1142,9 @@ def _find_lineno(self, obj, source_lines):
         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 0dbcd9a11eaba2..0bd402e98288d0 100644
--- a/Lib/test/test_doctest/doctest_lineno.py
+++ b/Lib/test/test_doctest/doctest_lineno.py
@@ -76,3 +76,32 @@ def property_with_doctest(self):
 @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 72763d4a0132d0..0fa74407e3c436 100644
--- a/Lib/test/test_doctest/test_doctest.py
+++ b/Lib/test/test_doctest/test_doctest.py
@@ -678,6 +678,8 @@ def basics(): r"""
     >>> 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 @@ def basics(): r"""
        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 00000000000000..78ec8025fbc0fd
--- /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`.

_______________________________________________
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: arch...@mail-archive.com

Reply via email to