https://github.com/python/cpython/commit/cb8a72b301f47e76d93a7fe5b259e9a5758792e1
commit: cb8a72b301f47e76d93a7fe5b259e9a5758792e1
branch: main
author: Serhiy Storchaka <[email protected]>
committer: serhiy-storchaka <[email protected]>
date: 2025-05-30T00:32:44+03:00
summary:
gh-134857: Improve error report for doctests run with unittest (GH-134858)
Remove doctest module frames from tracebacks and redundant newline
character from a failure message.
files:
A Misc/NEWS.d/next/Library/2025-05-28-20-49-29.gh-issue-134857.dVYXVO.rst
M Lib/doctest.py
M Lib/test/test_doctest/test_doctest.py
diff --git a/Lib/doctest.py b/Lib/doctest.py
index 2acb6cb79f394d..dec10a345165da 100644
--- a/Lib/doctest.py
+++ b/Lib/doctest.py
@@ -108,6 +108,8 @@ def _test():
from _colorize import ANSIColors, can_colorize
+__unittest = True
+
class TestResults(namedtuple('TestResults', 'failed attempted')):
def __new__(cls, failed, attempted, *, skipped=0):
results = super().__new__(cls, failed, attempted)
@@ -1395,11 +1397,11 @@ def __run(self, test, compileflags, out):
exec(compile(example.source, filename, "single",
compileflags, True), test.globs)
self.debugger.set_continue() # ==== Example Finished ====
- exception = None
+ exc_info = None
except KeyboardInterrupt:
raise
- except:
- exception = sys.exc_info()
+ except BaseException as exc:
+ exc_info = type(exc), exc, exc.__traceback__.tb_next
self.debugger.set_continue() # ==== Example Finished ====
got = self._fakeout.getvalue() # the actual output
@@ -1408,21 +1410,21 @@ def __run(self, test, compileflags, out):
# If the example executed without raising any exceptions,
# verify its output.
- if exception is None:
+ if exc_info is None:
if check(example.want, got, self.optionflags):
outcome = SUCCESS
# The example raised an exception: check if it was expected.
else:
- formatted_ex = traceback.format_exception_only(*exception[:2])
- if issubclass(exception[0], SyntaxError):
+ formatted_ex = traceback.format_exception_only(*exc_info[:2])
+ if issubclass(exc_info[0], SyntaxError):
# SyntaxError / IndentationError is special:
# we don't care about the carets / suggestions / etc
# We only care about the error message and notes.
# They start with `SyntaxError:` (or any other class name)
exception_line_prefixes = (
- f"{exception[0].__qualname__}:",
-
f"{exception[0].__module__}.{exception[0].__qualname__}:",
+ f"{exc_info[0].__qualname__}:",
+
f"{exc_info[0].__module__}.{exc_info[0].__qualname__}:",
)
exc_msg_index = next(
index
@@ -1433,7 +1435,7 @@ def __run(self, test, compileflags, out):
exc_msg = "".join(formatted_ex)
if not quiet:
- got += _exception_traceback(exception)
+ got += _exception_traceback(exc_info)
# If `example.exc_msg` is None, then we weren't expecting
# an exception.
@@ -1462,7 +1464,7 @@ def __run(self, test, compileflags, out):
elif outcome is BOOM:
if not quiet:
self.report_unexpected_exception(out, test, example,
- exception)
+ exc_info)
failures += 1
else:
assert False, ("unknown outcome", outcome)
@@ -2324,7 +2326,7 @@ def runTest(self):
sys.stdout = old
if results.failed:
- raise self.failureException(self.format_failure(new.getvalue()))
+ raise
self.failureException(self.format_failure(new.getvalue().rstrip('\n')))
def format_failure(self, err):
test = self._dt_test
diff --git a/Lib/test/test_doctest/test_doctest.py
b/Lib/test/test_doctest/test_doctest.py
index c5b247797c321d..2bfaa6c599cd47 100644
--- a/Lib/test/test_doctest/test_doctest.py
+++ b/Lib/test/test_doctest/test_doctest.py
@@ -2411,9 +2411,6 @@ def test_DocTestSuite_errors():
>>> result
<unittest.result.TestResult run=4 errors=0 failures=4>
>>> print(result.failures[0][1]) # doctest: +ELLIPSIS
- Traceback (most recent call last):
- File ...
- raise self.failureException(self.format_failure(new.getvalue()))
AssertionError: Failed doctest test for
test.test_doctest.sample_doctest_errors
File "...sample_doctest_errors.py", line 0, in sample_doctest_errors
<BLANKLINE>
@@ -2431,21 +2428,12 @@ def test_DocTestSuite_errors():
1/0
Exception raised:
Traceback (most recent call last):
- File ...
- exec(compile(example.source, filename, "single",
- ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- compileflags, True), test.globs)
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<doctest test.test_doctest.sample_doctest_errors[1]>",
line 1, in <module>
1/0
~^~
ZeroDivisionError: division by zero
<BLANKLINE>
- <BLANKLINE>
>>> print(result.failures[1][1]) # doctest: +ELLIPSIS
- Traceback (most recent call last):
- File ...
- raise self.failureException(self.format_failure(new.getvalue()))
AssertionError: Failed doctest test for
test.test_doctest.sample_doctest_errors.__test__.bad
File "...sample_doctest_errors.py", line unknown line number, in bad
<BLANKLINE>
@@ -2463,21 +2451,12 @@ def test_DocTestSuite_errors():
1/0
Exception raised:
Traceback (most recent call last):
- File ...
- exec(compile(example.source, filename, "single",
- ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- compileflags, True), test.globs)
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<doctest
test.test_doctest.sample_doctest_errors.__test__.bad[1]>", line 1, in <module>
1/0
~^~
ZeroDivisionError: division by zero
<BLANKLINE>
- <BLANKLINE>
>>> print(result.failures[2][1]) # doctest: +ELLIPSIS
- Traceback (most recent call last):
- File ...
- raise self.failureException(self.format_failure(new.getvalue()))
AssertionError: Failed doctest test for
test.test_doctest.sample_doctest_errors.errors
File "...sample_doctest_errors.py", line 14, in errors
<BLANKLINE>
@@ -2495,11 +2474,6 @@ def test_DocTestSuite_errors():
1/0
Exception raised:
Traceback (most recent call last):
- File ...
- exec(compile(example.source, filename, "single",
- ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- compileflags, True), test.globs)
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<doctest
test.test_doctest.sample_doctest_errors.errors[1]>", line 1, in <module>
1/0
~^~
@@ -2510,11 +2484,6 @@ def test_DocTestSuite_errors():
f()
Exception raised:
Traceback (most recent call last):
- File ...
- exec(compile(example.source, filename, "single",
- ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- compileflags, True), test.globs)
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<doctest
test.test_doctest.sample_doctest_errors.errors[3]>", line 1, in <module>
f()
~^^
@@ -2528,11 +2497,6 @@ def test_DocTestSuite_errors():
g()
Exception raised:
Traceback (most recent call last):
- File ...
- exec(compile(example.source, filename, "single",
- ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- compileflags, True), test.globs)
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<doctest
test.test_doctest.sample_doctest_errors.errors[4]>", line 1, in <module>
g()
~^^
@@ -2541,11 +2505,7 @@ def test_DocTestSuite_errors():
~~^^^
IndexError: list index out of range
<BLANKLINE>
- <BLANKLINE>
>>> print(result.failures[3][1]) # doctest: +ELLIPSIS
- Traceback (most recent call last):
- File ...
- raise self.failureException(self.format_failure(new.getvalue()))
AssertionError: Failed doctest test for
test.test_doctest.sample_doctest_errors.syntax_error
File "...sample_doctest_errors.py", line 29, in syntax_error
<BLANKLINE>
@@ -2554,18 +2514,11 @@ def test_DocTestSuite_errors():
Failed example:
2+*3
Exception raised:
- Traceback (most recent call last):
- File ...
- exec(compile(example.source, filename, "single",
- ~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- compileflags, True), test.globs)
- ^^^^^^^^^^^^^^^^^^^
File "<doctest
test.test_doctest.sample_doctest_errors.syntax_error[0]>", line 1
2+*3
^
SyntaxError: invalid syntax
<BLANKLINE>
- <BLANKLINE>
"""
def test_DocFileSuite():
@@ -2740,9 +2693,6 @@ def test_DocFileSuite_errors():
>>> result
<unittest.result.TestResult run=1 errors=0 failures=1>
>>> print(result.failures[0][1]) # doctest: +ELLIPSIS
- Traceback (most recent call last):
- File ...
- raise self.failureException(self.format_failure(new.getvalue()))
AssertionError: Failed doctest test for test_doctest_errors.txt
File "...test_doctest_errors.txt", line 0
<BLANKLINE>
@@ -2760,11 +2710,6 @@ def test_DocFileSuite_errors():
1/0
Exception raised:
Traceback (most recent call last):
- File ...
- exec(compile(example.source, filename, "single",
- ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- compileflags, True), test.globs)
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<doctest test_doctest_errors.txt[1]>", line 1, in <module>
1/0
~^~
@@ -2775,11 +2720,6 @@ def test_DocFileSuite_errors():
f()
Exception raised:
Traceback (most recent call last):
- File ...
- exec(compile(example.source, filename, "single",
- ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- compileflags, True), test.globs)
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<doctest test_doctest_errors.txt[3]>", line 1, in <module>
f()
~^^
@@ -2792,18 +2732,11 @@ def test_DocFileSuite_errors():
Failed example:
2+*3
Exception raised:
- Traceback (most recent call last):
- File ...
- exec(compile(example.source, filename, "single",
- ~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- compileflags, True), test.globs)
- ^^^^^^^^^^^^^^^^^^^
File "<doctest test_doctest_errors.txt[4]>", line 1
2+*3
^
SyntaxError: invalid syntax
<BLANKLINE>
- <BLANKLINE>
"""
def test_trailing_space_in_test():
@@ -2876,7 +2809,8 @@ def test_unittest_reportflags():
>>> result
<unittest.result.TestResult run=1 errors=0 failures=1>
>>> print(result.failures[0][1]) # doctest: +ELLIPSIS
- Traceback ...
+ AssertionError: Failed doctest test for test_doctest.txt
+ ...
Failed example:
favorite_color
...
@@ -2895,14 +2829,14 @@ def test_unittest_reportflags():
>>> result
<unittest.result.TestResult run=1 errors=0 failures=1>
>>> print(result.failures[0][1]) # doctest: +ELLIPSIS
- Traceback ...
+ AssertionError: Failed doctest test for test_doctest.txt
+ ...
Failed example:
favorite_color
Exception raised:
...
NameError: name 'favorite_color' is not defined
<BLANKLINE>
- <BLANKLINE>
We get only the first failure.
@@ -2922,7 +2856,8 @@ def test_unittest_reportflags():
the trailing whitespace using `\x20` in the diff below.
>>> print(result.failures[0][1]) # doctest: +ELLIPSIS
- Traceback ...
+ AssertionError: Failed doctest test for test_doctest.txt
+ ...
Failed example:
favorite_color
...
@@ -2937,7 +2872,6 @@ def test_unittest_reportflags():
+\x20
b
<BLANKLINE>
- <BLANKLINE>
Test runners can restore the formatting flags after they run:
@@ -3145,11 +3079,6 @@ def test_testfile_errors(): r"""
1/0
Exception raised:
Traceback (most recent call last):
- File ...
- exec(compile(example.source, filename, "single",
- ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- compileflags, True), test.globs)
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<doctest test_doctest_errors.txt[1]>", line 1, in <module>
1/0
~^~
@@ -3160,11 +3089,6 @@ def test_testfile_errors(): r"""
f()
Exception raised:
Traceback (most recent call last):
- File ...
- exec(compile(example.source, filename, "single",
- ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- compileflags, True), test.globs)
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<doctest test_doctest_errors.txt[3]>", line 1, in <module>
f()
~^^
@@ -3177,12 +3101,6 @@ def test_testfile_errors(): r"""
Failed example:
2+*3
Exception raised:
- Traceback (most recent call last):
- File ...
- exec(compile(example.source, filename, "single",
- ~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- compileflags, True), test.globs)
- ^^^^^^^^^^^^^^^^^^^
File "<doctest test_doctest_errors.txt[4]>", line 1
2+*3
^
@@ -3343,11 +3261,6 @@ def test_testmod_errors(): r"""
1/0
Exception raised:
Traceback (most recent call last):
- File ...
- exec(compile(example.source, filename, "single",
- ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- compileflags, True), test.globs)
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<doctest test.test_doctest.sample_doctest_errors[1]>", line 1,
in <module>
1/0
~^~
@@ -3366,11 +3279,6 @@ def test_testmod_errors(): r"""
1/0
Exception raised:
Traceback (most recent call last):
- File ...
- exec(compile(example.source, filename, "single",
- ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- compileflags, True), test.globs)
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<doctest
test.test_doctest.sample_doctest_errors.__test__.bad[1]>", line 1, in <module>
1/0
~^~
@@ -3389,11 +3297,6 @@ def test_testmod_errors(): r"""
1/0
Exception raised:
Traceback (most recent call last):
- File ...
- exec(compile(example.source, filename, "single",
- ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- compileflags, True), test.globs)
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<doctest test.test_doctest.sample_doctest_errors.errors[1]>",
line 1, in <module>
1/0
~^~
@@ -3404,11 +3307,6 @@ def test_testmod_errors(): r"""
f()
Exception raised:
Traceback (most recent call last):
- File ...
- exec(compile(example.source, filename, "single",
- ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- compileflags, True), test.globs)
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<doctest test.test_doctest.sample_doctest_errors.errors[3]>",
line 1, in <module>
f()
~^^
@@ -3422,11 +3320,6 @@ def test_testmod_errors(): r"""
g()
Exception raised:
Traceback (most recent call last):
- File ...
- exec(compile(example.source, filename, "single",
- ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- compileflags, True), test.globs)
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<doctest test.test_doctest.sample_doctest_errors.errors[4]>",
line 1, in <module>
g()
~^^
@@ -3439,12 +3332,6 @@ def test_testmod_errors(): r"""
Failed example:
2+*3
Exception raised:
- Traceback (most recent call last):
- File ...
- exec(compile(example.source, filename, "single",
- ~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- compileflags, True), test.globs)
- ^^^^^^^^^^^^^^^^^^^
File "<doctest
test.test_doctest.sample_doctest_errors.syntax_error[0]>", line 1
2+*3
^
@@ -3490,11 +3377,6 @@ def test_unicode(): """
raise Exception('clé')
Exception raised:
Traceback (most recent call last):
- File ...
- exec(compile(example.source, filename, "single",
- ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- compileflags, True), test.globs)
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<doctest foo-bär@baz[0]>", line 1, in <module>
raise Exception('clé')
Exception: clé
diff --git
a/Misc/NEWS.d/next/Library/2025-05-28-20-49-29.gh-issue-134857.dVYXVO.rst
b/Misc/NEWS.d/next/Library/2025-05-28-20-49-29.gh-issue-134857.dVYXVO.rst
new file mode 100644
index 00000000000000..92e38c0bb5ac87
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-05-28-20-49-29.gh-issue-134857.dVYXVO.rst
@@ -0,0 +1,3 @@
+Improve error report for :mod:`doctest`\ s run with :mod:`unittest`. Remove
+:mod:`!doctest` module frames from tracebacks and redundant newline
+character from a failure message.
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]