From 8be7a054871cd041a242a9aa8f7e83e9a7a28ee1 Mon Sep 17 00:00:00 2001 From: Frantisek Hrbata Date: Wed, 29 Mar 2023 16:51:55 +0200 Subject: [PATCH] tools: fix progress output in asyncio.run with zero terminal width Currently the forced progress in RunTool is trying to fit the output line into a terminal width, but it doesn't take into an account a situation when the terminal width is reported as zero. This manifests when running in docker image with redirected output and can be seen in the github workflow output for esp-idf-ci-action. docker run --rm -t my_ubuntu_esp python3 -c 'import os,sys; print(os.get_terminal_size(), sys.stdout.isatty())' os.terminal_size(columns=238, lines=59) True vs docker run --rm -t my_ubuntu_esp python3 -c 'import os,sys; print(os.get_terminal_size(), sys.stdout.isatty())' | tee os.terminal_size(columns=0, lines=0) True Since the output is reported as tty and the terminal width as 0, the fit_text_in_terminal() function returns empty string. I also verified this by running idf.py build inside a testing docker image. This fix adjusts the fit_text_in_terminal() function to return original line if the terminal width is zero. Also simplify the progress print and use same approach as ninja https://github.com/ninja-build/ninja/blob/master/src/line_printer.cc#L66 Signed-off-by: Frantisek Hrbata --- tools/idf_py_actions/tools.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tools/idf_py_actions/tools.py b/tools/idf_py_actions/tools.py index 1b46c9c43e..db8b1c1de6 100644 --- a/tools/idf_py_actions/tools.py +++ b/tools/idf_py_actions/tools.py @@ -153,6 +153,8 @@ def fit_text_in_terminal(out: str) -> str: """Fit text in terminal, if the string is not fit replace center with `...`""" space_for_dots = 3 # Space for "..." terminal_width, _ = os.get_terminal_size() + if not terminal_width: + return out if terminal_width <= space_for_dots: # if the wide of the terminal is too small just print dots return '.' * terminal_width @@ -246,9 +248,8 @@ class RunTool: def print_progression(output: str) -> None: # Print a new line on top of the previous line - sys.stdout.write('\x1b[K') - print('\r', end='') - print(fit_text_in_terminal(output.strip('\n\r')), end='', file=output_stream) + print('\r' + fit_text_in_terminal(output.strip('\n\r')) + '\x1b[K', end='', file=output_stream) + output_stream.flush() async def read_stream() -> Optional[str]: try: