gh-136914: Use inspect.isroutine() in DocTest's lineno computation by dlax · Pull Request #136930 · python/cpython · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Use inspect.isroutine() in DocTest's lineno computation
Previously, DocTest's lineno of `functools.cache()`-decorated functions
was not properly returned (None was returned) because the underlying
computation, in `DocTest._find_lineno()`, 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, thus fixing lineno computation for
functools.cache()-decorated functions.
  • Loading branch information
dlax committed Jul 21, 2025
commit ddf3ab12f3e733fcd4e38c80c71389fdff2f4266
2 changes: 1 addition & 1 deletion Lib/doctest.py
18 changes: 18 additions & 0 deletions Lib/test/test_doctest/doctest_lineno.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,21 @@ 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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'd suggest using a custom class decorator here instead of functools.cache. We don't want this to depend on the implementation details of functools.cache, which could change in the future.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think that this may add unnecessary complexity to the tests. And such test will not guarantee that the code works also for functools.cached, which is a comon case. Other tests just test common cases.

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
2 changes: 2 additions & 0 deletions Lib/test/test_doctest/test_doctest.py
Original file line number Diff line number Diff line change
Expand Up @@ -687,6 +687,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
Expand Down