From 0bc10b7dc098716c3707238381e55cce70b53a9c Mon Sep 17 00:00:00 2001 From: Melissa LeBlanc-Williams Date: Thu, 10 Nov 2022 12:43:27 -0800 Subject: [PATCH] Fix run_command sometimes stops --- adafruit_shell.py | 93 ++++++++++++++++++++++++----------------------- 1 file changed, 48 insertions(+), 45 deletions(-) diff --git a/adafruit_shell.py b/adafruit_shell.py index 390d5cf..2d5645f 100644 --- a/adafruit_shell.py +++ b/adafruit_shell.py @@ -25,6 +25,8 @@ import sys import os import shutil import subprocess +import shlex +import fcntl import platform import fileinput import re @@ -67,75 +69,76 @@ class Shell: """ Run a shell command and show the output as it runs """ - original_stdout = sys.stdout - original_stderr = sys.stderr - try: - # pylint: disable=consider-using-with - proc = subprocess.Popen( - cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE - ) - # pylint: enable=consider-using-with - full_output = "" - while True: - output = proc.stdout.readline() - err = proc.stderr.read() - if err and not suppress_message: - self.error(err.decode("utf-8", errors="ignore")) - if len(output) == 0 and proc.poll() is not None: - break - if output: - decoded_output = output.decode("utf-8", errors="ignore").strip() - if not suppress_message: - self.info(decoded_output) - full_output += decoded_output - except Exception: # pylint: disable=broad-except - pass - finally: - sys.stdout = original_stdout - sys.stderr = original_stderr - if return_output: - return full_output - r = proc.poll() - if r == 0: - return True - return False + def non_block_read(output): + fd = output.fileno() + fl = fcntl.fcntl(fd, fcntl.F_GETFL) + fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK) + try: + return output.read() + except: + return "" - def info(self, message): + full_output = "" + with subprocess.Popen( + cmd, + shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + universal_newlines=True + ) as proc: + while proc.poll() is None: + err = non_block_read(proc.stderr) + if err != "" and not suppress_message: + self.error(err.strip(), end="\n\r") + output = non_block_read(proc.stdout) + if output != "" and not suppress_message: + self.info(output.strip(), end="\n\r") + full_output += output + return_code = proc.poll() + proc.stdout.close() + proc.stderr.close() + if return_output: + return full_output + if return_code: + return False + return True + + def info(self, message, **kwargs): """ Display a message with the group in green """ if self._group is not None: - print(colored.green(self._group) + " " + message) + print(colored.green(self._group) + " " + message, **kwargs) else: - print(message) + print(message, **kwargs) - def warn(self, message): + def warn(self, message, **kwargs): """ Display a message with the group in yellow """ if self._group is not None: - print(colored.yellow(self._group) + " " + message) + print(colored.yellow(self._group) + " " + message, **kwargs) else: - print(message) + print(message, **kwargs) - def bail(self, message=None): + def bail(self, message=None, **kwargs): """ Exit and display an error message if given """ if message is None: - self.error("Exiting due to error") + self.error("Exiting due to error", **kwargs) else: - self.error(f"Exiting due to error: {message}") + self.error(f"Exiting due to error: {message}", **kwargs) sys.exit(1) - def error(self, message): + def error(self, message, **kwargs): """ - Display some inforrmation + Display some information """ if self._group is not None: - print(colored.red(self._group) + " " + message) + print(colored.red(self._group) + " " + message, **kwargs) else: - print(message) + print(message, **kwargs) @staticmethod def print_colored(message, color):