18
18
)
19
19
20
20
from ..key_binding import KeyPress
21
+ from ..utils import DummyContext
21
22
from .base import Input
22
23
from .posix_utils import PosixStdinReader
23
24
from .vt100_parser import Vt100Parser
@@ -44,7 +45,9 @@ def __init__(self, stdin: TextIO) -> None:
44
45
# (Idle reports stdin to be a TTY, but fileno() is not implemented.)
45
46
try :
46
47
# This should not raise, but can return 0.
47
- stdin .fileno ()
48
+ fileno = stdin .fileno ()
49
+ except ValueError :
50
+ raise EOFError # stdin closed?
48
51
except io .UnsupportedOperation as e :
49
52
if "idlelib.run" in sys .modules :
50
53
raise io .UnsupportedOperation (
@@ -72,10 +75,10 @@ def __init__(self, stdin: TextIO) -> None:
72
75
73
76
# Create a backup of the fileno(). We want this to work even if the
74
77
# underlying file is closed, so that `typeahead_hash()` keeps working.
75
- self ._fileno = stdin . fileno ()
78
+ self ._fileno = fileno
76
79
77
80
self ._buffer : List [KeyPress ] = [] # Buffer to collect the Key objects.
78
- self .stdin_reader = PosixStdinReader (self . _fileno , encoding = stdin .encoding )
81
+ self .stdin_reader = PosixStdinReader (fileno , encoding = stdin .encoding )
79
82
self .vt100_parser = Vt100Parser (
80
83
lambda key_press : self ._buffer .append (key_press )
81
84
)
@@ -123,16 +126,40 @@ def flush_keys(self) -> List[KeyPress]:
123
126
124
127
@property
125
128
def closed (self ) -> bool :
126
- return self .stdin_reader .closed
129
+ # See: https://github.com/prompt-toolkit/ptpython/issues/463
130
+ # For ptpython, if the user does `sys.stdin.close()`, then
131
+ # `stdin_reader` will not yet be closed, but `stdin` will be closed.
132
+ # After this, `stdin.fileno()` and `stdin.read()` will both raise
133
+ # `ValueError`.
134
+ return self .stdin .closed or self .stdin_reader .closed
127
135
128
136
def raw_mode (self ) -> ContextManager [None ]:
129
- return raw_mode (self .stdin .fileno ())
137
+ try :
138
+ fileno = self .stdin .fileno ()
139
+ except ValueError :
140
+ # Stdin closed?
141
+ return DummyContext ()
142
+
143
+ return raw_mode (fileno )
130
144
131
145
def cooked_mode (self ) -> ContextManager [None ]:
132
- return cooked_mode (self .stdin .fileno ())
146
+ try :
147
+ fileno = self .stdin .fileno ()
148
+ except ValueError :
149
+ # Stdin closed?
150
+ return DummyContext ()
151
+
152
+ return cooked_mode (fileno )
133
153
134
154
def fileno (self ) -> int :
135
- return self .stdin .fileno ()
155
+ """
156
+ Return file descriptor.
157
+ Raises `EOFError` when the input is closed.
158
+ """
159
+ try :
160
+ return self .stdin .fileno ()
161
+ except ValueError :
162
+ raise EOFError
136
163
137
164
def typeahead_hash (self ) -> str :
138
165
return "fd-%s" % (self ._fileno ,)
0 commit comments