Skip to content

Commit 566b614

Browse files
committed
fix(cli): use prompt_toolkit run_in_terminal for lazy-dep install prompt (#40490)
1 parent 56236b1 commit 566b614

1 file changed

Lines changed: 33 additions & 6 deletions

File tree

tools/lazy_deps.py

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -458,13 +458,40 @@ def ensure(feature: str, *, prompt: bool = True) -> None:
458458

459459
if prompt and sys.stdin.isatty() and sys.stdout.isatty():
460460
spec_list = ", ".join(missing)
461+
prompt_msg = (
462+
f"\nFeature {feature!r} requires: {spec_list}\n"
463+
f"Install into the active venv now? [Y/n] "
464+
)
465+
answer = "n"
461466
try:
462-
answer = input(
463-
f"\nFeature {feature!r} requires: {spec_list}\n"
464-
f"Install into the active venv now? [Y/n] "
465-
).strip().lower()
466-
except (EOFError, KeyboardInterrupt):
467-
answer = "n"
467+
# When prompt_toolkit owns the terminal, bare input() deadlocks
468+
# because keystrokes go to prompt_toolkit, not stdin. Temporarily
469+
# release the terminal via run_in_terminal so input() can read.
470+
from prompt_toolkit.application.current import get_app_or_none
471+
app = get_app_or_none()
472+
except Exception:
473+
app = None # prompt_toolkit not installed or detection failed
474+
475+
if app is not None:
476+
try:
477+
from prompt_toolkit.application import run_in_terminal
478+
479+
def _read_input():
480+
nonlocal answer
481+
try:
482+
answer = input(prompt_msg).strip().lower()
483+
except (EOFError, KeyboardInterrupt):
484+
answer = "n"
485+
486+
run_in_terminal(_read_input)()
487+
except Exception:
488+
# Fallback: skip prompt if run_in_terminal fails
489+
answer = "n"
490+
else:
491+
try:
492+
answer = input(prompt_msg).strip().lower()
493+
except (EOFError, KeyboardInterrupt):
494+
answer = "n"
468495
if answer and answer not in {"y", "yes"}:
469496
raise FeatureUnavailable(
470497
feature, missing, "user declined install at prompt"

0 commit comments

Comments
 (0)