Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
gh-153291: Move the free-threaded readline tests to test_free_threading
The Argument Clinic getters are exercised there under the TSan CI job
(test_free_threading is in TSAN_TESTS; test_readline is not).
  • Loading branch information
harjothkhara committed Jul 9, 2026
commit f86b02900dd1d377b101bc494b3816b7d8300cde
47 changes: 47 additions & 0 deletions Lib/test/test_free_threading/test_readline.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import unittest

from test.support import threading_helper
from test.support import import_helper

readline = import_helper.import_module("readline")


@threading_helper.requires_working_threading()
class TestReadlineRaces(unittest.TestCase):
# get_completer()/get_pre_input_hook() must take the module critical
# section like their setters do; otherwise reading and Py_NewRef-ing the
# stored hook races the setter replacing it (gh-153291).

def test_completer_get_set(self):
def setter():
for _ in range(1000):
readline.set_completer(lambda text, state: None)
readline.set_completer(None)

def getter():
for _ in range(1000):
readline.get_completer()

original = readline.get_completer()
self.addCleanup(readline.set_completer, original)
threading_helper.run_concurrently([setter] * 2 + [getter] * 6)

@unittest.skipUnless(hasattr(readline, "set_pre_input_hook"),
"needs readline.set_pre_input_hook")
def test_pre_input_hook_get_set(self):
def setter():
for _ in range(1000):
readline.set_pre_input_hook(lambda: None)
readline.set_pre_input_hook(None)

def getter():
for _ in range(1000):
readline.get_pre_input_hook()

original = readline.get_pre_input_hook()
self.addCleanup(readline.set_pre_input_hook, original)
threading_helper.run_concurrently([setter] * 2 + [getter] * 6)


if __name__ == "__main__":
unittest.main()
38 changes: 0 additions & 38 deletions Lib/test/test_readline.py
Original file line number Diff line number Diff line change
Expand Up @@ -452,44 +452,6 @@ def completer_delims(b):
with threading_helper.start_threads(threads):
pass

@threading_helper.reap_threads
@threading_helper.requires_working_threading()
def test_free_threading_get_completer(self):
def completer(b):
b.wait()
for _ in range(100):
readline.get_completer()
readline.set_completer(lambda text, state: None)
readline.set_completer(None)
readline.get_completer()

count = 40
barrier = threading.Barrier(count)
threads = [threading.Thread(target=completer, args=(barrier,)) for _ in range(count)]

with threading_helper.start_threads(threads):
pass

@unittest.skipUnless(hasattr(readline, "get_pre_input_hook"),
"get_pre_input_hook not available")
@threading_helper.reap_threads
@threading_helper.requires_working_threading()
def test_free_threading_get_pre_input_hook(self):
def pre_input_hook(b):
b.wait()
for _ in range(100):
readline.get_pre_input_hook()
readline.set_pre_input_hook(lambda: None)
readline.set_pre_input_hook(None)
readline.get_pre_input_hook()

count = 40
barrier = threading.Barrier(count)
threads = [threading.Thread(target=pre_input_hook, args=(barrier,)) for _ in range(count)]

with threading_helper.start_threads(threads):
pass


if __name__ == "__main__":
unittest.main()
Loading