Skip to content

Commit 0ac40ac

Browse files
authored
gh-127353: Allow to force color output on Windows V2 (#127926)
1 parent e2325c9 commit 0ac40ac

File tree

3 files changed

+51
-38
lines changed

3 files changed

+51
-38
lines changed

Lib/_colorize.py

+9-8
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,6 @@ def get_colors(colorize: bool = False) -> ANSIColors:
3232

3333

3434
def can_colorize() -> bool:
35-
if sys.platform == "win32":
36-
try:
37-
import nt
38-
39-
if not nt._supports_virtual_terminal():
40-
return False
41-
except (ImportError, AttributeError):
42-
return False
4335
if not sys.flags.ignore_environment:
4436
if os.environ.get("PYTHON_COLORS") == "0":
4537
return False
@@ -58,6 +50,15 @@ def can_colorize() -> bool:
5850
if not hasattr(sys.stderr, "fileno"):
5951
return False
6052

53+
if sys.platform == "win32":
54+
try:
55+
import nt
56+
57+
if not nt._supports_virtual_terminal():
58+
return False
59+
except (ImportError, AttributeError):
60+
return False
61+
6162
try:
6263
return os.isatty(sys.stderr.fileno())
6364
except io.UnsupportedOperation:

Lib/test/test__colorize.py

+40-30
Original file line numberDiff line numberDiff line change
@@ -19,40 +19,50 @@ def tearDownModule():
1919
class TestColorizeFunction(unittest.TestCase):
2020
@force_not_colorized
2121
def test_colorized_detection_checks_for_environment_variables(self):
22-
if sys.platform == "win32":
23-
virtual_patching = unittest.mock.patch("nt._supports_virtual_terminal",
24-
return_value=True)
25-
else:
26-
virtual_patching = contextlib.nullcontext()
27-
with virtual_patching:
28-
29-
flags = unittest.mock.MagicMock(ignore_environment=False)
30-
with (unittest.mock.patch("os.isatty") as isatty_mock,
31-
unittest.mock.patch("sys.flags", flags),
32-
unittest.mock.patch("_colorize.can_colorize", ORIGINAL_CAN_COLORIZE)):
33-
isatty_mock.return_value = True
34-
with unittest.mock.patch("os.environ", {'TERM': 'dumb'}):
35-
self.assertEqual(_colorize.can_colorize(), False)
36-
with unittest.mock.patch("os.environ", {'PYTHON_COLORS': '1'}):
37-
self.assertEqual(_colorize.can_colorize(), True)
38-
with unittest.mock.patch("os.environ", {'PYTHON_COLORS': '0'}):
39-
self.assertEqual(_colorize.can_colorize(), False)
40-
with unittest.mock.patch("os.environ", {'NO_COLOR': '1'}):
22+
flags = unittest.mock.MagicMock(ignore_environment=False)
23+
with (unittest.mock.patch("os.isatty") as isatty_mock,
24+
unittest.mock.patch("sys.stderr") as stderr_mock,
25+
unittest.mock.patch("sys.flags", flags),
26+
unittest.mock.patch("_colorize.can_colorize", ORIGINAL_CAN_COLORIZE),
27+
(unittest.mock.patch("nt._supports_virtual_terminal", return_value=False)
28+
if sys.platform == "win32" else
29+
contextlib.nullcontext()) as vt_mock):
30+
31+
isatty_mock.return_value = True
32+
stderr_mock.fileno.return_value = 2
33+
stderr_mock.isatty.return_value = True
34+
with unittest.mock.patch("os.environ", {'TERM': 'dumb'}):
35+
self.assertEqual(_colorize.can_colorize(), False)
36+
with unittest.mock.patch("os.environ", {'PYTHON_COLORS': '1'}):
37+
self.assertEqual(_colorize.can_colorize(), True)
38+
with unittest.mock.patch("os.environ", {'PYTHON_COLORS': '0'}):
39+
self.assertEqual(_colorize.can_colorize(), False)
40+
with unittest.mock.patch("os.environ", {'NO_COLOR': '1'}):
41+
self.assertEqual(_colorize.can_colorize(), False)
42+
with unittest.mock.patch("os.environ",
43+
{'NO_COLOR': '1', "PYTHON_COLORS": '1'}):
44+
self.assertEqual(_colorize.can_colorize(), True)
45+
with unittest.mock.patch("os.environ", {'FORCE_COLOR': '1'}):
46+
self.assertEqual(_colorize.can_colorize(), True)
47+
with unittest.mock.patch("os.environ",
48+
{'FORCE_COLOR': '1', 'NO_COLOR': '1'}):
49+
self.assertEqual(_colorize.can_colorize(), False)
50+
with unittest.mock.patch("os.environ",
51+
{'FORCE_COLOR': '1', "PYTHON_COLORS": '0'}):
52+
self.assertEqual(_colorize.can_colorize(), False)
53+
54+
with unittest.mock.patch("os.environ", {}):
55+
if sys.platform == "win32":
4156
self.assertEqual(_colorize.can_colorize(), False)
42-
with unittest.mock.patch("os.environ",
43-
{'NO_COLOR': '1', "PYTHON_COLORS": '1'}):
57+
58+
vt_mock.return_value = True
4459
self.assertEqual(_colorize.can_colorize(), True)
45-
with unittest.mock.patch("os.environ", {'FORCE_COLOR': '1'}):
60+
else:
4661
self.assertEqual(_colorize.can_colorize(), True)
47-
with unittest.mock.patch("os.environ",
48-
{'FORCE_COLOR': '1', 'NO_COLOR': '1'}):
49-
self.assertEqual(_colorize.can_colorize(), False)
50-
with unittest.mock.patch("os.environ",
51-
{'FORCE_COLOR': '1', "PYTHON_COLORS": '0'}):
52-
self.assertEqual(_colorize.can_colorize(), False)
62+
5363
isatty_mock.return_value = False
54-
with unittest.mock.patch("os.environ", {}):
55-
self.assertEqual(_colorize.can_colorize(), False)
64+
stderr_mock.isatty.return_value = False
65+
self.assertEqual(_colorize.can_colorize(), False)
5666

5767

5868
if __name__ == "__main__":
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Allow to force color output on Windows using environment variables. Patch by
2+
Andrey Efremov.

0 commit comments

Comments
 (0)