Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[3.13] gh-116402: Avoid readline in test_builtin TTY input tests (GH-122447) #122472

Merged
merged 1 commit into from
Jul 30, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 24 additions & 15 deletions Lib/test/test_builtin.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import asyncio
import builtins
import collections
import contextlib
import decimal
import fractions
import gc
Expand All @@ -30,6 +31,7 @@
from operator import neg
from test import support
from test.support import (cpython_only, swap_attr, maybe_get_event_loop_policy)
from test.support.import_helper import import_module
from test.support.os_helper import (EnvironmentVarGuard, TESTFN, unlink)
from test.support.script_helper import assert_python_ok
from test.support.warnings_helper import check_warnings
Expand Down Expand Up @@ -2369,7 +2371,8 @@ def child(wpipe):
print(ascii(input(prompt)), file=wpipe)
except BaseException as e:
print(ascii(f'{e.__class__.__name__}: {e!s}'), file=wpipe)
lines = self.run_child(child, terminal_input + b"\r\n")
with self.detach_readline():
lines = self.run_child(child, terminal_input + b"\r\n")
# Check we did exercise the GNU readline path
self.assertIn(lines[0], {'tty = True', 'tty = False'})
if lines[0] != 'tty = True':
Expand All @@ -2382,28 +2385,36 @@ def child(wpipe):
expected = terminal_input.decode(sys.stdin.encoding) # what else?
self.assertEqual(input_result, expected)

def test_input_tty(self):
# Test input() functionality when wired to a tty (the code path
# is different and invokes GNU readline if available).
self.check_input_tty("prompt", b"quux")

def skip_if_readline(self):
@contextlib.contextmanager
def detach_readline(self):
# bpo-13886: When the readline module is loaded, PyOS_Readline() uses
# the readline implementation. In some cases, the Python readline
# callback rlhandler() is called by readline with a string without
# non-ASCII characters. Skip tests on non-ASCII characters if the
# readline module is loaded, since test_builtin is not intended to test
# non-ASCII characters.
# Unlink readline temporarily from PyOS_Readline() for those tests,
# since test_builtin is not intended to test
# the readline module, but the builtins module.
if 'readline' in sys.modules:
self.skipTest("the readline module is loaded")
if "readline" in sys.modules:
c = import_module("ctypes")
fp_api = "PyOS_ReadlineFunctionPointer"
prev_value = c.c_void_p.in_dll(c.pythonapi, fp_api).value
c.c_void_p.in_dll(c.pythonapi, fp_api).value = None
try:
yield
finally:
c.c_void_p.in_dll(c.pythonapi, fp_api).value = prev_value
else:
yield

def test_input_tty(self):
# Test input() functionality when wired to a tty
self.check_input_tty("prompt", b"quux")

def test_input_tty_non_ascii(self):
self.skip_if_readline()
# Check stdin/stdout encoding is used when invoking PyOS_Readline()
self.check_input_tty("prompté", b"quux\xc3\xa9", "utf-8")

def test_input_tty_non_ascii_unicode_errors(self):
self.skip_if_readline()
# Check stdin/stdout error handler is used when invoking PyOS_Readline()
self.check_input_tty("prompté", b"quux\xe9", "ascii")

Expand All @@ -2413,14 +2424,12 @@ def test_input_tty_null_in_prompt(self):
'null characters')

def test_input_tty_nonencodable_prompt(self):
self.skip_if_readline()
self.check_input_tty("prompté", b"quux", "ascii", stdout_errors='strict',
expected="UnicodeEncodeError: 'ascii' codec can't encode "
"character '\\xe9' in position 6: ordinal not in "
"range(128)")

def test_input_tty_nondecodable_input(self):
self.skip_if_readline()
self.check_input_tty("prompt", b"quux\xe9", "ascii", stdin_errors='strict',
expected="UnicodeDecodeError: 'ascii' codec can't decode "
"byte 0xe9 in position 4: ordinal not in "
Expand Down
Loading