22
22
TEST_STRING_1 = b"I wish to buy a fish license.\n "
23
23
TEST_STRING_2 = b"For my pet fish, Eric.\n "
24
24
25
+ try :
26
+ _TIOCGWINSZ = tty .TIOCGWINSZ
27
+ _TIOCSWINSZ = tty .TIOCSWINSZ
28
+ _HAVE_WINSZ = True
29
+ except AttributeError :
30
+ _HAVE_WINSZ = False
31
+
25
32
if verbose :
26
33
def debug (msg ):
27
34
print (msg )
@@ -80,11 +87,17 @@ def expectedFailureOnBSD(fun):
80
87
return unittest .expectedFailure (fun )
81
88
return fun
82
89
90
+ def _get_term_winsz (fd ):
91
+ s = struct .pack ("HHHH" , 0 , 0 , 0 , 0 )
92
+ return fcntl .ioctl (fd , _TIOCGWINSZ , s )
93
+
94
+ def _set_term_winsz (fd , winsz ):
95
+ fcntl .ioctl (fd , _TIOCSWINSZ , winsz )
96
+
83
97
84
98
# Marginal testing of pty suite. Cannot do extensive 'do or fail' testing
85
99
# because pty code is not too portable.
86
100
# XXX(nnorwitz): these tests leak fds when there is an error.
87
- # Soumendra: test_openpty may leave tty in abnormal state upon failure.
88
101
class PtyTest (unittest .TestCase ):
89
102
def setUp (self ):
90
103
old_alarm = signal .signal (signal .SIGALRM , self .handle_sig )
@@ -98,62 +111,70 @@ def setUp(self):
98
111
self .addCleanup (signal .alarm , 0 )
99
112
signal .alarm (10 )
100
113
114
+ # Save original stdin window size
115
+ self .stdin_rows = None
116
+ self .stdin_cols = None
117
+ if _HAVE_WINSZ :
118
+ try :
119
+ stdin_dim = os .get_terminal_size (pty .STDIN_FILENO )
120
+ self .stdin_rows = stdin_dim .lines
121
+ self .stdin_cols = stdin_dim .columns
122
+ old_stdin_winsz = struct .pack ("HHHH" , self .stdin_rows ,
123
+ self .stdin_cols , 0 , 0 )
124
+ self .addCleanup (_set_term_winsz , pty .STDIN_FILENO , old_stdin_winsz )
125
+ except OSError :
126
+ # possible reason: current stdin is not a tty
127
+ pass
128
+
101
129
def handle_sig (self , sig , frame ):
102
130
self .fail ("isatty hung" )
103
131
104
- # RELEVANT ANYMORE?
105
132
@staticmethod
106
133
def handle_sighup (signum , frame ):
107
134
# bpo-38547: if the process is the session leader, os.close(master_fd)
108
135
# of "master_fd, slave_name = pty.master_open()" raises SIGHUP
109
136
# signal: just ignore the signal.
137
+ #
138
+ # NOTE: the above comment is from an older version of the test;
139
+ # master_open() is not being used anymore.
110
140
pass
111
141
112
142
@expectedFailureIfStdinIsTTY
113
143
def test_openpty (self ):
114
144
try :
115
145
mode = tty .tcgetattr (pty .STDIN_FILENO )
116
146
except tty .error :
117
- # pty.STDIN_FILENO not a tty?
147
+ # possible reason: current stdin is not a tty
118
148
debug ("tty.tcgetattr(pty.STDIN_FILENO) failed" )
119
149
mode = None
120
150
121
- try :
122
- TIOCGWINSZ = tty .TIOCGWINSZ
123
- TIOCSWINSZ = tty .TIOCSWINSZ
124
- except AttributeError :
125
- debug ("TIOCSWINSZ/TIOCGWINSZ not available" )
126
- winsz = None
127
- else :
151
+ new_stdin_winsz = None
152
+ if _HAVE_WINSZ :
128
153
try :
129
154
debug ("Setting pty.STDIN_FILENO window size" )
130
- current_stdin_winsz = os .get_terminal_size (pty .STDIN_FILENO )
131
-
132
155
# Set number of columns and rows to be the
133
156
# floors of 1/5 of respective original values
134
- winsz = struct .pack ("HHHH" , current_stdin_winsz . lines // 5 ,
135
- current_stdin_winsz . columns // 5 , 0 , 0 )
136
- fcntl . ioctl (pty .STDIN_FILENO , TIOCSWINSZ , winsz )
157
+ target_stdin_winsz = struct .pack ("HHHH" , self . stdin_rows // 5 ,
158
+ self . stdin_cols // 5 , 0 , 0 )
159
+ _set_term_winsz (pty .STDIN_FILENO , target_stdin_winsz )
137
160
138
161
# Were we able to set the window size
139
162
# of pty.STDIN_FILENO successfully?
140
- s = struct .pack ("HHHH" , 0 , 0 , 0 , 0 )
141
- new_stdin_winsz = fcntl .ioctl (pty .STDIN_FILENO , TIOCGWINSZ , s )
142
- self .assertEqual (new_stdin_winsz , winsz ,
163
+ new_stdin_winsz = _get_term_winsz (pty .STDIN_FILENO )
164
+ self .assertEqual (new_stdin_winsz , target_stdin_winsz ,
143
165
"pty.STDIN_FILENO window size unchanged" )
144
166
except OSError :
145
- # pty.STDIN_FILENO not a tty?
146
- debug ("Failed to set pty.STDIN_FILENO window size" )
147
- winsz = None
167
+ # possible reason: current stdin is not a tty
168
+ warnings . warn ("Failed to set pty.STDIN_FILENO window size" )
169
+ pass
148
170
149
171
try :
150
172
debug ("Calling pty.openpty()" )
151
173
try :
152
- master_fd , slave_fd = pty .openpty (mode , winsz )
174
+ master_fd , slave_fd = pty .openpty (mode , new_stdin_winsz )
153
175
except TypeError :
154
176
master_fd , slave_fd = pty .openpty ()
155
- debug ("Got master_fd '%d', slave_fd '%d'" %
156
- (master_fd , slave_fd ))
177
+ debug (f"Got master_fd '{ master_fd } ', slave_fd '{ slave_fd } '" )
157
178
except OSError :
158
179
# " An optional feature could not be imported " ... ?
159
180
raise unittest .SkipTest ("Pseudo-terminals (seemingly) not functional." )
@@ -163,15 +184,16 @@ def test_openpty(self):
163
184
if mode :
164
185
self .assertEqual (tty .tcgetattr (slave_fd ), mode ,
165
186
"openpty() failed to set slave termios" )
166
- if winsz :
167
- s = struct .pack ("HHHH" , 0 , 0 , 0 , 0 )
168
- self .assertEqual (fcntl .ioctl (slave_fd , TIOCGWINSZ , s ), winsz ,
187
+ if new_stdin_winsz :
188
+ self .assertEqual (_get_term_winsz (slave_fd ), new_stdin_winsz ,
169
189
"openpty() failed to set slave window size" )
170
190
171
- # RELEVANT ANYMORE?
172
191
# Solaris requires reading the fd before anything is returned.
173
192
# My guess is that since we open and close the slave fd
174
193
# in master_open(), we need to read the EOF.
194
+ #
195
+ # NOTE: the above comment is from an older version of the test;
196
+ # master_open() is not being used anymore.
175
197
176
198
# Ensure the fd is non-blocking in case there's nothing to read.
177
199
blocking = os .get_blocking (master_fd )
@@ -205,13 +227,6 @@ def test_openpty(self):
205
227
# to ignore this signal.
206
228
os .close (master_fd )
207
229
208
- if winsz :
209
- winsz = struct .pack ("HHHH" , current_stdin_winsz .lines ,
210
- current_stdin_winsz .columns , 0 , 0 )
211
- fcntl .ioctl (pty .STDIN_FILENO , TIOCSWINSZ , winsz )
212
-
213
- # pty.openpty() passed.
214
-
215
230
def test_fork (self ):
216
231
debug ("calling pty.fork()" )
217
232
pid , master_fd = pty .fork ()
@@ -295,8 +310,6 @@ def test_fork(self):
295
310
296
311
os .close (master_fd )
297
312
298
- # pty.fork() passed.
299
-
300
313
@expectedFailureOnBSD
301
314
def test_master_read (self ):
302
315
debug ("Calling pty.openpty()" )
@@ -407,6 +420,7 @@ def test__copy_eof_on_all(self):
407
420
with self .assertRaises (IndexError ):
408
421
pty ._copy (masters [0 ])
409
422
423
+
410
424
def tearDownModule ():
411
425
reap_children ()
412
426
0 commit comments