|
8 | 8 | import threading |
9 | 9 | import types |
10 | 10 | import unittest |
| 11 | +import tempfile |
| 12 | +import os |
11 | 13 |
|
12 | 14 | try: |
13 | 15 | import _testcapi |
@@ -598,6 +600,41 @@ def test_error_during_module_execution_propagates(self): |
598 | 600 | self.assertEqual(result.returncode, 0, f"stdout: {result.stdout}, stderr: {result.stderr}") |
599 | 601 | self.assertIn("OK", result.stdout) |
600 | 602 |
|
| 603 | + def test_circular_lazy_import_does_not_crash_for_gh_144727(self): |
| 604 | + with tempfile.TemporaryDirectory() as tmpdir: |
| 605 | + a_path = os.path.join(tmpdir, "a.py") |
| 606 | + b_path = os.path.join(tmpdir, "b.py") |
| 607 | + |
| 608 | + with open(a_path, "w") as f: |
| 609 | + f.write(textwrap.dedent("""\ |
| 610 | + lazy import b |
| 611 | +
|
| 612 | + def something(): |
| 613 | + b.hello() |
| 614 | +
|
| 615 | + something() |
| 616 | + """)) |
| 617 | + |
| 618 | + with open(b_path, "w") as f: |
| 619 | + f.write(textwrap.dedent("""\ |
| 620 | + lazy import a |
| 621 | +
|
| 622 | + def hello(): |
| 623 | + print(a) |
| 624 | + """)) |
| 625 | + |
| 626 | + result = subprocess.run( |
| 627 | + [sys.executable, a_path], |
| 628 | + capture_output=True, |
| 629 | + text=True, |
| 630 | + cwd=tmpdir, |
| 631 | + ) |
| 632 | + # Must not crash (segfault = -11 on Linux, 3221225477 on Windows) |
| 633 | + self.assertNotEqual(result.returncode, -11, |
| 634 | + f"Process crashed with SIGSEGV\nstderr: {result.stderr}") |
| 635 | + # Should get a proper Python error, not a crash |
| 636 | + self.assertIn("Error", result.stderr) |
| 637 | + |
601 | 638 |
|
602 | 639 | class GlobalsAndDictTests(unittest.TestCase): |
603 | 640 | """Tests for globals() and __dict__ behavior with lazy imports. |
|
0 commit comments