| 
									
										
										
										
											2024-05-01 21:27:06 +03:00
										 |  |  | import contextlib | 
					
						
							| 
									
										
										
										
											2025-01-24 18:00:54 +01:00
										 |  |  | import io | 
					
						
							| 
									
										
										
										
											2024-05-01 21:27:06 +03:00
										 |  |  | import sys | 
					
						
							|  |  |  | import unittest | 
					
						
							|  |  |  | import unittest.mock | 
					
						
							|  |  |  | import _colorize | 
					
						
							| 
									
										
										
										
											2025-01-24 18:00:54 +01:00
										 |  |  | from test.support.os_helper import EnvironmentVarGuard | 
					
						
							| 
									
										
										
										
											2024-05-01 21:27:06 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-24 18:00:54 +01:00
										 |  |  | @contextlib.contextmanager | 
					
						
							|  |  |  | def clear_env(): | 
					
						
							|  |  |  |     with EnvironmentVarGuard() as mock_env: | 
					
						
							|  |  |  |         for var in "FORCE_COLOR", "NO_COLOR", "PYTHON_COLORS": | 
					
						
							|  |  |  |             mock_env.unset(var) | 
					
						
							|  |  |  |         yield mock_env | 
					
						
							| 
									
										
										
										
											2024-05-01 21:27:06 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-24 18:00:54 +01:00
										 |  |  | def supports_virtual_terminal(): | 
					
						
							|  |  |  |     if sys.platform == "win32": | 
					
						
							|  |  |  |         return unittest.mock.patch("nt._supports_virtual_terminal", return_value=True) | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         return contextlib.nullcontext() | 
					
						
							| 
									
										
										
										
											2024-05-01 21:27:06 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class TestColorizeFunction(unittest.TestCase): | 
					
						
							|  |  |  |     def test_colorized_detection_checks_for_environment_variables(self): | 
					
						
							| 
									
										
										
										
											2025-01-24 18:00:54 +01:00
										 |  |  |         def check(env, fallback, expected): | 
					
						
							|  |  |  |             with (self.subTest(env=env, fallback=fallback), | 
					
						
							|  |  |  |                   clear_env() as mock_env): | 
					
						
							|  |  |  |                 mock_env.update(env) | 
					
						
							|  |  |  |                 isatty_mock.return_value = fallback | 
					
						
							|  |  |  |                 stdout_mock.isatty.return_value = fallback | 
					
						
							|  |  |  |                 self.assertEqual(_colorize.can_colorize(), expected) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-15 09:41:11 +01:00
										 |  |  |         with (unittest.mock.patch("os.isatty") as isatty_mock, | 
					
						
							| 
									
										
										
										
											2025-01-21 18:14:24 +02:00
										 |  |  |               unittest.mock.patch("sys.stdout") as stdout_mock, | 
					
						
							| 
									
										
										
										
											2025-01-24 18:00:54 +01:00
										 |  |  |               supports_virtual_terminal()): | 
					
						
							|  |  |  |             stdout_mock.fileno.return_value = 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             for fallback in False, True: | 
					
						
							|  |  |  |                 check({}, fallback, fallback) | 
					
						
							|  |  |  |                 check({'TERM': 'dumb'}, fallback, False) | 
					
						
							|  |  |  |                 check({'TERM': 'xterm'}, fallback, fallback) | 
					
						
							|  |  |  |                 check({'TERM': ''}, fallback, fallback) | 
					
						
							|  |  |  |                 check({'FORCE_COLOR': '1'}, fallback, True) | 
					
						
							|  |  |  |                 check({'FORCE_COLOR': '0'}, fallback, True) | 
					
						
							| 
									
										
										
										
											2025-01-27 15:48:05 +01:00
										 |  |  |                 check({'FORCE_COLOR': ''}, fallback, fallback) | 
					
						
							| 
									
										
										
										
											2025-01-24 18:00:54 +01:00
										 |  |  |                 check({'NO_COLOR': '1'}, fallback, False) | 
					
						
							|  |  |  |                 check({'NO_COLOR': '0'}, fallback, False) | 
					
						
							| 
									
										
										
										
											2025-01-27 15:48:05 +01:00
										 |  |  |                 check({'NO_COLOR': ''}, fallback, fallback) | 
					
						
							| 
									
										
										
										
											2025-01-24 18:00:54 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             check({'TERM': 'dumb', 'FORCE_COLOR': '1'}, False, True) | 
					
						
							|  |  |  |             check({'FORCE_COLOR': '1', 'NO_COLOR': '1'}, True, False) | 
					
						
							| 
									
										
										
										
											2024-12-15 09:41:11 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-24 18:00:54 +01:00
										 |  |  |             for ignore_environment in False, True: | 
					
						
							|  |  |  |                 # Simulate running with or without `-E`. | 
					
						
							|  |  |  |                 flags = unittest.mock.MagicMock(ignore_environment=ignore_environment) | 
					
						
							|  |  |  |                 with unittest.mock.patch("sys.flags", flags): | 
					
						
							|  |  |  |                     check({'PYTHON_COLORS': '1'}, True, True) | 
					
						
							|  |  |  |                     check({'PYTHON_COLORS': '1'}, False, not ignore_environment) | 
					
						
							|  |  |  |                     check({'PYTHON_COLORS': '0'}, True, ignore_environment) | 
					
						
							|  |  |  |                     check({'PYTHON_COLORS': '0'}, False, False) | 
					
						
							|  |  |  |                     for fallback in False, True: | 
					
						
							|  |  |  |                         check({'PYTHON_COLORS': 'x'}, fallback, fallback) | 
					
						
							|  |  |  |                         check({'PYTHON_COLORS': ''}, fallback, fallback) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     check({'TERM': 'dumb', 'PYTHON_COLORS': '1'}, False, not ignore_environment) | 
					
						
							|  |  |  |                     check({'NO_COLOR': '1', 'PYTHON_COLORS': '1'}, False, not ignore_environment) | 
					
						
							|  |  |  |                     check({'FORCE_COLOR': '1', 'PYTHON_COLORS': '0'}, True, ignore_environment) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @unittest.skipUnless(sys.platform == "win32", "requires Windows") | 
					
						
							|  |  |  |     def test_colorized_detection_checks_on_windows(self): | 
					
						
							|  |  |  |         with (clear_env(), | 
					
						
							|  |  |  |               unittest.mock.patch("os.isatty") as isatty_mock, | 
					
						
							|  |  |  |               unittest.mock.patch("sys.stdout") as stdout_mock, | 
					
						
							|  |  |  |               supports_virtual_terminal() as vt_mock): | 
					
						
							|  |  |  |             stdout_mock.fileno.return_value = 1 | 
					
						
							| 
									
										
										
										
											2024-12-15 09:41:11 +01:00
										 |  |  |             isatty_mock.return_value = True | 
					
						
							| 
									
										
										
										
											2025-01-24 18:00:54 +01:00
										 |  |  |             stdout_mock.isatty.return_value = True | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             vt_mock.return_value = True | 
					
						
							|  |  |  |             self.assertEqual(_colorize.can_colorize(), True) | 
					
						
							|  |  |  |             vt_mock.return_value = False | 
					
						
							|  |  |  |             self.assertEqual(_colorize.can_colorize(), False) | 
					
						
							|  |  |  |             import nt | 
					
						
							|  |  |  |             del nt._supports_virtual_terminal | 
					
						
							|  |  |  |             self.assertEqual(_colorize.can_colorize(), False) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_colorized_detection_checks_for_std_streams(self): | 
					
						
							|  |  |  |         with (clear_env(), | 
					
						
							|  |  |  |               unittest.mock.patch("os.isatty") as isatty_mock, | 
					
						
							|  |  |  |               unittest.mock.patch("sys.stdout") as stdout_mock, | 
					
						
							|  |  |  |               unittest.mock.patch("sys.stderr") as stderr_mock, | 
					
						
							|  |  |  |               supports_virtual_terminal()): | 
					
						
							| 
									
										
										
										
											2025-01-21 18:14:24 +02:00
										 |  |  |             stdout_mock.fileno.return_value = 1 | 
					
						
							| 
									
										
										
										
											2025-01-24 18:00:54 +01:00
										 |  |  |             stderr_mock.fileno.side_effect = ZeroDivisionError | 
					
						
							|  |  |  |             stderr_mock.isatty.side_effect = ZeroDivisionError | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             isatty_mock.return_value = True | 
					
						
							| 
									
										
										
										
											2025-01-21 18:14:24 +02:00
										 |  |  |             stdout_mock.isatty.return_value = True | 
					
						
							| 
									
										
										
										
											2025-01-24 18:00:54 +01:00
										 |  |  |             self.assertEqual(_colorize.can_colorize(), True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             isatty_mock.return_value = False | 
					
						
							|  |  |  |             stdout_mock.isatty.return_value = False | 
					
						
							|  |  |  |             self.assertEqual(_colorize.can_colorize(), False) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_colorized_detection_checks_for_file(self): | 
					
						
							|  |  |  |         with clear_env(), supports_virtual_terminal(): | 
					
						
							| 
									
										
										
										
											2024-12-15 09:41:11 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-24 18:00:54 +01:00
										 |  |  |             with unittest.mock.patch("os.isatty") as isatty_mock: | 
					
						
							|  |  |  |                 file = unittest.mock.MagicMock() | 
					
						
							|  |  |  |                 file.fileno.return_value = 1 | 
					
						
							|  |  |  |                 isatty_mock.return_value = True | 
					
						
							|  |  |  |                 self.assertEqual(_colorize.can_colorize(file=file), True) | 
					
						
							| 
									
										
										
										
											2024-05-01 21:27:06 +03:00
										 |  |  |                 isatty_mock.return_value = False | 
					
						
							| 
									
										
										
										
											2025-01-24 18:00:54 +01:00
										 |  |  |                 self.assertEqual(_colorize.can_colorize(file=file), False) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # No file.fileno. | 
					
						
							|  |  |  |             with unittest.mock.patch("os.isatty", side_effect=ZeroDivisionError): | 
					
						
							|  |  |  |                 file = unittest.mock.MagicMock(spec=['isatty']) | 
					
						
							|  |  |  |                 file.isatty.return_value = True | 
					
						
							|  |  |  |                 self.assertEqual(_colorize.can_colorize(file=file), False) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # file.fileno() raises io.UnsupportedOperation. | 
					
						
							|  |  |  |             with unittest.mock.patch("os.isatty", side_effect=ZeroDivisionError): | 
					
						
							|  |  |  |                 file = unittest.mock.MagicMock() | 
					
						
							|  |  |  |                 file.fileno.side_effect = io.UnsupportedOperation | 
					
						
							|  |  |  |                 file.isatty.return_value = True | 
					
						
							|  |  |  |                 self.assertEqual(_colorize.can_colorize(file=file), True) | 
					
						
							|  |  |  |                 file.isatty.return_value = False | 
					
						
							|  |  |  |                 self.assertEqual(_colorize.can_colorize(file=file), False) | 
					
						
							| 
									
										
										
										
											2024-05-01 21:27:06 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if __name__ == "__main__": | 
					
						
							|  |  |  |     unittest.main() |