From f0d86b8d450e42695e5d014d91c5efb5eceaea53 Mon Sep 17 00:00:00 2001 From: Leonardus Chen Date: Thu, 14 Nov 2024 00:29:41 +0700 Subject: [PATCH 1/7] Fix ExcInfo.value printed as source code --- src/_pytest/_code/code.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index 8fac39ea298..c59aebf2b13 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -1221,6 +1221,11 @@ def _write_entry_lines(self, tw: TerminalWriter) -> None: if not self.lines: return + if self.style == "value": + for line in self.lines: + tw.line(line) + return + # separate indents and source lines that are not failures: we want to # highlight the code but not the indentation, which may contain markers # such as "> assert 0" @@ -1236,11 +1241,8 @@ def _write_entry_lines(self, tw: TerminalWriter) -> None: failure_lines.extend(self.lines[index:]) break else: - if self.style == "value": - source_lines.append(line) - else: - indents.append(line[:indent_size]) - source_lines.append(line[indent_size:]) + indents.append(line[:indent_size]) + source_lines.append(line[indent_size:]) tw._write_source(source_lines, indents) From 25848f4d385684232421bc1d4d26bf9b34c72f87 Mon Sep 17 00:00:00 2001 From: Leonardus Chen Date: Thu, 14 Nov 2024 22:36:56 +0700 Subject: [PATCH 2/7] Change tw.line to tw.write --- src/_pytest/_code/code.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index c59aebf2b13..1be408525ac 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -1223,7 +1223,8 @@ def _write_entry_lines(self, tw: TerminalWriter) -> None: if self.style == "value": for line in self.lines: - tw.line(line) + tw.write(line) + tw.write("\n") return # separate indents and source lines that are not failures: we want to From c6a5c8da573141f4d7c6083d9a6aa4cbca336495 Mon Sep 17 00:00:00 2001 From: Leonardus Chen Date: Thu, 14 Nov 2024 22:37:34 +0700 Subject: [PATCH 3/7] Implement tests --- testing/code/test_excinfo.py | 19 +++++++++++++++++-- testing/conftest.py | 4 ++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index fc60ae9ac99..c203b1d8511 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -1103,6 +1103,23 @@ def f(): assert line.endswith("mod.py") assert tw_mock.lines[12] == ":3: ValueError" + def test_toterminal_value(self, importasmod, tw_mock): + mod = importasmod( + """ + def g(x): + raise ValueError(x) + def f(): + g('some_value') + """ + ) + excinfo = pytest.raises(ValueError, mod.f) + excinfo.traceback = excinfo.traceback.filter(excinfo) + repr = excinfo.getrepr(style="value") + repr.toterminal(tw_mock) + + assert tw_mock.get_write_msg(0) == "some_value" + assert tw_mock.get_write_msg(1) == "\n" + def test_toterminal_long_missing_source( self, importasmod, tmp_path: Path, tw_mock ) -> None: @@ -1250,8 +1267,6 @@ def i(): ) r = excinfo.getrepr(style="long") r.toterminal(tw_mock) - for line in tw_mock.lines: - print(line) assert tw_mock.lines[0] == "" assert tw_mock.lines[1] == " def f():" assert tw_mock.lines[2] == "> g()" diff --git a/testing/conftest.py b/testing/conftest.py index 046bb77a109..69af03324d6 100644 --- a/testing/conftest.py +++ b/testing/conftest.py @@ -119,8 +119,8 @@ def markup(self, text, **kw): return text def get_write_msg(self, idx): - flag, msg = self.lines[idx] - assert flag == TWMock.WRITE + assert self.lines[idx][0] == TWMock.WRITE + msg = self.lines[idx][1] return msg fullwidth = 80 From d50ad9306a4c4b69bdd970a57fc0aa1978b3030d Mon Sep 17 00:00:00 2001 From: Leonardus Chen Date: Thu, 14 Nov 2024 23:01:08 +0700 Subject: [PATCH 4/7] Add changelog and update AUTHORS --- AUTHORS | 1 + changelog/12849.bugfix.rst | 1 + 2 files changed, 2 insertions(+) create mode 100644 changelog/12849.bugfix.rst diff --git a/AUTHORS b/AUTHORS index c38f74d9980..303d04133cb 100644 --- a/AUTHORS +++ b/AUTHORS @@ -247,6 +247,7 @@ Kristoffer Nordström Kyle Altendorf Lawrence Mitchell Lee Kamentsky +Leonardus Chen Lev Maximov Levon Saldamli Lewis Cowles diff --git a/changelog/12849.bugfix.rst b/changelog/12849.bugfix.rst new file mode 100644 index 00000000000..4ec483503a3 --- /dev/null +++ b/changelog/12849.bugfix.rst @@ -0,0 +1 @@ +ANSI escape codes for colored output now handled correctly in :func:`pytest.fail` with `pytrace=False` From 7a2cf77b4b10bf77a7675a394c4649453253dcbb Mon Sep 17 00:00:00 2001 From: Leonardus Chen Date: Thu, 14 Nov 2024 23:13:42 +0700 Subject: [PATCH 5/7] Cleanup --- testing/code/test_excinfo.py | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index c203b1d8511..97c207e9795 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -1103,23 +1103,6 @@ def f(): assert line.endswith("mod.py") assert tw_mock.lines[12] == ":3: ValueError" - def test_toterminal_value(self, importasmod, tw_mock): - mod = importasmod( - """ - def g(x): - raise ValueError(x) - def f(): - g('some_value') - """ - ) - excinfo = pytest.raises(ValueError, mod.f) - excinfo.traceback = excinfo.traceback.filter(excinfo) - repr = excinfo.getrepr(style="value") - repr.toterminal(tw_mock) - - assert tw_mock.get_write_msg(0) == "some_value" - assert tw_mock.get_write_msg(1) == "\n" - def test_toterminal_long_missing_source( self, importasmod, tmp_path: Path, tw_mock ) -> None: @@ -1211,6 +1194,23 @@ def f(): line = tw_mock.lines[-1] assert line == ":3: ValueError" + def test_toterminal_value(self, importasmod, tw_mock): + mod = importasmod( + """ + def g(x): + raise ValueError(x) + def f(): + g('some_value') + """ + ) + excinfo = pytest.raises(ValueError, mod.f) + excinfo.traceback = excinfo.traceback.filter(excinfo) + repr = excinfo.getrepr(style="value") + repr.toterminal(tw_mock) + + assert tw_mock.get_write_msg(0) == "some_value" + assert tw_mock.get_write_msg(1) == "\n" + @pytest.mark.parametrize( "reproptions", [ @@ -1267,6 +1267,8 @@ def i(): ) r = excinfo.getrepr(style="long") r.toterminal(tw_mock) + for line in tw_mock.lines: + print(line) assert tw_mock.lines[0] == "" assert tw_mock.lines[1] == " def f():" assert tw_mock.lines[2] == "> g()" From 0e56876dc398c681eca4cda737562a3f3f79d137 Mon Sep 17 00:00:00 2001 From: Leonardus Chen Date: Thu, 14 Nov 2024 23:56:18 +0700 Subject: [PATCH 6/7] Forgot dot --- changelog/12849.bugfix.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog/12849.bugfix.rst b/changelog/12849.bugfix.rst index 4ec483503a3..fb72263aadd 100644 --- a/changelog/12849.bugfix.rst +++ b/changelog/12849.bugfix.rst @@ -1 +1 @@ -ANSI escape codes for colored output now handled correctly in :func:`pytest.fail` with `pytrace=False` +ANSI escape codes for colored output now handled correctly in :func:`pytest.fail` with `pytrace=False`. From 21225800ee59b47f1a3d5343931577922d936e20 Mon Sep 17 00:00:00 2001 From: Leonardus Chen Date: Fri, 22 Nov 2024 00:34:32 +0700 Subject: [PATCH 7/7] Add comments on tw.write usage instead of tw.line --- src/_pytest/_code/code.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index 1be408525ac..fec627b3a36 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -1222,6 +1222,9 @@ def _write_entry_lines(self, tw: TerminalWriter) -> None: return if self.style == "value": + # Using tw.write instead of tw.line for testing purposes due to TWMock implementation; + # lines written with TWMock.line and TWMock._write_source cannot be distinguished + # from each other, whereas lines written with TWMock.write are marked with TWMock.WRITE for line in self.lines: tw.write(line) tw.write("\n")