prompt: switching to prompt_toolkit in case of stdin with interactive mode (#5536)

### Motivation

There is an edge case that we're using mostly in integration tests from
the beginning of the world:
`echo 'echo 1' | xonsh -i` and it's not working with `TERM=dumb` because
dumb is readline.
So in this case we need to force using prompt_toolkit to avoid hanging.

Closes #5462 #5517

### Before

These all produces hanging because reading stdin is not implemented in
readline backend:
```xsh
echo whoami | TERM=dumb xonsh -i --no-rc   # dumb is readline in fact
# or the same
echo whoami | xonsh -st dumb -i  # dumb is readline in fact
# or the same
echo whoami | xonsh -st readline -i
```

### After

Switching to prompt_toolkit in these cases.

## For community
⬇️ **Please click the 👍 reaction instead of leaving a `+1` or 👍
comment**

---------

Co-authored-by: a <1@1.1>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
Andy Kipp 2024-06-25 18:04:14 +02:00 committed by GitHub
parent 584a84d645
commit 0b65348d5e
Failed to generate hash of commit
2 changed files with 34 additions and 1 deletions

View file

@ -0,0 +1,23 @@
**Added:**
* <news item>
**Changed:**
* prompt: Switching to prompt_toolkit in edge case of sending stdin to interactive mode (#5462 #5517).
**Deprecated:**
* <news item>
**Removed:**
* <news item>
**Fixed:**
* <news item>
**Security:**
* <news item>

View file

@ -202,9 +202,19 @@ class Shell:
if is_class(backend):
cls = backend
else:
"""
There is an edge case that we're using mostly in integration tests:
`echo 'echo 1' | xonsh -i` and it's not working with `TERM=dumb` (#5462 #5517)
because `dumb` is readline where stdin is not supported yet. PR is very welcome!
So in this case we need to force using prompt_toolkit.
"""
is_stdin_to_interactive = (
XSH.env.get("XONSH_INTERACTIVE", False) and not sys.stdin.isatty()
)
if backend == "none":
from xonsh.base_shell import BaseShell as cls
elif backend == "prompt_toolkit":
elif backend == "prompt_toolkit" or is_stdin_to_interactive:
from xonsh.ptk_shell.shell import PromptToolkitShell as cls
elif backend == "readline":
from xonsh.readline_shell import ReadlineShell as cls