From 9fa17222252cd04c06fa797204955b5591c621aa Mon Sep 17 00:00:00 2001 From: sobolevn Date: Tue, 31 Oct 2023 15:30:13 +0300 Subject: [PATCH 1/6] gh-111159: Fix `SyntaxError` doctests for non-builtin exception classes --- Lib/doctest.py | 7 ++++++- Lib/test/test_doctest.py | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/Lib/doctest.py b/Lib/doctest.py index f00d9358ffe10b..5b3723281d4c44 100644 --- a/Lib/doctest.py +++ b/Lib/doctest.py @@ -1402,7 +1402,12 @@ def __run(self, test, compileflags, out): exc_msg_index = next( index for index, line in enumerate(formatted_ex) - if line.startswith(f"{exception[0].__name__}:") + if ( + line.startswith(f"{exception[0].__qualname__}:") + or line.startswith( + f"{exception[0].__module__}.{exception[0].__qualname__}:", + ) + ) ) formatted_ex = formatted_ex[exc_msg_index:] diff --git a/Lib/test/test_doctest.py b/Lib/test/test_doctest.py index 5c59b00e729aa0..52ff0b06cf82f1 100644 --- a/Lib/test/test_doctest.py +++ b/Lib/test/test_doctest.py @@ -3310,6 +3310,25 @@ def test_syntax_error_with_note(cls, multiline=False): raise exc +def test_syntax_error_subclass_from_stdlib(): + """ + `ParseError` is a subclass of `SyntaxError`, but it is not a builtin: + + >>> from xml.etree.ElementTree import ParseError + >>> test_syntax_error_subclass_from_stdlib() + Traceback (most recent call last): + ... + xml.etree.ElementTree.ParseError: error + error + Note + Line + """ + from xml.etree.ElementTree import ParseError + exc = ParseError("error\nerror") + exc.add_note('Note\nLine') + raise exc + + def test_syntax_error_with_incorrect_expected_note(): """ >>> def f(x): From 42e2887514d26d150a722f0a4c126764c4dd63f9 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Tue, 31 Oct 2023 16:08:03 +0300 Subject: [PATCH 2/6] Address review --- Lib/doctest.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/Lib/doctest.py b/Lib/doctest.py index 5b3723281d4c44..be7e16aa531092 100644 --- a/Lib/doctest.py +++ b/Lib/doctest.py @@ -1399,15 +1399,12 @@ def __run(self, test, compileflags, out): # 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) + exc_name = f"{exception[0].__qualname__}:" + exc_fullname = f"{exception[0].__module__}.{exception[0].__qualname__}:" exc_msg_index = next( index for index, line in enumerate(formatted_ex) - if ( - line.startswith(f"{exception[0].__qualname__}:") - or line.startswith( - f"{exception[0].__module__}.{exception[0].__qualname__}:", - ) - ) + if line.startswith(exc_name) or line.startswith(exc_fullname) ) formatted_ex = formatted_ex[exc_msg_index:] From 7d388e23b74d2a84e1d9b1aecbc70c45c63b5b70 Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Wed, 1 Nov 2023 00:00:59 +0300 Subject: [PATCH 3/6] Apply suggestions from code review Co-authored-by: scoder --- Lib/doctest.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Lib/doctest.py b/Lib/doctest.py index be7e16aa531092..2f14aa08334895 100644 --- a/Lib/doctest.py +++ b/Lib/doctest.py @@ -1399,12 +1399,14 @@ def __run(self, test, compileflags, out): # 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) - exc_name = f"{exception[0].__qualname__}:" - exc_fullname = f"{exception[0].__module__}.{exception[0].__qualname__}:" + exception_line_prefixes = ( + f"{exception[0].__qualname__}:", + f"{exception[0].__module__}.{exception[0].__qualname__}:", + ) exc_msg_index = next( index for index, line in enumerate(formatted_ex) - if line.startswith(exc_name) or line.startswith(exc_fullname) + if line.startswith(exception_line_prefixes) ) formatted_ex = formatted_ex[exc_msg_index:] From 1c03d66a3e1275040a9a99289b7482d9b8a23b8b Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Wed, 1 Nov 2023 09:12:51 +0300 Subject: [PATCH 4/6] Apply suggestions from code review --- Lib/test/test_doctest.py | 1 - 1 file changed, 1 deletion(-) diff --git a/Lib/test/test_doctest.py b/Lib/test/test_doctest.py index 52ff0b06cf82f1..cb4e2157bb228b 100644 --- a/Lib/test/test_doctest.py +++ b/Lib/test/test_doctest.py @@ -3314,7 +3314,6 @@ def test_syntax_error_subclass_from_stdlib(): """ `ParseError` is a subclass of `SyntaxError`, but it is not a builtin: - >>> from xml.etree.ElementTree import ParseError >>> test_syntax_error_subclass_from_stdlib() Traceback (most recent call last): ... From 84177b26ed07f71d88a2d5aa9eb6974e723bccb5 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Sat, 4 Nov 2023 10:24:32 +0300 Subject: [PATCH 5/6] Add news --- .../next/Library/2023-11-04-10-24-25.gh-issue-111541.x0RBI1.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2023-11-04-10-24-25.gh-issue-111541.x0RBI1.rst diff --git a/Misc/NEWS.d/next/Library/2023-11-04-10-24-25.gh-issue-111541.x0RBI1.rst b/Misc/NEWS.d/next/Library/2023-11-04-10-24-25.gh-issue-111541.x0RBI1.rst new file mode 100644 index 00000000000000..2bb54fc62f998e --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-11-04-10-24-25.gh-issue-111541.x0RBI1.rst @@ -0,0 +1 @@ +Fix :mod:`doctest` for `SyntaxError` not-builtin subclasses. From e5453063750666614e8760019ce15973a82c30dc Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Sat, 4 Nov 2023 10:40:59 +0300 Subject: [PATCH 6/6] Update 2023-11-04-10-24-25.gh-issue-111541.x0RBI1.rst --- .../next/Library/2023-11-04-10-24-25.gh-issue-111541.x0RBI1.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2023-11-04-10-24-25.gh-issue-111541.x0RBI1.rst b/Misc/NEWS.d/next/Library/2023-11-04-10-24-25.gh-issue-111541.x0RBI1.rst index 2bb54fc62f998e..719b63dad36fb7 100644 --- a/Misc/NEWS.d/next/Library/2023-11-04-10-24-25.gh-issue-111541.x0RBI1.rst +++ b/Misc/NEWS.d/next/Library/2023-11-04-10-24-25.gh-issue-111541.x0RBI1.rst @@ -1 +1 @@ -Fix :mod:`doctest` for `SyntaxError` not-builtin subclasses. +Fix :mod:`doctest` for :exc:`SyntaxError` not-builtin subclasses.