@@ -2269,30 +2269,37 @@ def _run_child(self, child, terminal_input):
2269
2269
2270
2270
return lines
2271
2271
2272
- def check_input_tty (self , prompt , terminal_input , stdio_encoding = None ):
2272
+ def check_input_tty (self , prompt , terminal_input , stdio_encoding = None , * ,
2273
+ expected = None ,
2274
+ stdin_errors = 'surrogateescape' ,
2275
+ stdout_errors = 'replace' ):
2273
2276
if not sys .stdin .isatty () or not sys .stdout .isatty ():
2274
2277
self .skipTest ("stdin and stdout must be ttys" )
2275
2278
def child (wpipe ):
2276
2279
# Check the error handlers are accounted for
2277
2280
if stdio_encoding :
2278
2281
sys .stdin = io .TextIOWrapper (sys .stdin .detach (),
2279
2282
encoding = stdio_encoding ,
2280
- errors = 'surrogateescape' )
2283
+ errors = stdin_errors )
2281
2284
sys .stdout = io .TextIOWrapper (sys .stdout .detach (),
2282
2285
encoding = stdio_encoding ,
2283
- errors = 'replace' )
2286
+ errors = stdout_errors )
2284
2287
print ("tty =" , sys .stdin .isatty () and sys .stdout .isatty (), file = wpipe )
2285
- print (ascii (input (prompt )), file = wpipe )
2288
+ try :
2289
+ print (ascii (input (prompt )), file = wpipe )
2290
+ except BaseException as e :
2291
+ print (ascii (f'{ e .__class__ .__name__ } : { e !s} ' ), file = wpipe )
2286
2292
lines = self .run_child (child , terminal_input + b"\r \n " )
2287
2293
# Check we did exercise the GNU readline path
2288
2294
self .assertIn (lines [0 ], {'tty = True' , 'tty = False' })
2289
2295
if lines [0 ] != 'tty = True' :
2290
2296
self .skipTest ("standard IO in should have been a tty" )
2291
2297
input_result = eval (lines [1 ]) # ascii() -> eval() roundtrip
2292
- if stdio_encoding :
2293
- expected = terminal_input .decode (stdio_encoding , 'surrogateescape' )
2294
- else :
2295
- expected = terminal_input .decode (sys .stdin .encoding ) # what else?
2298
+ if expected is None :
2299
+ if stdio_encoding :
2300
+ expected = terminal_input .decode (stdio_encoding , 'surrogateescape' )
2301
+ else :
2302
+ expected = terminal_input .decode (sys .stdin .encoding ) # what else?
2296
2303
self .assertEqual (input_result , expected )
2297
2304
2298
2305
def test_input_tty (self ):
@@ -2313,13 +2320,32 @@ def skip_if_readline(self):
2313
2320
def test_input_tty_non_ascii (self ):
2314
2321
self .skip_if_readline ()
2315
2322
# Check stdin/stdout encoding is used when invoking PyOS_Readline()
2316
- self .check_input_tty ("prompté" , b"quux\xe9 " , "utf-8" )
2323
+ self .check_input_tty ("prompté" , b"quux\xc3 \xa9 " , "utf-8" )
2317
2324
2318
2325
def test_input_tty_non_ascii_unicode_errors (self ):
2319
2326
self .skip_if_readline ()
2320
2327
# Check stdin/stdout error handler is used when invoking PyOS_Readline()
2321
2328
self .check_input_tty ("prompté" , b"quux\xe9 " , "ascii" )
2322
2329
2330
+ def test_input_tty_null_in_prompt (self ):
2331
+ self .check_input_tty ("prompt\0 " , b"" ,
2332
+ expected = 'ValueError: input: prompt string cannot contain '
2333
+ 'null characters' )
2334
+
2335
+ def test_input_tty_nonencodable_prompt (self ):
2336
+ self .skip_if_readline ()
2337
+ self .check_input_tty ("prompté" , b"quux" , "ascii" , stdout_errors = 'strict' ,
2338
+ expected = "UnicodeEncodeError: 'ascii' codec can't encode "
2339
+ "character '\\ xe9' in position 6: ordinal not in "
2340
+ "range(128)" )
2341
+
2342
+ def test_input_tty_nondecodable_input (self ):
2343
+ self .skip_if_readline ()
2344
+ self .check_input_tty ("prompt" , b"quux\xe9 " , "ascii" , stdin_errors = 'strict' ,
2345
+ expected = "UnicodeDecodeError: 'ascii' codec can't decode "
2346
+ "byte 0xe9 in position 4: ordinal not in "
2347
+ "range(128)" )
2348
+
2323
2349
def test_input_no_stdout_fileno (self ):
2324
2350
# Issue #24402: If stdin is the original terminal but stdout.fileno()
2325
2351
# fails, do not use the original stdout file descriptor
0 commit comments