|  | 
| 6 | 6 | import sys | 
| 7 | 7 | import tempfile | 
| 8 | 8 | import textwrap | 
|  | 9 | +import threading | 
| 9 | 10 | import unittest | 
|  | 11 | +from test import support | 
|  | 12 | +from test.support import threading_helper | 
| 10 | 13 | from test.support import verbose | 
| 11 | 14 | from test.support.import_helper import import_module | 
| 12 | 15 | from test.support.os_helper import unlink, temp_dir, TESTFN | 
| @@ -403,5 +406,62 @@ def test_write_read_limited_history(self): | 
| 403 | 406 |         # See TestHistoryManipulation for the full test. | 
| 404 | 407 | 
 | 
| 405 | 408 | 
 | 
|  | 409 | +@unittest.skipUnless(support.Py_GIL_DISABLED, 'these tests can only possibly fail with GIL disabled') | 
|  | 410 | +class FreeThreadingTest(unittest.TestCase): | 
|  | 411 | +    def check(self, funcs, *args): | 
|  | 412 | +        barrier = threading.Barrier(len(funcs)) | 
|  | 413 | +        threads = [] | 
|  | 414 | + | 
|  | 415 | +        for func in funcs: | 
|  | 416 | +            thread = threading.Thread(target=func, args=(barrier, *args)) | 
|  | 417 | + | 
|  | 418 | +            threads.append(thread) | 
|  | 419 | + | 
|  | 420 | +        with threading_helper.start_threads(threads): | 
|  | 421 | +            pass | 
|  | 422 | + | 
|  | 423 | +    @threading_helper.reap_threads | 
|  | 424 | +    @threading_helper.requires_working_threading() | 
|  | 425 | +    def test_free_threading(self): | 
|  | 426 | +        def completer_delims(b): | 
|  | 427 | +            b.wait() | 
|  | 428 | +            for _ in range(100): | 
|  | 429 | +                readline.get_completer_delims() | 
|  | 430 | +                readline.set_completer_delims(' \t\n`@#%^&*()=+[{]}\\|;:\'",<>?') | 
|  | 431 | +                readline.set_completer_delims(' \t\n`@#%^&*()=+[{]}\\|;:\'",<>?') | 
|  | 432 | +                readline.get_completer_delims() | 
|  | 433 | + | 
|  | 434 | +        self.check([completer_delims] * 100) | 
|  | 435 | + | 
|  | 436 | +    @threading_helper.reap_threads | 
|  | 437 | +    @threading_helper.requires_working_threading() | 
|  | 438 | +    def test_free_threading_doctest_difflib(self): | 
|  | 439 | +        import doctest, difflib | 
|  | 440 | + | 
|  | 441 | +        preserve_stdout = sys.stdout | 
|  | 442 | +        COUNT = 40 | 
|  | 443 | +        funcs = [] | 
|  | 444 | +        results = [False] * COUNT | 
|  | 445 | + | 
|  | 446 | +        for i in range(COUNT): | 
|  | 447 | +            def func(b, i=i): | 
|  | 448 | +                try: | 
|  | 449 | +                    doctest.testmod(difflib) | 
|  | 450 | +                except RecursionError: | 
|  | 451 | +                    results[i] = True | 
|  | 452 | +                except Exception: | 
|  | 453 | +                    pass | 
|  | 454 | +                else: | 
|  | 455 | +                    results[i] = True | 
|  | 456 | + | 
|  | 457 | +            funcs.append(func) | 
|  | 458 | + | 
|  | 459 | +        self.check(funcs) | 
|  | 460 | + | 
|  | 461 | +        sys.stdout = preserve_stdout | 
|  | 462 | + | 
|  | 463 | +        self.assertTrue(all(results)) | 
|  | 464 | + | 
|  | 465 | + | 
| 406 | 466 | if __name__ == "__main__": | 
| 407 | 467 |     unittest.main() | 
0 commit comments