Skip to content

Commit 5aed15d

Browse files
committed
imp(terminal): replace non-color escape sequences in output
1 parent 06712d4 commit 5aed15d

2 files changed

Lines changed: 25 additions & 0 deletions

File tree

src/_pytest/terminal.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import linecache
99
import os
1010
import platform
11+
import re
1112
import sys
1213
import time
1314
import warnings
@@ -50,6 +51,7 @@
5051
from _pytest._code.code import _TracebackStyle
5152

5253
REPORT_COLLECTING_RESOLUTION = 0.5
54+
RE_ESCAPE_NONCOLOR = re.compile(r'\x1b(?!\[[\d;]+m)')
5355

5456
KNOWN_TYPES = (
5557
"failed",
@@ -65,6 +67,10 @@
6567
_REPORTCHARS_DEFAULT = "fE"
6668

6769

70+
def replace_non_color_escapes(s: str) -> str:
71+
return RE_ESCAPE_NONCOLOR.sub('^[', s)
72+
73+
6874
def _getdimensions() -> Tuple[int, int]:
6975
# Improved version of shutil.get_terminal_size that looks at stdin,
7076
# stderr, stdout. Ref: https://bugs.python.org/issue14841.
@@ -1176,6 +1182,7 @@ def _outrep_summary(self, rep):
11761182
self.section(secname, "-")
11771183
if content[-1:] == "\n":
11781184
content = content[:-1]
1185+
content = replace_non_color_escapes(content)
11791186
self._tw.line(content)
11801187

11811188
def summary_stats(self) -> None:

testing/test_terminal.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
from _pytest.terminal import _get_pos
2626
from _pytest.terminal import _plugin_nameversions
2727
from _pytest.terminal import getreportopt
28+
from _pytest.terminal import replace_non_color_escapes
2829
from _pytest.terminal import TerminalReporter
2930

3031
try:
@@ -361,6 +362,23 @@ def test_rewrite(self, testdir, monkeypatch):
361362
assert f.getvalue() == "hello" + "\r" + "hey" + (6 * " ")
362363

363364

365+
class TestTerminalUnit:
366+
def test_replace_non_color_escapes(self) -> None:
367+
f = replace_non_color_escapes
368+
369+
# without any escapes.
370+
assert f("foo") == "foo"
371+
372+
# color escapes.
373+
assert f('\x1b[32mINFO') == '\x1b[32mINFO'
374+
assert f('\x1b[38;2;0;0;0m') == '\x1b[38;2;0;0;0m'
375+
376+
# non-color escapes.
377+
# clears screen.
378+
assert f('\033[2J\033[1;1H') == '^[[2J^[[1;1H'
379+
assert f('\033') == '^['
380+
381+
364382
class TestCollectonly:
365383
def test_collectonly_basic(self, testdir):
366384
testdir.makepyfile(

0 commit comments

Comments
 (0)