From 5a637979519156c66c55c0a0ba85df481293a988 Mon Sep 17 00:00:00 2001 From: thePR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> Date: Sat, 5 Jul 2025 14:03:33 -0400 Subject: [PATCH] fix timed_input on Windows --- src/utils/input_utils.py | 49 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 5 deletions(-) diff --git a/src/utils/input_utils.py b/src/utils/input_utils.py index a9e58b3..cd10e80 100644 --- a/src/utils/input_utils.py +++ b/src/utils/input_utils.py @@ -1,14 +1,17 @@ import sys import select import io +import time from typing import Optional +try: + import msvcrt +except ImportError: # pragma: no cover - not on Windows + msvcrt = None -def timed_input(prompt: str, timeout: Optional[float]) -> str: - """Read input from the user with a timeout.""" - print(prompt, end="", flush=True) - if timeout is None or timeout <= 0: - return sys.stdin.readline().strip() + +def _timed_input_posix(timeout: float) -> str: + """POSIX implementation of timed input using ``select``.""" try: sys.stdin.fileno() except (AttributeError, io.UnsupportedOperation): @@ -17,3 +20,39 @@ def timed_input(prompt: str, timeout: Optional[float]) -> str: if ready: return sys.stdin.readline().strip() raise TimeoutError("input timed out") + + +def _timed_input_windows(timeout: float) -> str: + """Windows implementation of timed input using ``msvcrt``.""" + if msvcrt is None: # pragma: no cover - should not happen + return input().strip() + start = time.time() + buffer: list[str] = [] + while True: + if msvcrt.kbhit(): + char = msvcrt.getwche() + if char in ("\r", "\n"): + print() + return "".join(buffer) + if char == "\b": + if buffer: + buffer.pop() + print("\b \b", end="", flush=True) + else: + buffer.append(char) + if (time.time() - start) > timeout: + raise TimeoutError("input timed out") + time.sleep(0.05) + + +def timed_input(prompt: str, timeout: Optional[float]) -> str: + """Read input from the user with a timeout.""" + print(prompt, end="", flush=True) + if timeout is None or timeout <= 0: + return sys.stdin.readline().strip() + + if sys.platform == "win32": + return _timed_input_windows(timeout) + + # Fallback to ``select``-based implementation for POSIX systems + return _timed_input_posix(timeout)