11import asyncio
2- from contextlib import asynccontextmanager
2+ from contextlib import asynccontextmanager , contextmanager
33from dataclasses import asdict , dataclass , field
44import json
55from typing import AsyncIterator
66import uuid
77from pydantic import BaseModel , Field
88from typing_extensions import Literal
99
10+ from deno_sandbox .bridge import AsyncBridge
1011from deno_sandbox .options import Options , get_internal_options
11- from deno_sandbox .rpc import AsyncRpcClient
12+ from deno_sandbox .rpc import AsyncRpcClient , RpcClient
1213from deno_sandbox .sandbox_generated import (
1314 AsyncSandboxHandle as GeneratedAsyncSandboxHandle ,
1415 SpawnArgs ,
1516 AsyncSandboxProcess as GeneratedAsyncSandboxProcess ,
17+ SandboxHandle ,
1618)
1719from deno_sandbox .transport import (
1820 Transport ,
@@ -80,6 +82,27 @@ class AppConfig:
8082 memory_mb : int | None
8183
8284
85+ class Sandbox :
86+ def __init__ (self , options = None ):
87+ self ._bridge = AsyncBridge ()
88+ self ._async_sandbox = AsyncSandbox (options )
89+
90+ @contextmanager
91+ def create (self , options = None ):
92+ async_cm = self ._async_sandbox .create (options )
93+ async_handle = self ._bridge .run (async_cm .__aenter__ ())
94+
95+ rpc = RpcClient (async_handle ._rpc , self ._bridge )
96+
97+ try :
98+ yield SandboxHandle (rpc , async_handle .id )
99+ finally :
100+ self ._bridge .run (async_cm .__aexit__ (None , None , None ))
101+
102+ def close (self ):
103+ self ._bridge .stop ()
104+
105+
83106class AsyncSandboxProcess (GeneratedAsyncSandboxProcess ):
84107 async def spawn (self , args : SpawnArgs ) -> RemoteProcess :
85108 result : SpawnResult = await super ().spawn (args )
@@ -99,6 +122,7 @@ def __init__(
99122 ):
100123 self .__options = get_internal_options (options or Options ())
101124 self ._transport_factory = WebSocketTransportFactory ()
125+ self ._rpc : AsyncRpcClient | None = None
102126
103127 async def _init_transport (self , app_config : AppConfig ) -> Transport :
104128 transport = self ._transport_factory .create_transport ()
@@ -128,8 +152,8 @@ async def create(
128152 transport = await self ._init_transport (app_config )
129153
130154 try :
131- rpc = AsyncRpcClient (transport )
132- yield AsyncSandboxHandle (rpc , sandbox_id )
155+ self . _rpc = AsyncRpcClient (transport )
156+ yield AsyncSandboxHandle (self . _rpc , sandbox_id )
133157 finally :
134158 await transport .close ()
135159
0 commit comments