"""Utilities related to user input."""
-import readchar # type: ignore
+import logging
import signal
import sys
from typing import List
+import readchar # type: ignore
+
+import exceptions
+
+logger = logging.getLogger(__file__)
+
def single_keystroke_response(
valid_responses: List[str],
default_response: str = None,
timeout_seconds: int = None,
) -> str:
- class TimeoutError(Exception):
- pass
+ """Get a single keystroke response to a prompt."""
def _handle_timeout(signum, frame) -> None:
- raise TimeoutError()
+ raise exceptions.TimeoutError()
def _single_keystroke_response_internal(
valid_responses: List[str], timeout_seconds=None
try:
while True:
response = readchar.readchar()
+ logger.debug('Keystroke: 0x%x', ord(response))
if response in valid_responses:
break
if ord(response) in os_special_keystrokes:
print(prompt, end="")
sys.stdout.flush()
try:
- response = _single_keystroke_response_internal(
- valid_responses, timeout_seconds
- )
- except TimeoutError:
+ response = _single_keystroke_response_internal(valid_responses, timeout_seconds)
+ if ord(response) == 3:
+ raise KeyboardInterrupt('User pressed ^C in input_utils.')
+
+ except exceptions.TimeoutError:
if default_response is not None:
response = default_response
if prompt is not None:
def yn_response(prompt: str = None, *, timeout_seconds=None) -> str:
+ """Get a Y/N response to a prompt."""
+
return single_keystroke_response(
["y", "n", "Y", "N"], prompt=prompt, timeout_seconds=timeout_seconds
).lower()
def keystroke_helper() -> None:
+ """Misc util to watch keystrokes and report what they were."""
+
print("Watching for keystrokes; ^C to quit.")
while True:
key = readchar.readkey()