Skip to content

Commit 62b3761

Browse files
committed
Beta submodule
1 parent c8d968e commit 62b3761

File tree

2 files changed

+238
-209
lines changed

2 files changed

+238
-209
lines changed

packages/python-sdk/e2b/sandbox_async/main.py

Lines changed: 233 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,40 @@
22
import logging
33
import httpx
44

5-
from typing import Dict, Optional, TypedDict, overload, List
5+
from typing import (
6+
Dict,
7+
Optional,
8+
TypedDict,
9+
overload,
10+
List,
11+
Type,
12+
)
613

714
from packaging.version import Version
815
from typing_extensions import Unpack
916

17+
from e2b.api import AsyncApiClient, handle_api_exception
18+
from e2b.api.client.api.sandboxes import (
19+
post_sandboxes_sandbox_id_pause,
20+
post_sandboxes_sandbox_id_resume,
21+
)
22+
from e2b.api.client.models import ResumedSandbox
1023
from e2b.api.client.types import Unset
1124
from e2b.connection_config import ConnectionConfig, ApiParams
1225
from e2b.envd.api import ENVD_API_HEALTH_ROUTE, ahandle_envd_api_exception
13-
from e2b.exceptions import format_request_timeout_error, SandboxException
14-
from e2b.sandbox.sandbox_api import SandboxMetrics
26+
from e2b.exceptions import (
27+
format_request_timeout_error,
28+
SandboxException,
29+
NotFoundException,
30+
)
31+
from e2b.sandbox.main import SandboxBase
32+
from e2b.sandbox.sandbox_api import SandboxMetrics, SandboxQueryBeta
1533
from e2b.sandbox.utils import class_method_variant
1634
from e2b.sandbox_async.filesystem.filesystem import Filesystem
1735
from e2b.sandbox_async.commands.command import Commands
1836
from e2b.sandbox_async.commands.pty import Pty
1937
from e2b.sandbox_async.sandbox_api import SandboxApi, SandboxInfo
38+
from e2b.sandbox_async.sandbox_beta import AsyncSandboxPaginator
2039

2140
logger = logging.getLogger(__name__)
2241

@@ -45,7 +64,210 @@ class AsyncSandboxOpts(TypedDict):
4564
connection_config: ConnectionConfig
4665

4766

48-
class AsyncSandbox(SandboxApi):
67+
class AsyncBeta:
68+
def __init__(self, sandbox: "AsyncSandbox"):
69+
self._sandbox = sandbox
70+
71+
@staticmethod
72+
def list(
73+
query: Optional[SandboxQueryBeta] = None,
74+
limit: Optional[int] = None,
75+
next_token: Optional[str] = None,
76+
**opts: Unpack[ApiParams],
77+
) -> AsyncSandboxPaginator:
78+
"""
79+
List all running sandboxes.
80+
81+
:param query: Filter the list of sandboxes by metadata or state, e.g. `SandboxListQuery(metadata={"key": "value"})` or `SandboxListQuery(state=[SandboxState.RUNNING])`
82+
:param limit: Maximum number of sandboxes to return
83+
:param next_token: Token for pagination
84+
85+
:return: List of running sandboxes
86+
"""
87+
return AsyncSandboxPaginator(
88+
query=query,
89+
limit=limit,
90+
next_token=next_token,
91+
**opts,
92+
)
93+
94+
@overload
95+
async def pause(
96+
self,
97+
**opts: Unpack[ApiParams],
98+
) -> str:
99+
"""
100+
Pause the sandbox.
101+
102+
:return: Sandbox ID that can be used to resume the sandbox
103+
"""
104+
...
105+
106+
@overload
107+
@staticmethod
108+
async def pause(
109+
sandbox_id: str,
110+
**opts: Unpack[ApiParams],
111+
) -> str:
112+
"""
113+
Pause the sandbox specified by sandbox ID.
114+
115+
:param sandbox_id: Sandbox ID
116+
117+
:return: Sandbox ID that can be used to resume the sandbox
118+
"""
119+
...
120+
121+
@class_method_variant("_cls_pause")
122+
async def pause(
123+
self,
124+
**opts: Unpack[ApiParams],
125+
) -> str:
126+
"""
127+
Pause the sandbox.
128+
129+
:param request_timeout: Timeout for the request in **seconds**
130+
131+
:return: Sandbox ID that can be used to resume the sandbox
132+
"""
133+
134+
await self._cls_pause(
135+
sandbox_id=self._sandbox.sandbox_id,
136+
**opts,
137+
)
138+
139+
return self._sandbox.sandbox_id
140+
141+
@classmethod
142+
async def _cls_pause(
143+
cls,
144+
sandbox_id: str,
145+
**opts: Unpack[ApiParams],
146+
) -> bool:
147+
config = ConnectionConfig(**opts)
148+
149+
async with AsyncApiClient(
150+
config,
151+
limits=SandboxBase._limits,
152+
) as api_client:
153+
res = await post_sandboxes_sandbox_id_pause.asyncio_detailed(
154+
sandbox_id,
155+
client=api_client,
156+
)
157+
158+
if res.status_code == 404:
159+
raise NotFoundException(f"Sandbox {sandbox_id} not found")
160+
161+
if res.status_code == 409:
162+
return False
163+
164+
if res.status_code >= 300:
165+
raise handle_api_exception(res)
166+
167+
return True
168+
169+
@overload
170+
async def resume(
171+
self,
172+
timeout: Optional[int] = None,
173+
**opts: Unpack[ApiParams],
174+
) -> "AsyncSandbox":
175+
"""
176+
Resume the sandbox.
177+
178+
:return: A running sandbox instance
179+
"""
180+
...
181+
182+
@overload
183+
@staticmethod
184+
async def resume(
185+
sandbox_id: str,
186+
timeout: Optional[int] = None,
187+
**opts: Unpack[ApiParams],
188+
) -> "AsyncSandbox":
189+
"""
190+
Resume the sandbox.
191+
192+
:param sandbox_id: Sandbox ID
193+
:param timeout: Timeout for the sandbox in **seconds**
194+
195+
:return: A running sandbox instance
196+
"""
197+
...
198+
199+
@class_method_variant("_cls_resume")
200+
async def resume(
201+
self,
202+
timeout: Optional[int] = None,
203+
**opts: Unpack[ApiParams],
204+
) -> "AsyncSandbox":
205+
"""
206+
Resume the sandbox.
207+
208+
The **default sandbox timeout of 300 seconds** will be used for the resumed sandbox.
209+
If you pass a custom timeout via the `timeout` parameter, it will be used instead.
210+
211+
:param sandbox_id: Sandbox ID
212+
:param timeout: Timeout for the sandbox in **seconds**
213+
214+
:return: A running sandbox instance
215+
"""
216+
217+
await self._cls_resume(
218+
sandbox_id=self._sandbox.sandbox_id,
219+
timeout=timeout,
220+
**opts,
221+
)
222+
223+
return await self._sandbox.connect(
224+
sandbox_id=self._sandbox.sandbox_id,
225+
**opts,
226+
)
227+
228+
@classmethod
229+
async def _cls_resume(
230+
cls,
231+
sandbox_id: str,
232+
timeout: Optional[int] = None,
233+
**opts: Unpack[ApiParams],
234+
) -> bool:
235+
timeout = timeout or SandboxBase.default_sandbox_timeout
236+
237+
config = ConnectionConfig(**opts)
238+
239+
async with AsyncApiClient(
240+
config,
241+
limits=SandboxBase._limits,
242+
) as api_client:
243+
res = await post_sandboxes_sandbox_id_resume.asyncio_detailed(
244+
sandbox_id,
245+
client=api_client,
246+
body=ResumedSandbox(timeout=timeout),
247+
)
248+
249+
if res.status_code == 404:
250+
raise NotFoundException(f"Paused sandbox {sandbox_id} not found")
251+
252+
if res.status_code == 409:
253+
return False
254+
255+
if res.status_code >= 300:
256+
raise handle_api_exception(res)
257+
258+
return True
259+
260+
261+
class _AsyncSandboxMeta(type):
262+
"""Metaclass for AsyncSandbox to provide class-level beta access."""
263+
264+
@property
265+
def beta(cls) -> Type[AsyncBeta]:
266+
"""Access to beta features at class level."""
267+
return AsyncBeta
268+
269+
270+
class AsyncSandbox(SandboxApi, metaclass=_AsyncSandboxMeta):
49271
"""
50272
E2B cloud sandbox is a secure and isolated cloud environment.
51273
@@ -89,6 +311,13 @@ def pty(self) -> Pty:
89311
"""
90312
return self._pty
91313

314+
@property
315+
def beta(self) -> AsyncBeta:
316+
"""
317+
Module for beta features.
318+
"""
319+
return AsyncBeta(self)
320+
92321
def __init__(self, **opts: Unpack[AsyncSandboxOpts]):
93322
"""
94323
Use `AsyncSandbox.create()` to create a new sandbox instead.

0 commit comments

Comments
 (0)