Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/python-timeout-zero.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@e2b/python-sdk': patch
---

Keep an explicit `timeout=0` on sandbox create and connect instead of substituting the 300s default.
4 changes: 3 additions & 1 deletion packages/python-sdk/e2b/sandbox_async/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -1158,7 +1158,9 @@ async def _create(
else:
response = await SandboxApi._create_sandbox(
template=template or cls.default_template,
timeout=timeout or cls.default_sandbox_timeout,
timeout=(
timeout if timeout is not None else cls.default_sandbox_timeout
),
metadata=metadata,
env_vars=envs,
secure=secure,
Expand Down
4 changes: 3 additions & 1 deletion packages/python-sdk/e2b/sandbox_async/sandbox_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,9 @@ async def _cls_connect(
on_resume: SandboxOnResume = "restore",
**opts: Unpack[ApiParams],
) -> SandboxCreateResponse:
timeout = timeout or SandboxBase.default_sandbox_timeout
timeout = (
timeout if timeout is not None else SandboxBase.default_sandbox_timeout
)

# Sandbox is not running, resume it
config = ConnectionConfig(logger=logger, **cls._resolve_api_params(**opts))
Expand Down
4 changes: 3 additions & 1 deletion packages/python-sdk/e2b/sandbox_sync/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -1154,7 +1154,9 @@ def _create(
else:
response = SandboxApi._create_sandbox(
template=template or cls.default_template,
timeout=timeout or cls.default_sandbox_timeout,
timeout=(
timeout if timeout is not None else cls.default_sandbox_timeout
),
metadata=metadata,
env_vars=envs,
secure=secure,
Expand Down
4 changes: 3 additions & 1 deletion packages/python-sdk/e2b/sandbox_sync/sandbox_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,9 @@ def _cls_connect(
on_resume: SandboxOnResume = "restore",
**opts: Unpack[ApiParams],
) -> SandboxCreateResponse:
timeout = timeout or SandboxBase.default_sandbox_timeout
timeout = (
timeout if timeout is not None else SandboxBase.default_sandbox_timeout
)

config = ConnectionConfig(logger=logger, **cls._resolve_api_params(**opts))

Expand Down
83 changes: 83 additions & 0 deletions packages/python-sdk/tests/shared/sandbox/test_timeout.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
from types import SimpleNamespace
from unittest.mock import AsyncMock, Mock

from e2b import AsyncSandbox, Sandbox
from e2b.api.client.api.sandboxes import (
post_sandboxes,
post_sandboxes_sandbox_id_connect,
)
from e2b.api.client.models import Sandbox as SandboxModel
from e2b.sandbox.main import SandboxBase


def _created_sandbox():
return SimpleNamespace(
status_code=200,
parsed=SandboxModel(
client_id="client-id",
envd_version="0.2.4",
sandbox_id="sbx-test",
template_id="template-id",
),
)


def test_create_sends_timeout_zero(monkeypatch, test_api_key):
# timeout=0 is a value. `timeout or default` used to send 300 instead.
request = Mock(return_value=_created_sandbox())
monkeypatch.setattr(post_sandboxes, "sync_detailed", request)

Sandbox.create(api_key=test_api_key, timeout=0)

assert request.call_args.kwargs["body"].to_dict()["timeout"] == 0


def test_create_omitted_timeout_uses_default(monkeypatch, test_api_key):
request = Mock(return_value=_created_sandbox())
monkeypatch.setattr(post_sandboxes, "sync_detailed", request)

Sandbox.create(api_key=test_api_key)

assert (
request.call_args.kwargs["body"].to_dict()["timeout"]
== SandboxBase.default_sandbox_timeout
)


async def test_async_create_sends_timeout_zero(monkeypatch, test_api_key):
request = AsyncMock(return_value=_created_sandbox())
monkeypatch.setattr(post_sandboxes, "asyncio_detailed", request)

await AsyncSandbox.create(api_key=test_api_key, timeout=0)

assert request.call_args.kwargs["body"].to_dict()["timeout"] == 0


async def test_async_create_omitted_timeout_uses_default(monkeypatch, test_api_key):
request = AsyncMock(return_value=_created_sandbox())
monkeypatch.setattr(post_sandboxes, "asyncio_detailed", request)

await AsyncSandbox.create(api_key=test_api_key)

assert (
request.call_args.kwargs["body"].to_dict()["timeout"]
== SandboxBase.default_sandbox_timeout
)


def test_connect_sends_timeout_zero(monkeypatch, test_api_key):
request = Mock(return_value=_created_sandbox())
monkeypatch.setattr(post_sandboxes_sandbox_id_connect, "sync_detailed", request)

Sandbox.connect("sbx-test", timeout=0, api_key=test_api_key)

assert request.call_args.kwargs["body"].to_dict()["timeout"] == 0


async def test_async_connect_sends_timeout_zero(monkeypatch, test_api_key):
request = AsyncMock(return_value=_created_sandbox())
monkeypatch.setattr(post_sandboxes_sandbox_id_connect, "asyncio_detailed", request)

await AsyncSandbox.connect("sbx-test", timeout=0, api_key=test_api_key)

assert request.call_args.kwargs["body"].to_dict()["timeout"] == 0