Skip to content

Commit fece15d

Browse files
authored
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().
1 parent d5e75c0 commit fece15d

File tree

4 files changed

+39
-1
lines changed

4 files changed

+39
-1
lines changed

Lib/doctest.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ def _test():
9494

9595
import __future__
9696
import difflib
97+
import functools
9798
import inspect
9899
import linecache
99100
import os
@@ -1141,7 +1142,9 @@ def _find_lineno(self, obj, source_lines):
11411142
if inspect.ismethod(obj): obj = obj.__func__
11421143
if isinstance(obj, property):
11431144
obj = obj.fget
1144-
if inspect.isfunction(obj) and getattr(obj, '__doc__', None):
1145+
if isinstance(obj, functools.cached_property):
1146+
obj = obj.func
1147+
if inspect.isroutine(obj) and getattr(obj, '__doc__', None):
11451148
# We don't use `docstring` var here, because `obj` can be changed.
11461149
obj = inspect.unwrap(obj)
11471150
try:

Lib/test/test_doctest/doctest_lineno.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,32 @@ def property_with_doctest(self):
7676
@decorator
7777
def func_with_docstring_wrapped():
7878
"""Some unrelated info."""
79+
80+
81+
# https://github.com/python/cpython/issues/136914
82+
import functools
83+
84+
85+
@functools.cache
86+
def cached_func_with_doctest(value):
87+
"""
88+
>>> cached_func_with_doctest(1)
89+
-1
90+
"""
91+
return -value
92+
93+
94+
@functools.cache
95+
def cached_func_without_docstring(value):
96+
return value + 1
97+
98+
99+
class ClassWithACachedProperty:
100+
101+
@functools.cached_property
102+
def cached(self):
103+
"""
104+
>>> X().cached
105+
-1
106+
"""
107+
return 0

Lib/test/test_doctest/test_doctest.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -678,6 +678,8 @@ def basics(): r"""
678678
>>> for t in tests:
679679
... print('%5s %s' % (t.lineno, t.name))
680680
None test.test_doctest.doctest_lineno
681+
None test.test_doctest.doctest_lineno.ClassWithACachedProperty
682+
102 test.test_doctest.doctest_lineno.ClassWithACachedProperty.cached
681683
22 test.test_doctest.doctest_lineno.ClassWithDocstring
682684
30 test.test_doctest.doctest_lineno.ClassWithDoctest
683685
None test.test_doctest.doctest_lineno.ClassWithoutDocstring
@@ -687,6 +689,8 @@ def basics(): r"""
687689
45 test.test_doctest.doctest_lineno.MethodWrapper.method_with_doctest
688690
None test.test_doctest.doctest_lineno.MethodWrapper.method_without_docstring
689691
61 test.test_doctest.doctest_lineno.MethodWrapper.property_with_doctest
692+
86 test.test_doctest.doctest_lineno.cached_func_with_doctest
693+
None test.test_doctest.doctest_lineno.cached_func_without_docstring
690694
4 test.test_doctest.doctest_lineno.func_with_docstring
691695
77 test.test_doctest.doctest_lineno.func_with_docstring_wrapped
692696
12 test.test_doctest.doctest_lineno.func_with_doctest
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix retrieval of :attr:`doctest.DocTest.lineno` for objects decorated with
2+
:func:`functools.cache` or :class:`functools.cached_property`.

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy