44import asyncio
55import builtins
66import collections
7+ import contextlib
78import decimal
89import fractions
910import gc
3132from operator import neg
3233from test import support
3334from test .support import (cpython_only , swap_attr , maybe_get_event_loop_policy )
35+ from test .support .import_helper import import_module
3436from test .support .os_helper import (EnvironmentVarGuard , TESTFN , unlink )
3537from test .support .script_helper import assert_python_ok
3638from test .support .warnings_helper import check_warnings
@@ -2412,7 +2414,8 @@ def child(wpipe):
24122414 print (ascii (input (prompt )), file = wpipe )
24132415 except BaseException as e :
24142416 print (ascii (f'{ e .__class__ .__name__ } : { e !s} ' ), file = wpipe )
2415- lines = self .run_child (child , terminal_input + b"\r \n " )
2417+ with self .detach_readline ():
2418+ lines = self .run_child (child , terminal_input + b"\r \n " )
24162419 # Check we did exercise the GNU readline path
24172420 self .assertIn (lines [0 ], {'tty = True' , 'tty = False' })
24182421 if lines [0 ] != 'tty = True' :
@@ -2425,28 +2428,36 @@ def child(wpipe):
24252428 expected = terminal_input .decode (sys .stdin .encoding ) # what else?
24262429 self .assertEqual (input_result , expected )
24272430
2428- def test_input_tty (self ):
2429- # Test input() functionality when wired to a tty (the code path
2430- # is different and invokes GNU readline if available).
2431- self .check_input_tty ("prompt" , b"quux" )
2432-
2433- def skip_if_readline (self ):
2431+ @contextlib .contextmanager
2432+ def detach_readline (self ):
24342433 # bpo-13886: When the readline module is loaded, PyOS_Readline() uses
24352434 # the readline implementation. In some cases, the Python readline
24362435 # callback rlhandler() is called by readline with a string without
2437- # non-ASCII characters. Skip tests on non-ASCII characters if the
2438- # readline module is loaded, since test_builtin is not intended to test
2436+ # non-ASCII characters.
2437+ # Unlink readline temporarily from PyOS_Readline() for those tests,
2438+ # since test_builtin is not intended to test
24392439 # the readline module, but the builtins module.
2440- if 'readline' in sys .modules :
2441- self .skipTest ("the readline module is loaded" )
2440+ if "readline" in sys .modules :
2441+ c = import_module ("ctypes" )
2442+ fp_api = "PyOS_ReadlineFunctionPointer"
2443+ prev_value = c .c_void_p .in_dll (c .pythonapi , fp_api ).value
2444+ c .c_void_p .in_dll (c .pythonapi , fp_api ).value = None
2445+ try :
2446+ yield
2447+ finally :
2448+ c .c_void_p .in_dll (c .pythonapi , fp_api ).value = prev_value
2449+ else :
2450+ yield
2451+
2452+ def test_input_tty (self ):
2453+ # Test input() functionality when wired to a tty
2454+ self .check_input_tty ("prompt" , b"quux" )
24422455
24432456 def test_input_tty_non_ascii (self ):
2444- self .skip_if_readline ()
24452457 # Check stdin/stdout encoding is used when invoking PyOS_Readline()
24462458 self .check_input_tty ("prompté" , b"quux\xc3 \xa9 " , "utf-8" )
24472459
24482460 def test_input_tty_non_ascii_unicode_errors (self ):
2449- self .skip_if_readline ()
24502461 # Check stdin/stdout error handler is used when invoking PyOS_Readline()
24512462 self .check_input_tty ("prompté" , b"quux\xe9 " , "ascii" )
24522463
@@ -2456,14 +2467,12 @@ def test_input_tty_null_in_prompt(self):
24562467 'null characters' )
24572468
24582469 def test_input_tty_nonencodable_prompt (self ):
2459- self .skip_if_readline ()
24602470 self .check_input_tty ("prompté" , b"quux" , "ascii" , stdout_errors = 'strict' ,
24612471 expected = "UnicodeEncodeError: 'ascii' codec can't encode "
24622472 "character '\\ xe9' in position 6: ordinal not in "
24632473 "range(128)" )
24642474
24652475 def test_input_tty_nondecodable_input (self ):
2466- self .skip_if_readline ()
24672476 self .check_input_tty ("prompt" , b"quux\xe9 " , "ascii" , stdin_errors = 'strict' ,
24682477 expected = "UnicodeDecodeError: 'ascii' codec can't decode "
24692478 "byte 0xe9 in position 4: ordinal not in "
0 commit comments