Skip to content
Merged
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
19 changes: 16 additions & 3 deletions code_sandboxes/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

Remote sandboxes (out-of-process execution via Jupyter kernel protocol):
- DockerSandbox: Docker container based, good isolation
- JupyterSandbox: Jupyter Server with persistent kernel state
- JupyterServerSandbox: Jupyter Server with persistent kernel state
- DatalayerSandbox: Cloud-based Datalayer runtime, full isolation
- GoogleColabSandbox: Google Colab runtime, connects to an assigned kernel
- KaggleSandbox: Kaggle runtime, connects to an interactive notebook kernel
Expand Down Expand Up @@ -91,7 +91,7 @@
)
from .google_colab_sandbox import GoogleColabSandbox
from .interfaces import ISandboxClient
from .jupyter_sandbox import JupyterSandbox
from .jupyter_server_sandbox import JupyterServerSandbox
from .kaggle import KAGGLE_API_TOKEN_ENV, KaggleKernelClient, parse_kaggle_channels_url
from .kaggle_execute import KaggleExecutionResult, KaggleKernelExecutor
from .kaggle_sandbox import KaggleSandbox
Expand Down Expand Up @@ -121,10 +121,23 @@
SnapshotInfo,
TunnelInfo,
)
from .providers import (
PROVIDERS,
ProviderRequirement,
SandboxProvider,
available_providers,
get_provider,
)
from .monty_sandbox import MontySandbox

__all__ = [
"KAGGLE_API_TOKEN_ENV",
# Providers
"PROVIDERS",
"ProviderRequirement",
"SandboxProvider",
"available_providers",
"get_provider",
# Models
"CodeError",
"CodeExecutionOutcome",
Expand All @@ -145,7 +158,7 @@
"GoogleColabKernelClient",
"GoogleColabSandbox",
"ISandboxClient",
"JupyterSandbox",
"JupyterServerSandbox",
"KaggleExecutionResult",
"KaggleKernelClient",
"KaggleKernelExecutor",
Expand Down
2 changes: 1 addition & 1 deletion code_sandboxes/__version__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@

"""Code Sandboxes."""

__version__ = "1.0.9"
__version__ = "1.0.10"
27 changes: 16 additions & 11 deletions code_sandboxes/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ def create( # noqa: C901
variant: The type of sandbox to create.
- "eval": Simple Python exec() based, minimal isolation
- "docker": Docker container based (requires Docker)
- "jupyter": Jupyter Server with persistent kernel state
- "jupyter-server": Jupyter Server with persistent kernel state
- "datalayer": Cloud-based Datalayer runtime (default)
config: Optional full configuration object (overrides individual params).
timeout: Default timeout for code execution in seconds.
Expand Down Expand Up @@ -286,7 +286,12 @@ def create( # noqa: C901

from .eval_sandbox import EvalSandbox

variant_value = variant.value if isinstance(variant, SandboxVariant) else variant
# In one normal form, as every dispatcher here reads it: the value of
# a variant may carry a dash — `jupyter-server` — and callers type
# either spelling.
variant_value = (
variant.value if isinstance(variant, SandboxVariant) else variant
).replace("-", "_")

Comment on lines +289 to 295
if variant_value == "eval":
sandbox = EvalSandbox(config=config, **kwargs)
Expand All @@ -295,10 +300,10 @@ def create( # noqa: C901
from .docker_sandbox import DockerSandbox

sandbox = DockerSandbox(config=config, **kwargs)
elif variant_value == "jupyter":
from .jupyter_sandbox import JupyterSandbox
elif variant_value == "jupyter_server":
from .jupyter_server_sandbox import JupyterServerSandbox

sandbox = JupyterSandbox(config=config, **kwargs)
sandbox = JupyterServerSandbox(config=config, **kwargs)
elif variant_value == "datalayer":
from .datalayer_sandbox import DatalayerSandbox

Expand All @@ -322,8 +327,8 @@ def create( # noqa: C901
else:
raise ValueError(
f"Unknown sandbox variant: {variant}. "
"Supported variants: eval, docker, jupyter, "
"datalayer, google_colab, kaggle, monty, modal"
"Supported variants: "
+ ", ".join(sorted(v.value for v in SandboxVariant))
)

# Set tags if provided
Expand Down Expand Up @@ -379,10 +384,10 @@ def list_environments(
from .docker_sandbox import DockerSandbox

return DockerSandbox.list_environments()
if variant_value == "jupyter":
from .jupyter_sandbox import JupyterSandbox
if variant_value == "jupyter_server":
from .jupyter_server_sandbox import JupyterServerSandbox

return JupyterSandbox.list_environments()
return JupyterServerSandbox.list_environments()
if variant_value == "monty":
from .monty_sandbox import MontySandbox

Expand All @@ -405,7 +410,7 @@ def list_environments(
return DatalayerSandbox.list_environments(**kwargs)
raise ValueError(
f"Unknown sandbox variant: {variant}. "
"Supported variants: eval, docker, jupyter, monty, modal, "
"Supported variants: eval, docker, jupyter-server, monty, modal, "
"kaggle, google_colab, datalayer"
)

Expand Down
10 changes: 5 additions & 5 deletions code_sandboxes/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
console = Console()

_SUPPORTED_REPL_VARIANTS = {
"jupyter",
"jupyter-server",
"docker",
"eval",
"monty",
Expand All @@ -40,7 +40,7 @@
def _root(ctx: typer.Context) -> None:
"""Code sandboxes CLI."""
if ctx.invoked_subcommand is None:
_run_repl(variant="jupyter")
_run_repl(variant="jupyter-server")


def _print_result(result: Any) -> None:
Expand Down Expand Up @@ -76,7 +76,7 @@ def _resolve_variant(variant: str | None) -> str:
else:
selected = typer.prompt(
"Sandbox variant",
default="jupyter",
default="jupyter-server",
show_default=True,
)
selected = selected.strip().lower()
Expand All @@ -102,7 +102,7 @@ def _resolve_variant_kwargs(
) -> dict[str, Any]:
kwargs: dict[str, Any] = {}

if variant == "jupyter":
if variant.strip().lower().replace("-", "_") == "jupyter_server":
# Match `jupyter console` behavior by launching local Jupyter on random port.
kwargs["port"] = 0

Expand Down Expand Up @@ -485,7 +485,7 @@ def create(
create_kwargs: dict[str, Any] = {}
if gpu:
create_kwargs["gpu"] = gpu
if variant.strip().lower().replace("-", "_") == "jupyter":
if variant.strip().lower().replace("-", "_") == "jupyter_server":
if environment:
create_kwargs["kernel_name"] = environment
elif environment:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
logger = logging.getLogger(__name__)


class JupyterSandbox(Sandbox):
class JupyterServerSandbox(Sandbox):
"""Jupyter Server sandbox using a persistent kernel.

Pass ``headers`` to send extra HTTP headers on every request to an external
Expand Down Expand Up @@ -129,13 +129,13 @@ def __init__(
def list_environments(cls) -> list[SandboxEnvironment]:
return [
SandboxEnvironment(
name="jupyter",
name="jupyter-server",
title="Jupyter",
language="python",
owner="local",
visibility="local",
burning_rate=0.0,
metadata={"variant": "jupyter"},
metadata={"variant": "jupyter-server"},
)
]

Expand Down Expand Up @@ -260,7 +260,7 @@ def _start_local_server_inprocess(self, workdir: str, port: int) -> None:
from jupyter_server.serverapp import ServerApp
except Exception as exc:
raise SandboxConfigurationError(
"jupyter_server is required for JupyterSandbox. "
"jupyter_server is required for JupyterServerSandbox. "
"Install it with: pip install code-sandboxes[test]"
) from exc

Expand Down Expand Up @@ -369,7 +369,7 @@ def start(self) -> None:
from jupyter_kernel_client import JupyterKernelClient
except ImportError as exc:
raise SandboxConfigurationError(
"jupyter-kernel-client is required for JupyterSandbox. "
"jupyter-kernel-client is required for JupyterServerSandbox. "
"Install it with: pip install code-sandboxes[test]"
) from exc

Expand Down Expand Up @@ -407,7 +407,7 @@ def start(self) -> None:
self._default_context = self.create_context("default")
self._info = SandboxInfo(
id=self._sandbox_id,
variant="jupyter",
variant="jupyter-server",
status=SandboxStatus.RUNNING,
created_at=time.time(),
name=self.config.name,
Expand Down Expand Up @@ -525,7 +525,7 @@ def run_code(
raise SandboxNotStartedError()

if language != "python":
raise ValueError(f"JupyterSandbox only supports Python, got: {language}")
raise ValueError(f"JupyterServerSandbox only supports Python, got: {language}")

started_at = time.time()

Expand Down
6 changes: 3 additions & 3 deletions code_sandboxes/kaggle_execute.py
Original file line number Diff line number Diff line change
Expand Up @@ -399,13 +399,13 @@ def execute(
A :class:`KaggleExecutionResult` describing the run.
"""
username = self._resolve_username()
slug = slug or _slugify(title or f"jkc-run-{uuid.uuid4().hex[:8]}")
slug = slug or _slugify(title or f"code-sandbox-run-{uuid.uuid4().hex[:8]}")
ref = f"{username}/{slug}"
title = title or slug
normalized_accelerator = _normalize_accelerator(accelerator)
resolved_enable_gpu = bool(enable_gpu or normalized_accelerator)

with tempfile.TemporaryDirectory(prefix="jkc-kaggle-") as tmp:
with tempfile.TemporaryDirectory(prefix="code-sandbox-kaggle-") as tmp:
folder = Path(tmp)
code_file = self._write_sources(folder, code, kernel_type, language)
self._write_metadata(
Expand Down Expand Up @@ -573,7 +573,7 @@ def _download_output(
) -> None:
try:
if output_dir is None:
output_dir = tempfile.mkdtemp(prefix="jkc-kaggle-out-")
output_dir = tempfile.mkdtemp(prefix="code-sandbox-kaggle-out-")
files = self.output(slug, output_dir)
result.output_dir = output_dir
result.output_files = files
Expand Down
Loading
Loading