| import unittest | |
| from test.support import import_helper | |
| from test.support import threading_helper | |
| readline = import_helper.import_module("readline") | |
| @threading_helper.requires_working_threading() | |
| class TestReadlineRaces(unittest.TestCase): | |
| def test_completer_delims_get_set(self): | |
| def worker(): | |
| for _ in range(100): | |
| readline.get_completer_delims() | |
| readline.set_completer_delims( | |
| ' \t\n`@#%^&*()=+[{]}\\|;:\'",<>?') | |
| readline.set_completer_delims( | |
| ' \t\n`@#%^&*()=+[{]}\\|;:\'",<>?') | |
| readline.get_completer_delims() | |
| threading_helper.run_concurrently(worker, nthreads=40) | |
| # 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() |