From a1591f8aafc5fc4c101dafb7729e5f8a00862d22 Mon Sep 17 00:00:00 2001 From: pandula12 Date: Mon, 13 May 2024 14:53:47 +0930 Subject: [PATCH] true color and 256 terminal formatters added and use PYTEST_THEME env variable for style --- AUTHORS | 1 + changelog/11666.imporvement.rst | 5 ++ src/_pytest/_io/terminalwriter.py | 109 ++++++++++++++++-------------- 3 files changed, 65 insertions(+), 50 deletions(-) create mode 100644 changelog/11666.imporvement.rst diff --git a/AUTHORS b/AUTHORS index 54ed85fc7..d8c173ac1 100644 --- a/AUTHORS +++ b/AUTHORS @@ -308,6 +308,7 @@ Omar Kohl Omer Hadari Ondřej Súkup Oscar Benjamin +Pandula Gajadeera Parth Patel Patrick Hayes Patrick Lannigan diff --git a/changelog/11666.imporvement.rst b/changelog/11666.imporvement.rst new file mode 100644 index 000000000..b5cdf863b --- /dev/null +++ b/changelog/11666.imporvement.rst @@ -0,0 +1,5 @@ +Improved the terminal writer to be able to use Terminal256Formatter and TerminalTrueColorFormatter. + +These are newer versions of TerminalFormmater from the pygments library that is currently in use. + +These style of these formatters are set by the users through the environmental variable PYTEST_THEME. \ No newline at end of file diff --git a/src/_pytest/_io/terminalwriter.py b/src/_pytest/_io/terminalwriter.py index 5bcd05927..a03bd0ce7 100644 --- a/src/_pytest/_io/terminalwriter.py +++ b/src/_pytest/_io/terminalwriter.py @@ -194,58 +194,67 @@ class TerminalWriter: for indent, new_line in zip(indents, new_lines): self.line(indent + new_line) - def _highlight( - self, source: str, lexer: Literal["diff", "python"] = "python" - ) -> str: - """Highlight the given source if we have markup support.""" - from _pytest.config.exceptions import UsageError +def _highlight( + self, source: str, lexer: Literal["diff", "python"] = "python" +) -> str: + """Highlight the given source if we have markup support.""" + from _pytest.config.exceptions import UsageError - if not source or not self.hasmarkup or not self.code_highlight: - return source + if not source or not self.hasmarkup or not self.code_highlight: + return source - try: - from pygments.formatters.terminal import TerminalFormatter + try: + from pygments.formatters.terminal import TerminalFormatter - if lexer == "python": - from pygments.lexers.python import PythonLexer as Lexer - elif lexer == "diff": - from pygments.lexers.diff import DiffLexer as Lexer - else: - assert_never(lexer) - from pygments import highlight - import pygments.util - except ImportError: - return source + if lexer == "python": + from pygments.lexers.python import PythonLexer as Lexer + elif lexer == "diff": + from pygments.lexers.diff import DiffLexer as Lexer else: - try: - highlighted: str = highlight( - source, - Lexer(), - TerminalFormatter( - bg=os.getenv("PYTEST_THEME_MODE", "dark"), - style=os.getenv("PYTEST_THEME"), - ), - ) - # pygments terminal formatter may add a newline when there wasn't one. - # We don't want this, remove. - if highlighted[-1] == "\n" and source[-1] != "\n": - highlighted = highlighted[:-1] + assert_never(lexer) - # Some lexers will not set the initial color explicitly - # which may lead to the previous color being propagated to the - # start of the expression, so reset first. - return "\x1b[0m" + highlighted - except pygments.util.ClassNotFound as e: - raise UsageError( - "PYTEST_THEME environment variable had an invalid value: '{}'. " - "Only valid pygment styles are allowed.".format( - os.getenv("PYTEST_THEME") - ) - ) from e - except pygments.util.OptionError as e: - raise UsageError( - "PYTEST_THEME_MODE environment variable had an invalid value: '{}'. " - "The only allowed values are 'dark' and 'light'.".format( - os.getenv("PYTEST_THEME_MODE") - ) - ) from e + from pygments import highlight + import pygments.util + + if os.getenv("COLORTERM", "") in ("truecolor", "24bit"): + from pygments.formatters.terminal256 import TerminalTrueColorFormatter + terminal_formatter = TerminalTrueColorFormatter(style=os.getenv("PYTEST_THEME", "default")) + elif "256" in os.getenv("TERM", ""): + from pygments.formatters.terminal256 import Terminal256Formatter + terminal_formatter = Terminal256Formatter(style=os.getenv("PYTEST_THEME", "default")) + else: + terminal_formatter = TerminalFormatter(bg=os.getenv("PYTEST_THEME_MODE", "dark"), + style=os.getenv("PYTEST_THEME", "default")) + + except ImportError: + return source + else: + try: + highlighted: str = highlight( + source, + Lexer(), + terminal_formatter, + ) + # pygments terminal formatter may add a newline when there wasn't one. + # We don't want this, remove. + if highlighted[-1] == "\n" and source[-1] != "\n": + highlighted = highlighted[:-1] + + # Some lexers will not set the initial color explicitly + # which may lead to the previous color being propagated to the + # start of the expression, so reset first. + return "\x1b[0m" + highlighted + except pygments.util.ClassNotFound as e: + raise UsageError( + "PYTEST_THEME environment variable had an invalid value: '{}'. " + "Only valid pygment styles are allowed.".format( + os.getenv("PYTEST_THEME") + ) + ) from e + except pygments.util.OptionError as e: + raise UsageError( + "PYTEST_THEME_MODE environment variable had an invalid value: '{}'. " + "The only allowed values are 'dark' and 'light'.".format( + os.getenv("PYTEST_THEME_MODE") + ) + ) from e