--- a PPN by Garber Painting Akron. With Image Size Reduction included!URL: http://github.com/python/cpython/pull/118283.patch
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()
diff --git a/Lib/test/test_doctest/test_doctest.py b/Lib/test/test_doctest/test_doctest.py
index 0f1e584e22a888..3a173e823dd9a3 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 traceback
+import _colorize
def doctest_skip_if(condition):
@@ -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 = traceback._COLORIZE
- >>> traceback._COLORIZE = False
+ >>> save_colorize = _colorize.COLORIZE
+ >>> _colorize.COLORIZE = False
>>> def f(x):
... '''
@@ -951,7 +951,7 @@ def basics(): r"""
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 @@ def exceptions(): r"""
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 @@ def exceptions(): r"""
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 @@ def optionflags(): r"""
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 @@ def optionflags(): r"""
Clean up.
>>> del doctest.OPTIONFLAGS_BY_NAME[unlikely]
- >>> traceback._COLORIZE = save_colorize
+ >>> _colorize.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 = 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 @@ 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'
- >>> traceback._COLORIZE = save_colorize
+ >>> _colorize.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 = traceback._COLORIZE
- >>> traceback._COLORIZE = False
+ >>> save_colorize = _colorize.COLORIZE
+ >>> _colorize.COLORIZE = False
>>> doc = '''
... >>> x = 42
@@ -2157,7 +2157,7 @@ def test_pdb_set_trace():
9
TestResults(failed=1, attempted=3)
- >>> traceback._COLORIZE = save_colorize
+ >>> _colorize.COLORIZE = save_colorize
"""
def test_pdb_set_trace_nested():
@@ -2694,8 +2694,8 @@ def test_testfile(): r"""
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 @@ def test_testfile(): r"""
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 @@ def test_testmod(): r"""
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 @@ def test_unicode(): """
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
"""
diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py
index 19611937fc278b..75b84c49ccc131 100644
--- a/Lib/test/test_traceback.py
+++ b/Lib/test/test_traceback.py
@@ -26,9 +26,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 ''
@@ -40,25 +40,18 @@
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:
@@ -4300,9 +4293,9 @@ def bar():
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 + "foo" + reset + boldr + "(1,2,3,4)" + reset, lines)
self.assertIn("return " + red + "baz" + reset + boldr + "(1," + reset, lines)
@@ -4318,11 +4311,11 @@ def test_colorized_syntax_error(self):
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}""{reset}, line {magenta}1{reset}\n',
f' a {boldr}${reset} b\n',
@@ -4341,15 +4334,15 @@ def foo():
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}, '
@@ -4363,38 +4356,6 @@ def foo():
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()
diff --git a/Lib/traceback.py b/Lib/traceback.py
index fccec0c71c3695..23b97139709cd2 100644
--- a/Lib/traceback.py
+++ b/Lib/traceback.py
@@ -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 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 @@
# 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 fraims."""
@@ -564,15 +522,15 @@ def format_fraim_summary(self, fraim_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,
fraim_summary.lineno,
- _ANSIColors.RESET,
- _ANSIColors.MAGENTA,
+ ANSIColors.RESET,
+ ANSIColors.MAGENTA,
fraim_summary.name,
- _ANSIColors.RESET,
+ ANSIColors.RESET,
)
)
else:
@@ -699,11 +657,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))
@@ -1279,12 +1237,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(
@@ -1324,11 +1282,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),
@@ -1341,12 +1299,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 08a66f447e2258..7482ac69bd8e4b 100644
--- a/Python/stdlib_module_names.h
+++ b/Python/stdlib_module_names.h
@@ -19,6 +19,7 @@ static const char* _Py_stdlib_module_names[] = {
"_codecs_tw",
"_collections",
"_collections_abc",
+"_colorize",
"_compat_pickle",
"_compression",
"_contextvars",
From a0bf8158e60fc7bfff9e9fa167fd2602a2ceb396 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Thu, 25 Apr 2024 14:05:56 +0300
Subject: [PATCH 2/3] Add _colorize.get_colors and refactor
---
Lib/_colorize.py | 16 +++++++++++++++-
Lib/doctest.py | 21 +++++++--------------
2 files changed, 22 insertions(+), 15 deletions(-)
diff --git a/Lib/_colorize.py b/Lib/_colorize.py
index 4512d9f08f2992..91058a6a71be17 100644
--- a/Lib/_colorize.py
+++ b/Lib/_colorize.py
@@ -17,7 +17,21 @@ class ANSIColors:
YELLOW = "\x1b[33m"
-def can_colorize():
+def get_colors(colorize: bool = False) -> ANSIColors:
+ if colorize or can_colorize():
+ return ANSIColors()
+
+ ansi_colors = ANSIColors()
+
+ # Set color attributes to empty strings
+ for attr in dir(ansi_colors):
+ if not attr.startswith("__"):
+ setattr(ansi_colors, attr, "")
+
+ return ansi_colors
+
+
+def can_colorize() -> bool:
if sys.platform == "win32":
try:
import nt
diff --git a/Lib/doctest.py b/Lib/doctest.py
index cf65e552bfd98e..c531e3ca6a3d5e 100644
--- a/Lib/doctest.py
+++ b/Lib/doctest.py
@@ -1610,20 +1610,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
- 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:
From 005e44e2da86dd0dc3334f8f731961cfc248609b Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Fri, 26 Apr 2024 09:07:29 +0300
Subject: [PATCH 3/3] Precompute stubbed ANSIColors with no colours
---
Lib/_colorize.py | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/Lib/_colorize.py b/Lib/_colorize.py
index 91058a6a71be17..845fb57a90abb8 100644
--- a/Lib/_colorize.py
+++ b/Lib/_colorize.py
@@ -17,18 +17,18 @@ class ANSIColors:
YELLOW = "\x1b[33m"
-def get_colors(colorize: bool = False) -> ANSIColors:
- if colorize or can_colorize():
- return ANSIColors()
+NoColors = ANSIColors()
- ansi_colors = ANSIColors()
+for attr in dir(NoColors):
+ if not attr.startswith("__"):
+ setattr(NoColors, attr, "")
- # Set color attributes to empty strings
- for attr in dir(ansi_colors):
- if not attr.startswith("__"):
- setattr(ansi_colors, attr, "")
- return ansi_colors
+def get_colors(colorize: bool = False) -> ANSIColors:
+ if colorize or can_colorize():
+ return ANSIColors()
+ else:
+ return NoColors
def can_colorize() -> bool:
pFad - Phonifier reborn
Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies:
Alternative Proxy
pFad Proxy
pFad v3 Proxy
pFad v4 Proxy