|
5 | 5 | # the Apache 2.0 License: http://www.apache.org/licenses/LICENSE-2.0 |
6 | 6 |
|
7 | 7 |
|
8 | | -import sys |
| 8 | +import textwrap |
| 9 | +import threading |
9 | 10 | import unittest |
10 | 11 |
|
| 12 | +try: |
| 13 | + from concurrent import interpreters |
| 14 | +except ImportError: |
| 15 | + pass |
| 16 | +else: |
| 17 | + class TestSubinterpreters(unittest.TestCase): |
| 18 | + def test_record_module_loads_in_subinterpreter(self) -> None: |
| 19 | + def run_in_subinterpreter() -> None: |
| 20 | + interp = interpreters.create() |
11 | 21 |
|
12 | | -@unittest.skipIf( |
13 | | - sys.version_info < (3, 14), |
14 | | - "Subinterpreter support requires Python 3.14+", |
15 | | -) |
16 | | -class TestSubinterpreters(unittest.TestCase): |
17 | | - def setUp(self) -> None: |
18 | | - from concurrent import interpreters |
19 | | - self.interpreters = interpreters |
| 22 | + try: |
| 23 | + code = textwrap.dedent("""\ |
| 24 | + import asyncpg.protocol.record as record |
| 25 | + assert record.Record is not None |
| 26 | + """) |
| 27 | + interp.exec(code) |
| 28 | + finally: |
| 29 | + interp.close() |
20 | 30 |
|
21 | | - def test_record_module_loads_in_subinterpreter(self) -> None: |
22 | | - interp = self.interpreters.create() |
| 31 | + thread = threading.Thread(target=run_in_subinterpreter) |
| 32 | + thread.start() |
| 33 | + thread.join() |
23 | 34 |
|
24 | | - try: |
25 | | - code = """ |
26 | | -import asyncpg.protocol.record as record |
27 | | -assert record.Record is not None |
28 | | -""" |
29 | | - interp.exec(code) |
30 | | - finally: |
31 | | - interp.close() |
| 35 | + def test_record_module_state_isolation(self) -> None: |
| 36 | + import asyncpg.protocol.record |
32 | 37 |
|
33 | | - def test_record_module_state_isolation(self) -> None: |
34 | | - import asyncpg.protocol.record |
| 38 | + main_record_id = id(asyncpg.protocol.record.Record) |
35 | 39 |
|
36 | | - main_record_id = id(asyncpg.protocol.record.Record) |
| 40 | + def run_in_subinterpreter() -> None: |
| 41 | + interp = interpreters.create() |
37 | 42 |
|
38 | | - interp = self.interpreters.create() |
| 43 | + try: |
| 44 | + code = textwrap.dedent(f"""\ |
| 45 | + import asyncpg.protocol.record as record |
39 | 46 |
|
40 | | - try: |
41 | | - code = f""" |
42 | | -import asyncpg.protocol.record as record |
| 47 | + sub_record_id = id(record.Record) |
| 48 | + main_id = {main_record_id} |
43 | 49 |
|
44 | | -sub_record_id = id(record.Record) |
45 | | -main_id = {main_record_id} |
| 50 | + assert sub_record_id != main_id, ( |
| 51 | + f"Record type objects are the same: " |
| 52 | + f"{{sub_record_id}} == {{main_id}}. " |
| 53 | + f"This indicates shared global state." |
| 54 | + ) |
| 55 | + """) |
| 56 | + interp.exec(code) |
| 57 | + finally: |
| 58 | + interp.close() |
46 | 59 |
|
47 | | -assert sub_record_id != main_id, ( |
48 | | - f"Record type objects are the same: {{sub_record_id}} == {{main_id}}. " |
49 | | - "This indicates shared global state." |
50 | | -) |
51 | | -""" |
52 | | - interp.exec(code) |
53 | | - finally: |
54 | | - interp.close() |
| 60 | + thread = threading.Thread(target=run_in_subinterpreter) |
| 61 | + thread.start() |
| 62 | + thread.join() |
55 | 63 |
|
56 | 64 |
|
57 | 65 | if __name__ == "__main__": |
58 | | - unittest.main() |
| 66 | + _ = unittest.main() |
0 commit comments