2222TEST_STRING_1 = b"I wish to buy a fish license.\n "
2323TEST_STRING_2 = b"For my pet fish, Eric.\n "
2424
25+ try :
26+ _TIOCGWINSZ = tty .TIOCGWINSZ
27+ _TIOCSWINSZ = tty .TIOCSWINSZ
28+ _HAVE_WINSZ = True
29+ except AttributeError :
30+ _HAVE_WINSZ = False
31+
2532if verbose :
2633 def debug (msg ):
2734 print (msg )
@@ -80,11 +87,17 @@ def expectedFailureOnBSD(fun):
8087 return unittest .expectedFailure (fun )
8188 return fun
8289
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+
8397
8498# Marginal testing of pty suite. Cannot do extensive 'do or fail' testing
8599# because pty code is not too portable.
86100# XXX(nnorwitz): these tests leak fds when there is an error.
87- # Soumendra: test_openpty may leave tty in abnormal state upon failure.
88101class PtyTest (unittest .TestCase ):
89102 def setUp (self ):
90103 old_alarm = signal .signal (signal .SIGALRM , self .handle_sig )
@@ -98,62 +111,70 @@ def setUp(self):
98111 self .addCleanup (signal .alarm , 0 )
99112 signal .alarm (10 )
100113
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+
101129 def handle_sig (self , sig , frame ):
102130 self .fail ("isatty hung" )
103131
104- # RELEVANT ANYMORE?
105132 @staticmethod
106133 def handle_sighup (signum , frame ):
107134 # bpo-38547: if the process is the session leader, os.close(master_fd)
108135 # of "master_fd, slave_name = pty.master_open()" raises SIGHUP
109136 # 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.
110140 pass
111141
112142 @expectedFailureIfStdinIsTTY
113143 def test_openpty (self ):
114144 try :
115145 mode = tty .tcgetattr (pty .STDIN_FILENO )
116146 except tty .error :
117- # pty.STDIN_FILENO not a tty?
147+ # possible reason: current stdin is not a tty
118148 debug ("tty.tcgetattr(pty.STDIN_FILENO) failed" )
119149 mode = None
120150
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 :
128153 try :
129154 debug ("Setting pty.STDIN_FILENO window size" )
130- current_stdin_winsz = os .get_terminal_size (pty .STDIN_FILENO )
131-
132155 # Set number of columns and rows to be the
133156 # 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 )
137160
138161 # Were we able to set the window size
139162 # 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 ,
143165 "pty.STDIN_FILENO window size unchanged" )
144166 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
148170
149171 try :
150172 debug ("Calling pty.openpty()" )
151173 try :
152- master_fd , slave_fd = pty .openpty (mode , winsz )
174+ master_fd , slave_fd = pty .openpty (mode , new_stdin_winsz )
153175 except TypeError :
154176 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 } '" )
157178 except OSError :
158179 # " An optional feature could not be imported " ... ?
159180 raise unittest .SkipTest ("Pseudo-terminals (seemingly) not functional." )
@@ -163,15 +184,16 @@ def test_openpty(self):
163184 if mode :
164185 self .assertEqual (tty .tcgetattr (slave_fd ), mode ,
165186 "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 ,
169189 "openpty() failed to set slave window size" )
170190
171- # RELEVANT ANYMORE?
172191 # Solaris requires reading the fd before anything is returned.
173192 # My guess is that since we open and close the slave fd
174193 # 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.
175197
176198 # Ensure the fd is non-blocking in case there's nothing to read.
177199 blocking = os .get_blocking (master_fd )
@@ -205,13 +227,6 @@ def test_openpty(self):
205227 # to ignore this signal.
206228 os .close (master_fd )
207229
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-
215230 def test_fork (self ):
216231 debug ("calling pty.fork()" )
217232 pid , master_fd = pty .fork ()
@@ -295,8 +310,6 @@ def test_fork(self):
295310
296311 os .close (master_fd )
297312
298- # pty.fork() passed.
299-
300313 @expectedFailureOnBSD
301314 def test_master_read (self ):
302315 debug ("Calling pty.openpty()" )
@@ -407,6 +420,7 @@ def test__copy_eof_on_all(self):
407420 with self .assertRaises (IndexError ):
408421 pty ._copy (masters [0 ])
409422
423+
410424def tearDownModule ():
411425 reap_children ()
412426
0 commit comments