tools: idf.py: use actual sys.stdout instead of the memoized one

This fixes the issue with build output not being colorized on Windows,
while the hints messages are colorized.

The issue occurred because sys.stdout and sys.stderr get overridden
by colorama.init() at runtime, but the default argument
output_stream=sys.stdout holds the reference to the"original"
sys.stdout.

colorama.init() (which, by the way, gets called via a curious chain
of imports, via idf_component_tools.manifest and tqdm package)
overrides standard streams, on Windows only. The overridden streams
contain logic to convert ANSI color codes into Windows Console API
calls to colorize the text.

Since read_and_write_stream function used the default value of
output_stream evaluated at module loading time, it was using the
original sys.stdout, not the one overridden by colorama.

One extra note is that while this does fix the coloring issue, the
solution is a bit fragile, as it relies on one of the following
(on Windows):
- colorama.init() is called (this can change if idf-component-manager
  stops importing tqdm)
- Sufficiently new version of Windows 10 is used, and ANSI color codes
  support is enabled in the Registry.
pull/9702/head
Ivan Grokhotkov 2022-08-30 01:01:32 +02:00
rodzic b7efde18c6
commit 2c5b62f10e
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 1E050E141B280628
1 zmienionych plików z 2 dodań i 2 usunięć

Wyświetl plik

@ -222,12 +222,12 @@ class RunTool:
if p.stderr and p.stdout: # it only to avoid None type in p.std
await asyncio.gather(
self.read_and_write_stream(p.stderr, stderr_output_file, sys.stderr),
self.read_and_write_stream(p.stdout, stdout_output_file))
self.read_and_write_stream(p.stdout, stdout_output_file, sys.stdout))
await p.wait() # added for avoiding None returncode
return p, stderr_output_file, stdout_output_file
async def read_and_write_stream(self, input_stream: asyncio.StreamReader, output_filename: str,
output_stream: TextIO=sys.stdout) -> None:
output_stream: TextIO) -> None:
"""read the output of the `input_stream` and then write it into `output_filename` and `output_stream`"""
def delete_ansi_escape(text: str) -> str:
ansi_escape = re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])')