setup_color: Use native ANSI support on Windows 10
Windows 10 has support for native ANSI control codes.
This means we don't have to wrap stdout/stderr with Colorama, which uses old CMD APIs to handle these sequences.
This change inadvertently also works around an issue on Python 3 where Colorama errors when bytes are output by gclient_utils.CheckCallAndFilter due to not wrapping sys.stdout.buffer.
Bug: 942522
Change-Id: Ic7dde620b01bd94eb50de353bfc0276cad045a45
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/1735566
Commit-Queue: Raul Tambre <raul@tambre.ee>
Reviewed-by: Marc-Antoine Ruel <maruel@chromium.org>
Auto-Submit: Raul Tambre <raul@tambre.ee>
diff --git a/setup_color.py b/setup_color.py
index 24888a5..dfc60ec 100644
--- a/setup_color.py
+++ b/setup_color.py
@@ -5,13 +5,40 @@
from __future__ import print_function
+import ctypes
import os
+import platform
+import subprocess
import sys
from third_party import colorama
IS_TTY = None
OUT_TYPE = 'unknown'
+
+def enable_native_ansi():
+ """Enables native ANSI sequences in console. Windows 10 only.
+
+ Returns whether successful.
+ """
+ kernel32 = ctypes.windll.kernel32
+ ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x04
+
+ out_handle = kernel32.GetStdHandle(subprocess.STD_OUTPUT_HANDLE)
+ mode = ctypes.wintypes.DWORD()
+ if kernel32.GetConsoleMode(out_handle, ctypes.byref(mode)) == 0:
+ print('kernel32.GetConsoleMode failed')
+ return False
+
+ if not (mode.value & ENABLE_VIRTUAL_TERMINAL_PROCESSING):
+ if kernel32.SetConsoleMode(
+ out_handle, mode.value | ENABLE_VIRTUAL_TERMINAL_PROCESSING) == 0:
+ print('kernel32.SetConsoleMode to enable ANSI sequences failed')
+ return False
+
+ return True
+
+
def init():
# should_wrap instructs colorama to wrap stdout/stderr with an ASNI colorcode
# interpreter that converts them to SetConsoleTextAttribute calls. This only
@@ -30,7 +57,6 @@
OUT_TYPE = 'file (win)'
import msvcrt
- import ctypes
h = msvcrt.get_osfhandle(sys.stdout.fileno())
# h is the win32 HANDLE for stdout.
ftype = ctypes.windll.kernel32.GetFileType(h)
@@ -84,6 +110,10 @@
else:
# A normal file, or an unknown file type.
pass
+
+ # Enable native ANSI color codes on Windows 10.
+ if IS_TTY and platform.release() == '10':
+ should_wrap = not enable_native_ansi()
else:
# This is non-windows, so we trust isatty.
OUT_TYPE = 'pipe or file'