From d9c846317636b6c49b507c87bc0f0a2fae1b3957 Mon Sep 17 00:00:00 2001 From: Brian Schubert Date: Tue, 13 Feb 2024 18:43:55 -0500 Subject: [PATCH 1/3] Fix doctest reporting incorrect line numbers for decorated functions --- Lib/doctest.py | 2 ++ Lib/test/test_doctest/_support.py | 10 ++++++++++ Lib/test/test_doctest/doctest_lineno.py | 9 +++++++++ Lib/test/test_doctest/test_doctest.py | 1 + .../2024-02-13-18-27-03.gh-issue-115392.gle5tp.rst | 2 ++ 5 files changed, 24 insertions(+) create mode 100644 Lib/test/test_doctest/_support.py create mode 100644 Misc/NEWS.d/next/Library/2024-02-13-18-27-03.gh-issue-115392.gle5tp.rst diff --git a/Lib/doctest.py b/Lib/doctest.py index 114aac62a34e95..c403245af5d4e2 100644 --- a/Lib/doctest.py +++ b/Lib/doctest.py @@ -1140,6 +1140,8 @@ def _find_lineno(self, obj, source_lines): obj = obj.fget if inspect.isfunction(obj) and getattr(obj, '__doc__', None): # We don't use `docstring` var here, because `obj` can be changed. + while hasattr(obj, "__wrapped__"): + obj = obj.__wrapped__ obj = obj.__code__ if inspect.istraceback(obj): obj = obj.tb_frame if inspect.isframe(obj): obj = obj.f_code diff --git a/Lib/test/test_doctest/_support.py b/Lib/test/test_doctest/_support.py new file mode 100644 index 00000000000000..9f106888411202 --- /dev/null +++ b/Lib/test/test_doctest/_support.py @@ -0,0 +1,10 @@ +# This module is used in `doctest_lineno.py`. +import functools + + +def decorator(f): + @functools.wraps(f) + def inner(): + return f() + + return inner diff --git a/Lib/test/test_doctest/doctest_lineno.py b/Lib/test/test_doctest/doctest_lineno.py index 677c569cf710eb..b2348832adfa8d 100644 --- a/Lib/test/test_doctest/doctest_lineno.py +++ b/Lib/test/test_doctest/doctest_lineno.py @@ -67,3 +67,12 @@ def property_with_doctest(self): # https://github.com/python/cpython/issues/99433 str_wrapper = object().__str__ + + +# https://github.com/python/cpython/issues/115392 +from test.test_doctest._support import decorator + +@decorator +@decorator +def func_with_docstring_wrapped(): + """Some unrelated info.""" diff --git a/Lib/test/test_doctest/test_doctest.py b/Lib/test/test_doctest/test_doctest.py index 7015255db1f7f0..43be200b983227 100644 --- a/Lib/test/test_doctest/test_doctest.py +++ b/Lib/test/test_doctest/test_doctest.py @@ -685,6 +685,7 @@ def basics(): r""" None test.test_doctest.doctest_lineno.MethodWrapper.method_without_docstring 61 test.test_doctest.doctest_lineno.MethodWrapper.property_with_doctest 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 None test.test_doctest.doctest_lineno.func_without_docstring diff --git a/Misc/NEWS.d/next/Library/2024-02-13-18-27-03.gh-issue-115392.gle5tp.rst b/Misc/NEWS.d/next/Library/2024-02-13-18-27-03.gh-issue-115392.gle5tp.rst new file mode 100644 index 00000000000000..7329faf7011fc8 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-02-13-18-27-03.gh-issue-115392.gle5tp.rst @@ -0,0 +1,2 @@ +Fix a bug in `mod`:doctest: where incorrect line numbers would be +reported for decorated functions. From ffcb31b4a4dcbe9d8fd03e65dcc456e897a8c37c Mon Sep 17 00:00:00 2001 From: Brian Schubert Date: Tue, 13 Feb 2024 20:38:37 -0500 Subject: [PATCH 2/3] Fix typo in NEWS entry --- .../next/Library/2024-02-13-18-27-03.gh-issue-115392.gle5tp.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2024-02-13-18-27-03.gh-issue-115392.gle5tp.rst b/Misc/NEWS.d/next/Library/2024-02-13-18-27-03.gh-issue-115392.gle5tp.rst index 7329faf7011fc8..1c3368968e4cf0 100644 --- a/Misc/NEWS.d/next/Library/2024-02-13-18-27-03.gh-issue-115392.gle5tp.rst +++ b/Misc/NEWS.d/next/Library/2024-02-13-18-27-03.gh-issue-115392.gle5tp.rst @@ -1,2 +1,2 @@ -Fix a bug in `mod`:doctest: where incorrect line numbers would be +Fix a bug in :mod:`doctest` where incorrect line numbers would be reported for decorated functions. From 63d8b97cb9a0adcfd46fa8cae8aa3a5a92d4d379 Mon Sep 17 00:00:00 2001 From: Brian Schubert Date: Wed, 14 Feb 2024 09:02:11 -0500 Subject: [PATCH 3/3] Use inspect.unwrap, rename _support -> decorator_mod --- Lib/doctest.py | 4 +--- Lib/test/test_doctest/{_support.py => decorator_mod.py} | 0 Lib/test/test_doctest/doctest_lineno.py | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) rename Lib/test/test_doctest/{_support.py => decorator_mod.py} (100%) diff --git a/Lib/doctest.py b/Lib/doctest.py index c403245af5d4e2..1969777b667787 100644 --- a/Lib/doctest.py +++ b/Lib/doctest.py @@ -1140,9 +1140,7 @@ def _find_lineno(self, obj, source_lines): obj = obj.fget if inspect.isfunction(obj) and getattr(obj, '__doc__', None): # We don't use `docstring` var here, because `obj` can be changed. - while hasattr(obj, "__wrapped__"): - obj = obj.__wrapped__ - obj = obj.__code__ + obj = inspect.unwrap(obj).__code__ if inspect.istraceback(obj): obj = obj.tb_frame if inspect.isframe(obj): obj = obj.f_code if inspect.iscode(obj): diff --git a/Lib/test/test_doctest/_support.py b/Lib/test/test_doctest/decorator_mod.py similarity index 100% rename from Lib/test/test_doctest/_support.py rename to Lib/test/test_doctest/decorator_mod.py diff --git a/Lib/test/test_doctest/doctest_lineno.py b/Lib/test/test_doctest/doctest_lineno.py index b2348832adfa8d..0dbcd9a11eaba2 100644 --- a/Lib/test/test_doctest/doctest_lineno.py +++ b/Lib/test/test_doctest/doctest_lineno.py @@ -70,7 +70,7 @@ def property_with_doctest(self): # https://github.com/python/cpython/issues/115392 -from test.test_doctest._support import decorator +from test.test_doctest.decorator_mod import decorator @decorator @decorator