11import pytest
22import pytest_asyncio
33import os
4+ import asyncio
45
56from logging import warning
67
1011timeout = 60
1112
1213
14+ # Override the event loop so it never closes during test execution
15+ # This helps with pytest-xdist and prevents "Event loop is closed" errors
16+ @pytest .fixture (scope = "session" )
17+ def event_loop ():
18+ """Create a session-scoped event loop for all async tests."""
19+ try :
20+ loop = asyncio .get_running_loop ()
21+ except RuntimeError :
22+ loop = asyncio .new_event_loop ()
23+ yield loop
24+ loop .close ()
25+
26+
1327@pytest .fixture ()
1428def template ():
1529 return os .getenv ("E2B_TESTS_TEMPLATE" ) or "code-interpreter-v1"
@@ -31,20 +45,39 @@ def sandbox(template, debug):
3145 )
3246
3347
34- @pytest_asyncio .fixture
35- async def async_sandbox ( template , debug ):
36- async_sandbox = await AsyncSandbox . create ( template , timeout = timeout , debug = debug )
48+ @pytest .fixture
49+ def async_sandbox_factory ( request , template , debug , event_loop ):
50+ """Factory for creating async sandboxes with proper cleanup."""
3751
38- try :
39- yield async_sandbox
40- finally :
41- try :
42- await async_sandbox .kill ()
43- except : # noqa: E722
44- if not debug :
45- warning (
46- "Failed to kill sandbox — this is expected if the test runs with local envd."
47- )
52+ async def factory (template_override = None , ** kwargs ):
53+ template_name = template_override or template
54+ kwargs .setdefault ("timeout" , timeout )
55+ kwargs .setdefault ("debug" , debug )
56+
57+ sandbox = await AsyncSandbox .create (template_name , ** kwargs )
58+
59+ def kill ():
60+ async def _kill ():
61+ try :
62+ await sandbox .kill ()
63+ except : # noqa: E722
64+ if not debug :
65+ warning (
66+ "Failed to kill sandbox — this is expected if the test runs with local envd."
67+ )
68+
69+ event_loop .run_until_complete (_kill ())
70+
71+ request .addfinalizer (kill )
72+ return sandbox
73+
74+ return factory
75+
76+
77+ @pytest .fixture
78+ async def async_sandbox (async_sandbox_factory ):
79+ """Default async sandbox fixture."""
80+ return await async_sandbox_factory ()
4881
4982
5083@pytest .fixture
0 commit comments