gh-117225: Move colorize functionality to own internal module (#118283)

This commit is contained in:
Hugo van Kemenade 2024-05-01 21:27:06 +03:00 committed by GitHub
parent 164e2c31c0
commit 3b3f8dea57
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 218 additions and 180 deletions

64
Lib/_colorize.py Normal file
View File

@ -0,0 +1,64 @@
import io
import os
import sys
COLORIZE = True
class ANSIColors:
BOLD_GREEN = "\x1b[1;32m"
BOLD_MAGENTA = "\x1b[1;35m"
BOLD_RED = "\x1b[1;31m"
GREEN = "\x1b[32m"
GREY = "\x1b[90m"
MAGENTA = "\x1b[35m"
RED = "\x1b[31m"
RESET = "\x1b[0m"
YELLOW = "\x1b[33m"
NoColors = ANSIColors()
for attr in dir(NoColors):
if not attr.startswith("__"):
setattr(NoColors, attr, "")
def get_colors(colorize: bool = False) -> ANSIColors:
if colorize or can_colorize():
return ANSIColors()
else:
return NoColors
def can_colorize() -> bool:
if sys.platform == "win32":
try:
import nt
if not nt._supports_virtual_terminal():
return False
except (ImportError, AttributeError):
return False
if not sys.flags.ignore_environment:
if os.environ.get("PYTHON_COLORS") == "0":
return False
if os.environ.get("PYTHON_COLORS") == "1":
return True
if "NO_COLOR" in os.environ:
return False
if not COLORIZE:
return False
if not sys.flags.ignore_environment:
if "FORCE_COLOR" in os.environ:
return True
if os.environ.get("TERM") == "dumb":
return False
if not hasattr(sys.stderr, "fileno"):
return False
try:
return os.isatty(sys.stderr.fileno())
except io.UnsupportedOperation:
return sys.stderr.isatty()

View File

@ -104,7 +104,8 @@ import traceback
import unittest
from io import StringIO, IncrementalNewlineDecoder
from collections import namedtuple
from traceback import _ANSIColors, _can_colorize
import _colorize # Used in doctests
from _colorize import ANSIColors, can_colorize
class TestResults(namedtuple('TestResults', 'failed attempted')):
@ -1180,8 +1181,8 @@ class DocTestRunner:
The `run` method is used to process a single DocTest case. It
returns a TestResults instance.
>>> save_colorize = traceback._COLORIZE
>>> traceback._COLORIZE = False
>>> save_colorize = _colorize.COLORIZE
>>> _colorize.COLORIZE = False
>>> tests = DocTestFinder().find(_TestClass)
>>> runner = DocTestRunner(verbose=False)
@ -1234,7 +1235,7 @@ class DocTestRunner:
overriding the methods `report_start`, `report_success`,
`report_unexpected_exception`, and `report_failure`.
>>> traceback._COLORIZE = save_colorize
>>> _colorize.COLORIZE = save_colorize
"""
# This divider string is used to separate failure messages, and to
# separate sections of the summary.
@ -1314,7 +1315,7 @@ class DocTestRunner:
def _failure_header(self, test, example):
red, reset = (
(_ANSIColors.RED, _ANSIColors.RESET) if _can_colorize() else ("", "")
(ANSIColors.RED, ANSIColors.RESET) if can_colorize() else ("", "")
)
out = [f"{red}{self.DIVIDER}{reset}"]
if test.filename:
@ -1556,8 +1557,8 @@ class DocTestRunner:
# Make sure sys.displayhook just prints the value to stdout
save_displayhook = sys.displayhook
sys.displayhook = sys.__displayhook__
saved_can_colorize = traceback._can_colorize
traceback._can_colorize = lambda: False
saved_can_colorize = _colorize.can_colorize
_colorize.can_colorize = lambda: False
color_variables = {"PYTHON_COLORS": None, "FORCE_COLOR": None}
for key in color_variables:
color_variables[key] = os.environ.pop(key, None)
@ -1569,7 +1570,7 @@ class DocTestRunner:
sys.settrace(save_trace)
linecache.getlines = self.save_linecache_getlines
sys.displayhook = save_displayhook
traceback._can_colorize = saved_can_colorize
_colorize.can_colorize = saved_can_colorize
for key, value in color_variables.items():
if value is not None:
os.environ[key] = value
@ -1609,20 +1610,13 @@ class DocTestRunner:
else:
failed.append((name, (failures, tries, skips)))
if _can_colorize():
bold_green = _ANSIColors.BOLD_GREEN
bold_red = _ANSIColors.BOLD_RED
green = _ANSIColors.GREEN
red = _ANSIColors.RED
reset = _ANSIColors.RESET
yellow = _ANSIColors.YELLOW
else:
bold_green = ""
bold_red = ""
green = ""
red = ""
reset = ""
yellow = ""
ansi = _colorize.get_colors()
bold_green = ansi.BOLD_GREEN
bold_red = ansi.BOLD_RED
green = ansi.GREEN
red = ansi.RED
reset = ansi.RESET
yellow = ansi.YELLOW
if verbose:
if notests:

View File

@ -2579,20 +2579,21 @@ def copy_python_src_ignore(path, names):
}
return ignored
def force_not_colorized(func):
"""Force the terminal not to be colorized."""
@functools.wraps(func)
def wrapper(*args, **kwargs):
import traceback
original_fn = traceback._can_colorize
import _colorize
original_fn = _colorize.can_colorize
variables = {"PYTHON_COLORS": None, "FORCE_COLOR": None}
try:
for key in variables:
variables[key] = os.environ.pop(key, None)
traceback._can_colorize = lambda: False
_colorize.can_colorize = lambda: False
return func(*args, **kwargs)
finally:
traceback._can_colorize = original_fn
_colorize.can_colorize = original_fn
for key, value in variables.items():
if value is not None:
os.environ[key] = value

View File

@ -0,0 +1,59 @@
import contextlib
import sys
import unittest
import unittest.mock
import _colorize
from test.support import force_not_colorized
ORIGINAL_CAN_COLORIZE = _colorize.can_colorize
def setUpModule():
_colorize.can_colorize = lambda: False
def tearDownModule():
_colorize.can_colorize = ORIGINAL_CAN_COLORIZE
class TestColorizeFunction(unittest.TestCase):
@force_not_colorized
def test_colorized_detection_checks_for_environment_variables(self):
if sys.platform == "win32":
virtual_patching = unittest.mock.patch("nt._supports_virtual_terminal",
return_value=True)
else:
virtual_patching = contextlib.nullcontext()
with virtual_patching:
flags = unittest.mock.MagicMock(ignore_environment=False)
with (unittest.mock.patch("os.isatty") as isatty_mock,
unittest.mock.patch("sys.flags", flags),
unittest.mock.patch("_colorize.can_colorize", ORIGINAL_CAN_COLORIZE)):
isatty_mock.return_value = True
with unittest.mock.patch("os.environ", {'TERM': 'dumb'}):
self.assertEqual(_colorize.can_colorize(), False)
with unittest.mock.patch("os.environ", {'PYTHON_COLORS': '1'}):
self.assertEqual(_colorize.can_colorize(), True)
with unittest.mock.patch("os.environ", {'PYTHON_COLORS': '0'}):
self.assertEqual(_colorize.can_colorize(), False)
with unittest.mock.patch("os.environ", {'NO_COLOR': '1'}):
self.assertEqual(_colorize.can_colorize(), False)
with unittest.mock.patch("os.environ",
{'NO_COLOR': '1', "PYTHON_COLORS": '1'}):
self.assertEqual(_colorize.can_colorize(), True)
with unittest.mock.patch("os.environ", {'FORCE_COLOR': '1'}):
self.assertEqual(_colorize.can_colorize(), True)
with unittest.mock.patch("os.environ",
{'FORCE_COLOR': '1', 'NO_COLOR': '1'}):
self.assertEqual(_colorize.can_colorize(), False)
with unittest.mock.patch("os.environ",
{'FORCE_COLOR': '1', "PYTHON_COLORS": '0'}):
self.assertEqual(_colorize.can_colorize(), False)
isatty_mock.return_value = False
with unittest.mock.patch("os.environ", {}):
self.assertEqual(_colorize.can_colorize(), False)
if __name__ == "__main__":
unittest.main()

View File

@ -16,7 +16,7 @@ import unittest
import tempfile
import types
import contextlib
import traceback
import _colorize
def doctest_skip_if(condition):
@ -893,8 +893,8 @@ Unit tests for the `DocTestRunner` class.
DocTestRunner is used to run DocTest test cases, and to accumulate
statistics. Here's a simple DocTest case we can use:
>>> save_colorize = traceback._COLORIZE
>>> traceback._COLORIZE = False
>>> save_colorize = _colorize.COLORIZE
>>> _colorize.COLORIZE = False
>>> def f(x):
... '''
@ -951,7 +951,7 @@ the failure and proceeds to the next example:
ok
TestResults(failed=1, attempted=3)
>>> traceback._COLORIZE = save_colorize
>>> _colorize.COLORIZE = save_colorize
"""
def verbose_flag(): r"""
The `verbose` flag makes the test runner generate more detailed
@ -1027,8 +1027,8 @@ An expected exception is specified with a traceback message. The
lines between the first line and the type/value may be omitted or
replaced with any other string:
>>> save_colorize = traceback._COLORIZE
>>> traceback._COLORIZE = False
>>> save_colorize = _colorize.COLORIZE
>>> _colorize.COLORIZE = False
>>> def f(x):
... '''
@ -1261,7 +1261,7 @@ unexpected exception:
ZeroDivisionError: integer division or modulo by zero
TestResults(failed=1, attempted=1)
>>> traceback._COLORIZE = save_colorize
>>> _colorize.COLORIZE = save_colorize
"""
def displayhook(): r"""
Test that changing sys.displayhook doesn't matter for doctest.
@ -1303,8 +1303,8 @@ together).
The DONT_ACCEPT_TRUE_FOR_1 flag disables matches between True/False
and 1/0:
>>> save_colorize = traceback._COLORIZE
>>> traceback._COLORIZE = False
>>> save_colorize = _colorize.COLORIZE
>>> _colorize.COLORIZE = False
>>> def f(x):
... '>>> True\n1\n'
@ -1725,7 +1725,7 @@ more than one flag value. Here we verify that's fixed:
Clean up.
>>> del doctest.OPTIONFLAGS_BY_NAME[unlikely]
>>> traceback._COLORIZE = save_colorize
>>> _colorize.COLORIZE = save_colorize
"""
@ -1736,8 +1736,8 @@ Option directives can be used to turn option flags on or off for a
single example. To turn an option on for an example, follow that
example with a comment of the form ``# doctest: +OPTION``:
>>> save_colorize = traceback._COLORIZE
>>> traceback._COLORIZE = False
>>> save_colorize = _colorize.COLORIZE
>>> _colorize.COLORIZE = False
>>> def f(x): r'''
... >>> print(list(range(10))) # should fail: no ellipsis
@ -1947,7 +1947,7 @@ source:
Traceback (most recent call last):
ValueError: line 0 of the doctest for s has an option directive on a line with no example: '# doctest: +ELLIPSIS'
>>> traceback._COLORIZE = save_colorize
>>> _colorize.COLORIZE = save_colorize
"""
def test_testsource(): r"""
@ -2031,8 +2031,8 @@ if not hasattr(sys, 'gettrace') or not sys.gettrace():
with a version that restores stdout. This is necessary for you to
see debugger output.
>>> save_colorize = traceback._COLORIZE
>>> traceback._COLORIZE = False
>>> save_colorize = _colorize.COLORIZE
>>> _colorize.COLORIZE = False
>>> doc = '''
... >>> x = 42
@ -2157,7 +2157,7 @@ if not hasattr(sys, 'gettrace') or not sys.gettrace():
9
TestResults(failed=1, attempted=3)
>>> traceback._COLORIZE = save_colorize
>>> _colorize.COLORIZE = save_colorize
"""
def test_pdb_set_trace_nested():
@ -2694,8 +2694,8 @@ calling module. The return value is (#failures, #tests).
We don't want color or `-v` in sys.argv for these tests.
>>> save_colorize = traceback._COLORIZE
>>> traceback._COLORIZE = False
>>> save_colorize = _colorize.COLORIZE
>>> _colorize.COLORIZE = False
>>> save_argv = sys.argv
>>> if '-v' in sys.argv:
@ -2863,7 +2863,7 @@ Test the verbose output:
TestResults(failed=0, attempted=2)
>>> doctest.master = None # Reset master.
>>> sys.argv = save_argv
>>> traceback._COLORIZE = save_colorize
>>> _colorize.COLORIZE = save_colorize
"""
class TestImporter(importlib.abc.MetaPathFinder, importlib.abc.ResourceLoader):
@ -3001,8 +3001,8 @@ if supports_unicode:
def test_unicode(): """
Check doctest with a non-ascii filename:
>>> save_colorize = traceback._COLORIZE
>>> traceback._COLORIZE = False
>>> save_colorize = _colorize.COLORIZE
>>> _colorize.COLORIZE = False
>>> doc = '''
... >>> raise Exception('clé')
@ -3030,7 +3030,7 @@ Check doctest with a non-ascii filename:
Exception: clé
TestResults(failed=1, attempted=1)
>>> traceback._COLORIZE = save_colorize
>>> _colorize.COLORIZE = save_colorize
"""
@ -3325,8 +3325,8 @@ def test_run_doctestsuite_multiple_times():
def test_exception_with_note(note):
"""
>>> save_colorize = traceback._COLORIZE
>>> traceback._COLORIZE = False
>>> save_colorize = _colorize.COLORIZE
>>> _colorize.COLORIZE = False
>>> test_exception_with_note('Note')
Traceback (most recent call last):
@ -3378,7 +3378,7 @@ def test_exception_with_note(note):
note
TestResults(failed=1, attempted=...)
>>> traceback._COLORIZE = save_colorize
>>> _colorize.COLORIZE = save_colorize
"""
exc = ValueError('Text')
exc.add_note(note)
@ -3459,8 +3459,8 @@ def test_syntax_error_subclass_from_stdlib():
def test_syntax_error_with_incorrect_expected_note():
"""
>>> save_colorize = traceback._COLORIZE
>>> traceback._COLORIZE = False
>>> save_colorize = _colorize.COLORIZE
>>> _colorize.COLORIZE = False
>>> def f(x):
... r'''
@ -3491,7 +3491,7 @@ def test_syntax_error_with_incorrect_expected_note():
note2
TestResults(failed=1, attempted=...)
>>> traceback._COLORIZE = save_colorize
>>> _colorize.COLORIZE = save_colorize
"""

View File

@ -26,9 +26,9 @@ from test.support import force_not_colorized
import json
import textwrap
import traceback
import contextlib
from functools import partial
from pathlib import Path
import _colorize
MODULE_PREFIX = f'{__name__}.' if __name__ == '__main__' else ''
@ -40,25 +40,18 @@ test_tb = namedtuple('tb', ['tb_frame', 'tb_lineno', 'tb_next', 'tb_lasti'])
LEVENSHTEIN_DATA_FILE = Path(__file__).parent / 'levenshtein_examples.json'
ORIGINAL_CAN_COLORIZE = traceback._can_colorize
def setUpModule():
traceback._can_colorize = lambda: False
def tearDownModule():
traceback._can_colorize = ORIGINAL_CAN_COLORIZE
class TracebackCases(unittest.TestCase):
# For now, a very minimal set of tests. I want to be sure that
# formatting of SyntaxErrors works based on changes for 2.1.
def setUp(self):
super().setUp()
self.colorize = traceback._COLORIZE
traceback._COLORIZE = False
self.colorize = _colorize.COLORIZE
_colorize.COLORIZE = False
def tearDown(self):
super().tearDown()
traceback._COLORIZE = self.colorize
_colorize.COLORIZE = self.colorize
def get_exception_format(self, func, exc):
try:
@ -4478,9 +4471,9 @@ class TestColorizedTraceback(unittest.TestCase):
e, capture_locals=True
)
lines = "".join(exc.format(colorize=True))
red = traceback._ANSIColors.RED
boldr = traceback._ANSIColors.BOLD_RED
reset = traceback._ANSIColors.RESET
red = _colorize.ANSIColors.RED
boldr = _colorize.ANSIColors.BOLD_RED
reset = _colorize.ANSIColors.RESET
self.assertIn("y = " + red + "x['a']['b']" + reset + boldr + "['c']" + reset, lines)
self.assertIn("return " + red + "(lambda *args: foo(*args))" + reset + boldr + "(1,2,3,4)" + reset, lines)
self.assertIn("return (lambda *args: " + red + "foo" + reset + boldr + "(*args)" + reset + ")(1,2,3,4)", lines)
@ -4496,11 +4489,11 @@ class TestColorizedTraceback(unittest.TestCase):
e, capture_locals=True
)
actual = "".join(exc.format(colorize=True))
red = traceback._ANSIColors.RED
magenta = traceback._ANSIColors.MAGENTA
boldm = traceback._ANSIColors.BOLD_MAGENTA
boldr = traceback._ANSIColors.BOLD_RED
reset = traceback._ANSIColors.RESET
red = _colorize.ANSIColors.RED
magenta = _colorize.ANSIColors.MAGENTA
boldm = _colorize.ANSIColors.BOLD_MAGENTA
boldr = _colorize.ANSIColors.BOLD_RED
reset = _colorize.ANSIColors.RESET
expected = "".join([
f' File {magenta}"<string>"{reset}, line {magenta}1{reset}\n',
f' a {boldr}${reset} b\n',
@ -4519,15 +4512,15 @@ class TestColorizedTraceback(unittest.TestCase):
self.fail("No exception thrown.")
except Exception as e:
with captured_output("stderr") as tbstderr:
with unittest.mock.patch('traceback._can_colorize', return_value=True):
with unittest.mock.patch('_colorize.can_colorize', return_value=True):
exception_print(e)
actual = tbstderr.getvalue().splitlines()
red = traceback._ANSIColors.RED
boldr = traceback._ANSIColors.BOLD_RED
magenta = traceback._ANSIColors.MAGENTA
boldm = traceback._ANSIColors.BOLD_MAGENTA
reset = traceback._ANSIColors.RESET
red = _colorize.ANSIColors.RED
boldr = _colorize.ANSIColors.BOLD_RED
magenta = _colorize.ANSIColors.MAGENTA
boldm = _colorize.ANSIColors.BOLD_MAGENTA
reset = _colorize.ANSIColors.RESET
lno_foo = foo.__code__.co_firstlineno
expected = ['Traceback (most recent call last):',
f' File {magenta}"{__file__}"{reset}, '
@ -4541,38 +4534,6 @@ class TestColorizedTraceback(unittest.TestCase):
f'{boldm}ZeroDivisionError{reset}: {magenta}division by zero{reset}']
self.assertEqual(actual, expected)
@force_not_colorized
def test_colorized_detection_checks_for_environment_variables(self):
if sys.platform == "win32":
virtual_patching = unittest.mock.patch("nt._supports_virtual_terminal", return_value=True)
else:
virtual_patching = contextlib.nullcontext()
with virtual_patching:
flags = unittest.mock.MagicMock(ignore_environment=False)
with (unittest.mock.patch("os.isatty") as isatty_mock,
unittest.mock.patch("sys.flags", flags),
unittest.mock.patch("traceback._can_colorize", ORIGINAL_CAN_COLORIZE)):
isatty_mock.return_value = True
with unittest.mock.patch("os.environ", {'TERM': 'dumb'}):
self.assertEqual(traceback._can_colorize(), False)
with unittest.mock.patch("os.environ", {'PYTHON_COLORS': '1'}):
self.assertEqual(traceback._can_colorize(), True)
with unittest.mock.patch("os.environ", {'PYTHON_COLORS': '0'}):
self.assertEqual(traceback._can_colorize(), False)
with unittest.mock.patch("os.environ", {'NO_COLOR': '1'}):
self.assertEqual(traceback._can_colorize(), False)
with unittest.mock.patch("os.environ", {'NO_COLOR': '1', "PYTHON_COLORS": '1'}):
self.assertEqual(traceback._can_colorize(), True)
with unittest.mock.patch("os.environ", {'FORCE_COLOR': '1'}):
self.assertEqual(traceback._can_colorize(), True)
with unittest.mock.patch("os.environ", {'FORCE_COLOR': '1', 'NO_COLOR': '1'}):
self.assertEqual(traceback._can_colorize(), False)
with unittest.mock.patch("os.environ", {'FORCE_COLOR': '1', "PYTHON_COLORS": '0'}):
self.assertEqual(traceback._can_colorize(), False)
isatty_mock.return_value = False
with unittest.mock.patch("os.environ", {}):
self.assertEqual(traceback._can_colorize(), False)
if __name__ == "__main__":
unittest.main()

View File

@ -1,7 +1,5 @@
"""Extract, format and print information about Python stack traces."""
import os
import io
import collections.abc
import itertools
import linecache
@ -9,6 +7,8 @@ import sys
import textwrap
import warnings
from contextlib import suppress
import _colorize
from _colorize import ANSIColors
__all__ = ['extract_stack', 'extract_tb', 'format_exception',
'format_exception_only', 'format_list', 'format_stack',
@ -21,7 +21,6 @@ __all__ = ['extract_stack', 'extract_tb', 'format_exception',
# Formatting and printing lists of traceback lines.
#
_COLORIZE = True
def print_list(extracted_list, file=None):
"""Print the list of tuples as returned by extract_tb() or
@ -133,41 +132,10 @@ def print_exception(exc, /, value=_sentinel, tb=_sentinel, limit=None, \
BUILTIN_EXCEPTION_LIMIT = object()
def _can_colorize():
if sys.platform == "win32":
try:
import nt
if not nt._supports_virtual_terminal():
return False
except (ImportError, AttributeError):
return False
if not sys.flags.ignore_environment:
if os.environ.get("PYTHON_COLORS") == "0":
return False
if os.environ.get("PYTHON_COLORS") == "1":
return True
if "NO_COLOR" in os.environ:
return False
if not _COLORIZE:
return False
if not sys.flags.ignore_environment:
if "FORCE_COLOR" in os.environ:
return True
if os.environ.get("TERM") == "dumb":
return False
if not hasattr(sys.stderr, "fileno"):
return False
try:
return os.isatty(sys.stderr.fileno())
except io.UnsupportedOperation:
return sys.stderr.isatty()
def _print_exception_bltin(exc, /):
file = sys.stderr if sys.stderr is not None else sys.__stderr__
colorize = _can_colorize()
colorize = _colorize.can_colorize()
return print_exception(exc, limit=BUILTIN_EXCEPTION_LIMIT, file=file, colorize=colorize)
@ -214,9 +182,9 @@ def _format_final_exc_line(etype, value, *, insert_final_newline=True, colorize=
end_char = "\n" if insert_final_newline else ""
if colorize:
if value is None or not valuestr:
line = f"{_ANSIColors.BOLD_MAGENTA}{etype}{_ANSIColors.RESET}{end_char}"
line = f"{ANSIColors.BOLD_MAGENTA}{etype}{ANSIColors.RESET}{end_char}"
else:
line = f"{_ANSIColors.BOLD_MAGENTA}{etype}{_ANSIColors.RESET}: {_ANSIColors.MAGENTA}{valuestr}{_ANSIColors.RESET}{end_char}"
line = f"{ANSIColors.BOLD_MAGENTA}{etype}{ANSIColors.RESET}: {ANSIColors.MAGENTA}{valuestr}{ANSIColors.RESET}{end_char}"
else:
if value is None or not valuestr:
line = f"{etype}{end_char}"
@ -224,6 +192,7 @@ def _format_final_exc_line(etype, value, *, insert_final_newline=True, colorize=
line = f"{etype}: {valuestr}{end_char}"
return line
def _safe_string(value, what, func=str):
try:
return func(value)
@ -449,17 +418,6 @@ def _get_code_position(code, instruction_index):
_RECURSIVE_CUTOFF = 3 # Also hardcoded in traceback.c.
class _ANSIColors:
RED = '\x1b[31m'
BOLD_RED = '\x1b[1;31m'
MAGENTA = '\x1b[35m'
BOLD_MAGENTA = '\x1b[1;35m'
GREEN = "\x1b[32m"
BOLD_GREEN = "\x1b[1;32m"
GREY = '\x1b[90m'
RESET = '\x1b[0m'
YELLOW = "\x1b[33m"
class StackSummary(list):
"""A list of FrameSummary objects, representing a stack of frames."""
@ -564,15 +522,15 @@ class StackSummary(list):
filename = "<stdin>"
if colorize:
row.append(' File {}"{}"{}, line {}{}{}, in {}{}{}\n'.format(
_ANSIColors.MAGENTA,
ANSIColors.MAGENTA,
filename,
_ANSIColors.RESET,
_ANSIColors.MAGENTA,
ANSIColors.RESET,
ANSIColors.MAGENTA,
frame_summary.lineno,
_ANSIColors.RESET,
_ANSIColors.MAGENTA,
ANSIColors.RESET,
ANSIColors.MAGENTA,
frame_summary.name,
_ANSIColors.RESET,
ANSIColors.RESET,
)
)
else:
@ -696,11 +654,11 @@ class StackSummary(list):
for color, group in itertools.groupby(itertools.zip_longest(line, carets, fillvalue=""), key=lambda x: x[1]):
caret_group = list(group)
if color == "^":
colorized_line_parts.append(_ANSIColors.BOLD_RED + "".join(char for char, _ in caret_group) + _ANSIColors.RESET)
colorized_carets_parts.append(_ANSIColors.BOLD_RED + "".join(caret for _, caret in caret_group) + _ANSIColors.RESET)
colorized_line_parts.append(ANSIColors.BOLD_RED + "".join(char for char, _ in caret_group) + ANSIColors.RESET)
colorized_carets_parts.append(ANSIColors.BOLD_RED + "".join(caret for _, caret in caret_group) + ANSIColors.RESET)
elif color == "~":
colorized_line_parts.append(_ANSIColors.RED + "".join(char for char, _ in caret_group) + _ANSIColors.RESET)
colorized_carets_parts.append(_ANSIColors.RED + "".join(caret for _, caret in caret_group) + _ANSIColors.RESET)
colorized_line_parts.append(ANSIColors.RED + "".join(char for char, _ in caret_group) + ANSIColors.RESET)
colorized_carets_parts.append(ANSIColors.RED + "".join(caret for _, caret in caret_group) + ANSIColors.RESET)
else:
colorized_line_parts.append("".join(char for char, _ in caret_group))
colorized_carets_parts.append("".join(caret for _, caret in caret_group))
@ -1307,12 +1265,12 @@ class TracebackException:
if self.lineno is not None:
if colorize:
yield ' File {}"{}"{}, line {}{}{}\n'.format(
_ANSIColors.MAGENTA,
ANSIColors.MAGENTA,
self.filename or "<string>",
_ANSIColors.RESET,
_ANSIColors.MAGENTA,
ANSIColors.RESET,
ANSIColors.MAGENTA,
self.lineno,
_ANSIColors.RESET,
ANSIColors.RESET,
)
else:
yield ' File "{}", line {}\n'.format(
@ -1352,11 +1310,11 @@ class TracebackException:
# colorize from colno to end_colno
ltext = (
ltext[:colno] +
_ANSIColors.BOLD_RED + ltext[colno:end_colno] + _ANSIColors.RESET +
ANSIColors.BOLD_RED + ltext[colno:end_colno] + ANSIColors.RESET +
ltext[end_colno:]
)
start_color = _ANSIColors.BOLD_RED
end_color = _ANSIColors.RESET
start_color = ANSIColors.BOLD_RED
end_color = ANSIColors.RESET
yield ' {}\n'.format(ltext)
yield ' {}{}{}{}\n'.format(
"".join(caretspace),
@ -1369,12 +1327,12 @@ class TracebackException:
msg = self.msg or "<no detail available>"
if colorize:
yield "{}{}{}: {}{}{}{}\n".format(
_ANSIColors.BOLD_MAGENTA,
ANSIColors.BOLD_MAGENTA,
stype,
_ANSIColors.RESET,
_ANSIColors.MAGENTA,
ANSIColors.RESET,
ANSIColors.MAGENTA,
msg,
_ANSIColors.RESET,
ANSIColors.RESET,
filename_suffix)
else:
yield "{}: {}{}\n".format(stype, msg, filename_suffix)

View File

@ -20,6 +20,7 @@ static const char* _Py_stdlib_module_names[] = {
"_codecs_tw",
"_collections",
"_collections_abc",
"_colorize",
"_compat_pickle",
"_compression",
"_contextvars",