1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
from __future__ import annotations
import io
import sys
from typing import ContextManager, TextIO
from .base import DummyInput, Input, PipeInput
__all__ = [
"create_input",
"create_pipe_input",
]
def create_input(stdin: TextIO | None = None, always_prefer_tty: bool = False) -> Input:
"""
Create the appropriate `Input` object for the current os/environment.
:param always_prefer_tty: When set, if `sys.stdin` is connected to a Unix
`pipe`, check whether `sys.stdout` or `sys.stderr` are connected to a
pseudo terminal. If so, open the tty for reading instead of reading for
`sys.stdin`. (We can open `stdout` or `stderr` for reading, this is how
a `$PAGER` works.)
"""
if sys.platform == "win32":
from .win32 import Win32Input
# If `stdin` was assigned `None` (which happens with pythonw.exe), use
# a `DummyInput`. This triggers `EOFError` in the application code.
if stdin is None and sys.stdin is None:
return DummyInput()
return Win32Input(stdin or sys.stdin)
else:
from .vt100 import Vt100Input
# If no input TextIO is given, use stdin/stdout.
if stdin is None:
stdin = sys.stdin
if always_prefer_tty:
for obj in [sys.stdin, sys.stdout, sys.stderr]:
if obj.isatty():
stdin = obj
break
# If we can't access the file descriptor for the selected stdin, return
# a `DummyInput` instead. This can happen for instance in unit tests,
# when `sys.stdin` is patched by something that's not an actual file.
# (Instantiating `Vt100Input` would fail in this case.)
try:
stdin.fileno()
except io.UnsupportedOperation:
return DummyInput()
return Vt100Input(stdin)
def create_pipe_input() -> ContextManager[PipeInput]:
"""
Create an input pipe.
This is mostly useful for unit testing.
Usage::
with create_pipe_input() as input:
input.send_text('inputdata')
Breaking change: In prompt_toolkit 3.0.28 and earlier, this was returning
the `PipeInput` directly, rather than through a context manager.
"""
if sys.platform == "win32":
from .win32_pipe import Win32PipeInput
return Win32PipeInput.create()
else:
from .posix_pipe import PosixPipeInput
return PosixPipeInput.create()
|