diff --git a/Lib/_colorize.py b/Lib/_colorize.py deleted file mode 100644 index 4590062c30b3575..000000000000000 --- a/Lib/_colorize.py +++ /dev/null @@ -1,45 +0,0 @@ -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" - - -def can_colorize(): - if sys.platform == "win32": - try: - import nt - - if not nt._supports_virtual_terminal(): - return False - except (ImportError, AttributeError): - return False - - 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 "FORCE_COLOR" in os.environ: - return True - if os.environ.get("TERM") == "dumb": - return False - try: - return os.isatty(sys.stderr.fileno()) - except io.UnsupportedOperation: - return sys.stderr.isatty() diff --git a/Lib/doctest.py b/Lib/doctest.py index e003e30786ed93c..a3b42fdfb12254d 100644 --- a/Lib/doctest.py +++ b/Lib/doctest.py @@ -104,8 +104,7 @@ def _test(): import unittest from io import StringIO, IncrementalNewlineDecoder from collections import namedtuple -import _colorize # Used in doctests -from _colorize import ANSIColors, can_colorize +from traceback import _ANSIColors, _can_colorize class TestResults(namedtuple('TestResults', 'failed attempted')): @@ -1181,8 +1180,8 @@ class DocTestRunner: The `run` method is used to process a single DocTest case. It returns a TestResults instance. - >>> save_colorize = _colorize.COLORIZE - >>> _colorize.COLORIZE = False + >>> save_colorize = traceback._COLORIZE + >>> traceback._COLORIZE = False >>> tests = DocTestFinder().find(_TestClass) >>> runner = DocTestRunner(verbose=False) @@ -1235,7 +1234,7 @@ class DocTestRunner: overriding the methods `report_start`, `report_success`, `report_unexpected_exception`, and `report_failure`. - >>> _colorize.COLORIZE = save_colorize + >>> traceback._COLORIZE = save_colorize """ # This divider string is used to separate failure messages, and to # separate sections of the summary. @@ -1315,7 +1314,7 @@ def report_unexpected_exception(self, out, test, example, exc_info): 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: @@ -1602,13 +1601,13 @@ def summarize(self, verbose=None): 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 + 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 = "" diff --git a/Lib/test/test__colorize.py b/Lib/test/test__colorize.py deleted file mode 100644 index 4415459f0254ae5..000000000000000 --- a/Lib/test/test__colorize.py +++ /dev/null @@ -1,40 +0,0 @@ -import sys -import unittest -import unittest.mock -import _colorize - - -class TestColorizeFunction(unittest.TestCase): - def test_colorized_detection_checks_for_environment_variables(self): - env_vars_expected = [ - ({'TERM': 'dumb'}, False), - ({'PYTHON_COLORS': '1'}, True), - ({'PYTHON_COLORS': '0'}, False), - ({'NO_COLOR': '1'}, False), - ({'NO_COLOR': '1', "PYTHON_COLORS": '1'}, True), - ({'FORCE_COLOR': '1'}, True), - ({'FORCE_COLOR': '1', 'NO_COLOR': '1'}, False), - ({'FORCE_COLOR': '1', "PYTHON_COLORS": '0'}, False), - ] - - if sys.platform == "win32": - self.enterContext( - unittest.mock.patch( - "nt._supports_virtual_terminal", return_value=True - ) - ) - - isatty_mock = self.enterContext(unittest.mock.patch("os.isatty")) - isatty_mock.return_value = True - - for env_vars, expected in env_vars_expected: - with self.subTest(env_vars=env_vars, expected_color=expected): - with unittest.mock.patch("os.environ", env_vars): - self.assertEqual(_colorize.can_colorize(), expected) - - isatty_mock.return_value = False - self.assertEqual(_colorize.can_colorize(), False) - - -if __name__ == "__main__": - unittest.main() diff --git a/Lib/test/test_doctest/test_doctest.py b/Lib/test/test_doctest/test_doctest.py index 6da6999cac7c0cf..2ad16558d5574c9 100644 --- a/Lib/test/test_doctest/test_doctest.py +++ b/Lib/test/test_doctest/test_doctest.py @@ -16,7 +16,7 @@ import tempfile import types import contextlib -import _colorize # used in doctests +import traceback def doctest_skip_if(condition): @@ -471,7 +471,7 @@ def basics(): r""" >>> tests = finder.find(sample_func) >>> print(tests) # doctest: +ELLIPSIS - [] + [] The exact name depends on how test_doctest was invoked, so allow for leading path components. @@ -893,8 +893,8 @@ def basics(): r""" DocTestRunner is used to run DocTest test cases, and to accumulate statistics. Here's a simple DocTest case we can use: - >>> save_colorize = _colorize.COLORIZE - >>> _colorize.COLORIZE = False + >>> save_colorize = traceback._COLORIZE + >>> traceback._COLORIZE = False >>> def f(x): ... ''' @@ -951,7 +951,7 @@ def basics(): r""" ok TestResults(failed=1, attempted=3) - >>> _colorize.COLORIZE = save_colorize + >>> traceback._COLORIZE = save_colorize """ def verbose_flag(): r""" The `verbose` flag makes the test runner generate more detailed @@ -1027,8 +1027,8 @@ def exceptions(): r""" lines between the first line and the type/value may be omitted or replaced with any other string: - >>> save_colorize = _colorize.COLORIZE - >>> _colorize.COLORIZE = False + >>> save_colorize = traceback._COLORIZE + >>> traceback._COLORIZE = False >>> def f(x): ... ''' @@ -1261,7 +1261,7 @@ def exceptions(): r""" ZeroDivisionError: integer division or modulo by zero TestResults(failed=1, attempted=1) - >>> _colorize.COLORIZE = save_colorize + >>> traceback._COLORIZE = save_colorize """ def displayhook(): r""" Test that changing sys.displayhook doesn't matter for doctest. @@ -1303,8 +1303,8 @@ def optionflags(): r""" The DONT_ACCEPT_TRUE_FOR_1 flag disables matches between True/False and 1/0: - >>> save_colorize = _colorize.COLORIZE - >>> _colorize.COLORIZE = False + >>> save_colorize = traceback._COLORIZE + >>> traceback._COLORIZE = False >>> def f(x): ... '>>> True\n1\n' @@ -1725,7 +1725,7 @@ def optionflags(): r""" Clean up. >>> del doctest.OPTIONFLAGS_BY_NAME[unlikely] - >>> _colorize.COLORIZE = save_colorize + >>> traceback._COLORIZE = save_colorize """ @@ -1736,8 +1736,8 @@ def option_directives(): r""" single example. To turn an option on for an example, follow that example with a comment of the form ``# doctest: +OPTION``: - >>> save_colorize = _colorize.COLORIZE - >>> _colorize.COLORIZE = False + >>> save_colorize = traceback._COLORIZE + >>> traceback._COLORIZE = False >>> def f(x): r''' ... >>> print(list(range(10))) # should fail: no ellipsis @@ -1947,7 +1947,7 @@ def option_directives(): r""" 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' - >>> _colorize.COLORIZE = save_colorize + >>> traceback._COLORIZE = save_colorize """ def test_testsource(): r""" @@ -2031,8 +2031,8 @@ def test_pdb_set_trace(): with a version that restores stdout. This is necessary for you to see debugger output. - >>> save_colorize = _colorize.COLORIZE - >>> _colorize.COLORIZE = False + >>> save_colorize = traceback._COLORIZE + >>> traceback._COLORIZE = False >>> doc = ''' ... >>> x = 42 @@ -2157,7 +2157,7 @@ def test_pdb_set_trace(): 9 TestResults(failed=1, attempted=3) - >>> _colorize.COLORIZE = save_colorize + >>> traceback._COLORIZE = save_colorize """ def test_pdb_set_trace_nested(): @@ -2679,8 +2679,8 @@ def test_testfile(): r""" We don't want color or `-v` in sys.argv for these tests. - >>> save_colorize = _colorize.COLORIZE - >>> _colorize.COLORIZE = False + >>> save_colorize = traceback._COLORIZE + >>> traceback._COLORIZE = False >>> save_argv = sys.argv >>> if '-v' in sys.argv: @@ -2848,7 +2848,7 @@ def test_testfile(): r""" TestResults(failed=0, attempted=2) >>> doctest.master = None # Reset master. >>> sys.argv = save_argv - >>> _colorize.COLORIZE = save_colorize + >>> traceback._COLORIZE = save_colorize """ class TestImporter(importlib.abc.MetaPathFinder, importlib.abc.ResourceLoader): @@ -2986,8 +2986,8 @@ def test_testmod(): r""" def test_unicode(): """ Check doctest with a non-ascii filename: - >>> save_colorize = _colorize.COLORIZE - >>> _colorize.COLORIZE = False + >>> save_colorize = traceback._COLORIZE + >>> traceback._COLORIZE = False >>> doc = ''' ... >>> raise Exception('clé') @@ -3015,7 +3015,7 @@ def test_unicode(): """ Exception: clé TestResults(failed=1, attempted=1) - >>> _colorize.COLORIZE = save_colorize + >>> traceback._COLORIZE = save_colorize """ @@ -3310,8 +3310,8 @@ def test_run_doctestsuite_multiple_times(): def test_exception_with_note(note): """ - >>> save_colorize = _colorize.COLORIZE - >>> _colorize.COLORIZE = False + >>> save_colorize = traceback._COLORIZE + >>> traceback._COLORIZE = False >>> test_exception_with_note('Note') Traceback (most recent call last): @@ -3363,7 +3363,7 @@ def test_exception_with_note(note): note TestResults(failed=1, attempted=...) - >>> _colorize.COLORIZE = save_colorize + >>> traceback._COLORIZE = save_colorize """ exc = ValueError('Text') exc.add_note(note) @@ -3444,8 +3444,8 @@ def test_syntax_error_subclass_from_stdlib(): def test_syntax_error_with_incorrect_expected_note(): """ - >>> save_colorize = _colorize.COLORIZE - >>> _colorize.COLORIZE = False + >>> save_colorize = traceback._COLORIZE + >>> traceback._COLORIZE = False >>> def f(x): ... r''' @@ -3476,7 +3476,7 @@ def test_syntax_error_with_incorrect_expected_note(): note2 TestResults(failed=1, attempted=...) - >>> _colorize.COLORIZE = save_colorize + >>> traceback._COLORIZE = save_colorize """ diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py index 2e174a7184f2bc7..dd9b1850adf0860 100644 --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -25,9 +25,9 @@ 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 '' @@ -45,12 +45,12 @@ class TracebackCases(unittest.TestCase): # formatting of SyntaxErrors works based on changes for 2.1. def setUp(self): super().setUp() - self.colorize = _colorize.COLORIZE - _colorize.COLORIZE = False + self.colorize = traceback._COLORIZE + traceback._COLORIZE = False def tearDown(self): super().tearDown() - _colorize.COLORIZE = self.colorize + traceback._COLORIZE = self.colorize def get_exception_format(self, func, exc): try: @@ -4291,9 +4291,9 @@ def bar(): e, capture_locals=True ) lines = "".join(exc.format(colorize=True)) - red = _colorize.ANSIColors.RED - boldr = _colorize.ANSIColors.BOLD_RED - reset = _colorize.ANSIColors.RESET + red = traceback._ANSIColors.RED + boldr = traceback._ANSIColors.BOLD_RED + reset = traceback._ANSIColors.RESET self.assertIn("y = " + red + "x['a']['b']" + reset + boldr + "['c']" + reset, lines) self.assertIn("return " + red + "foo" + reset + boldr + "(1,2,3,4)" + reset, lines) self.assertIn("return " + red + "baz" + reset + boldr + "(1," + reset, lines) @@ -4309,11 +4309,11 @@ def test_colorized_syntax_error(self): e, capture_locals=True ) actual = "".join(exc.format(colorize=True)) - red = _colorize.ANSIColors.RED - magenta = _colorize.ANSIColors.MAGENTA - boldm = _colorize.ANSIColors.BOLD_MAGENTA - boldr = _colorize.ANSIColors.BOLD_RED - reset = _colorize.ANSIColors.RESET + red = traceback._ANSIColors.RED + magenta = traceback._ANSIColors.MAGENTA + boldm = traceback._ANSIColors.BOLD_MAGENTA + boldr = traceback._ANSIColors.BOLD_RED + reset = traceback._ANSIColors.RESET expected = "".join([ f' File {magenta}""{reset}, line {magenta}1{reset}\n', f' a {boldr}${reset} b\n', @@ -4332,15 +4332,15 @@ def foo(): self.fail("No exception thrown.") except Exception as e: with captured_output("stderr") as tbstderr: - with unittest.mock.patch('_colorize.can_colorize', return_value=True): + with unittest.mock.patch('traceback._can_colorize', return_value=True): exception_print(e) actual = tbstderr.getvalue().splitlines() - red = _colorize.ANSIColors.RED - boldr = _colorize.ANSIColors.BOLD_RED - magenta = _colorize.ANSIColors.MAGENTA - boldm = _colorize.ANSIColors.BOLD_MAGENTA - reset = _colorize.ANSIColors.RESET + red = traceback._ANSIColors.RED + boldr = traceback._ANSIColors.BOLD_RED + magenta = traceback._ANSIColors.MAGENTA + boldm = traceback._ANSIColors.BOLD_MAGENTA + reset = traceback._ANSIColors.RESET lno_foo = foo.__code__.co_firstlineno expected = ['Traceback (most recent call last):', f' File {magenta}"{__file__}"{reset}, ' @@ -4354,6 +4354,32 @@ def foo(): f'{boldm}ZeroDivisionError{reset}: {magenta}division by zero{reset}'] self.assertEqual(actual, expected) + 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: + with unittest.mock.patch("os.isatty") as isatty_mock: + 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 + self.assertEqual(traceback._can_colorize(), False) if __name__ == "__main__": unittest.main() diff --git a/Lib/traceback.py b/Lib/traceback.py index 1922fd8caee762d..054def57c214827 100644 --- a/Lib/traceback.py +++ b/Lib/traceback.py @@ -1,5 +1,7 @@ """Extract, format and print information about Python stack traces.""" +import os +import io import collections.abc import itertools import linecache @@ -7,8 +9,6 @@ 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', @@ -17,11 +17,12 @@ 'FrameSummary', 'StackSummary', 'TracebackException', 'walk_stack', 'walk_tb'] - # # 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 extract_stack() as a formatted stack trace to the given file.""" @@ -132,10 +133,35 @@ 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 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 "FORCE_COLOR" in os.environ: + return True + if os.environ.get("TERM") == "dumb": + 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 = _colorize.can_colorize() + colorize = _can_colorize() return print_exception(exc, limit=BUILTIN_EXCEPTION_LIMIT, file=file, colorize=colorize) @@ -182,9 +208,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}" @@ -417,6 +443,17 @@ 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.""" @@ -521,15 +558,15 @@ def format_frame_summary(self, frame_summary, **kwargs): filename = "" 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: @@ -656,11 +693,11 @@ def output_line(lineno): 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)) @@ -1236,12 +1273,12 @@ def _format_syntax_error(self, stype, **kwargs): if self.lineno is not None: if colorize: yield ' File {}"{}"{}, line {}{}{}\n'.format( - ANSIColors.MAGENTA, + _ANSIColors.MAGENTA, self.filename or "", - ANSIColors.RESET, - ANSIColors.MAGENTA, + _ANSIColors.RESET, + _ANSIColors.MAGENTA, self.lineno, - ANSIColors.RESET, + _ANSIColors.RESET, ) else: yield ' File "{}", line {}\n'.format( @@ -1281,11 +1318,11 @@ def _format_syntax_error(self, stype, **kwargs): # 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), @@ -1298,12 +1335,12 @@ def _format_syntax_error(self, stype, **kwargs): msg = self.msg or "" 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) diff --git a/Python/stdlib_module_names.h b/Python/stdlib_module_names.h index b8fbb4f43434e73..ac9d91b5e128850 100644 --- a/Python/stdlib_module_names.h +++ b/Python/stdlib_module_names.h @@ -19,7 +19,6 @@ static const char* _Py_stdlib_module_names[] = { "_codecs_tw", "_collections", "_collections_abc", -"_colorize", "_compat_pickle", "_compression", "_contextvars",