diff --git a/install.py b/install.py index b886500..3426cdb 100644 --- a/install.py +++ b/install.py @@ -357,26 +357,47 @@ def op_run_command(op: Dict[str, Any], ctx: Dict[str, Any]) -> None: stderr_lines: List[str] = [] # Read stdout and stderr in real-time - import selectors - sel = selectors.DefaultSelector() - sel.register(process.stdout, selectors.EVENT_READ) # type: ignore[arg-type] - sel.register(process.stderr, selectors.EVENT_READ) # type: ignore[arg-type] + if sys.platform == "win32": + # On Windows, use threads instead of selectors (pipes aren't selectable) + import threading - while process.poll() is None or sel.get_map(): - for key, _ in sel.select(timeout=0.1): - line = key.fileobj.readline() # type: ignore[union-attr] - if not line: - sel.unregister(key.fileobj) - continue - if key.fileobj == process.stdout: - stdout_lines.append(line) - print(line, end="", flush=True) - else: - stderr_lines.append(line) - print(line, end="", file=sys.stderr, flush=True) + def read_output(pipe, lines, file=None): + for line in iter(pipe.readline, ''): + lines.append(line) + print(line, end="", flush=True, file=file) + pipe.close() - sel.close() - process.wait() + stdout_thread = threading.Thread(target=read_output, args=(process.stdout, stdout_lines)) + stderr_thread = threading.Thread(target=read_output, args=(process.stderr, stderr_lines, sys.stderr)) + + stdout_thread.start() + stderr_thread.start() + + stdout_thread.join() + stderr_thread.join() + process.wait() + else: + # On Unix, use selectors for more efficient I/O + import selectors + sel = selectors.DefaultSelector() + sel.register(process.stdout, selectors.EVENT_READ) # type: ignore[arg-type] + sel.register(process.stderr, selectors.EVENT_READ) # type: ignore[arg-type] + + while process.poll() is None or sel.get_map(): + for key, _ in sel.select(timeout=0.1): + line = key.fileobj.readline() # type: ignore[union-attr] + if not line: + sel.unregister(key.fileobj) + continue + if key.fileobj == process.stdout: + stdout_lines.append(line) + print(line, end="", flush=True) + else: + stderr_lines.append(line) + print(line, end="", file=sys.stderr, flush=True) + + sel.close() + process.wait() write_log( {