code-sandboxes 1.9.36__tar.gz → 1.9.39__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- code_sandboxes-1.9.36/.github/workflows/build.yml → code_sandboxes-1.9.39/.github/workflows/build.yaml +1 -1
- code_sandboxes-1.9.36/.github/workflows/py-code-style.yml → code_sandboxes-1.9.39/.github/workflows/py-code-style.yaml +5 -5
- code_sandboxes-1.9.36/.github/workflows/py-tests.yml → code_sandboxes-1.9.39/.github/workflows/py-tests.yaml +5 -5
- code_sandboxes-1.9.36/.github/workflows/py-typing.yml → code_sandboxes-1.9.39/.github/workflows/py-typing.yaml +5 -5
- code_sandboxes-1.9.39/.github/workflows/release.yaml +105 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/CHANGELOG.md +44 -1
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/PKG-INFO +4 -3
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/README.md +1 -0
- code_sandboxes-1.9.39/RELEASE.md +35 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/__init__.py +11 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/__version__.py +1 -1
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/base.py +9 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/cli.py +1 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/client.py +109 -15
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/environments/adapters/datalayer.py +24 -3
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/environments/adapters/daytona.py +1 -1
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/environments/adapters/e2b.py +1 -1
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/environments/adapters/modal.py +1 -1
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/environments/contract.py +5 -3
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/environments/doctor/datalayer_sandbox.py +1 -1
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/environments/resolve.py +82 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/environments/resolve_conda.py +15 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/manage.py +20 -1
- code_sandboxes-1.9.39/code_sandboxes/marimo_cells.py +261 -0
- code_sandboxes-1.9.39/code_sandboxes/marimo_reactive.py +183 -0
- code_sandboxes-1.9.39/code_sandboxes/marimo_sandbox.py +367 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/modal_sandbox.py +1 -1
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/models.py +29 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/docs/contribute/index.mdx +5 -5
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/docs/environments/contract.mdx +3 -3
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/docs/environments/specification.mdx +1 -1
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/docs/index.mdx +1 -1
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/docs/providers/index.mdx +2 -1
- code_sandboxes-1.9.39/docs/docs/providers/marimo.mdx +230 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/docs/providers/modal.mdx +24 -8
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/docusaurus.config.js +6 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/package.json +1 -1
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/pyproject.toml +2 -2
- code_sandboxes-1.9.39/tests/egress_logs/buildctl-base.log +16 -0
- code_sandboxes-1.9.39/tests/egress_logs/buildctl-curl.log +41 -0
- code_sandboxes-1.9.39/tests/egress_logs/buildctl-pip.log +43 -0
- code_sandboxes-1.9.39/tests/egress_logs/buildctl-uv.log +54 -0
- code_sandboxes-1.9.39/tests/egress_logs/micromamba.log +30 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_environment_bases.py +1 -1
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_environment_conformance.py +1 -1
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_environment_contract.py +1 -1
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_environment_datalayer_builder.py +7 -4
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_environment_daytona_builder.py +1 -1
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_environment_doctor.py +4 -4
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_environment_e2b_builder.py +1 -1
- code_sandboxes-1.9.39/tests/test_environment_egress_refusals.py +146 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_manage.py +1 -0
- code_sandboxes-1.9.39/tests/test_marimo_cells.py +140 -0
- code_sandboxes-1.9.39/tests/test_marimo_sandbox.py +317 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_modal_google_colab_sandbox.py +1 -1
- /code_sandboxes-1.9.36/.github/workflows/environments-live.yml → /code_sandboxes-1.9.39/.github/workflows/environments-live.yaml +0 -0
- /code_sandboxes-1.9.36/.github/workflows/reusable-python.yml → /code_sandboxes-1.9.39/.github/workflows/reusable-python.yaml +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/.gitignore +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/.licenserc.yaml +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/.pre-commit-config.yaml +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/.vscode/settings.json +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/Dockerfile +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/LICENSE +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/Makefile +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/bridge_mount.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/builds.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/cloudflare_sandbox.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/commands.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/console.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/contents.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/coreweave_sandbox.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/datalayer_sandbox.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/daytona_sandbox.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/docker_sandbox.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/e2b_sandbox.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/environments/__init__.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/environments/__main__.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/environments/accounts.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/environments/adapters/__init__.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/environments/adapters/managed.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/environments/attest.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/environments/bases.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/environments/breaker.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/environments/build_secrets.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/environments/builders.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/environments/canonical.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/environments/conformance.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/environments/constraints/sandbox-contract-v1.txt +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/environments/constraints/wheelhouse/README.md +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/environments/constraints/wheelhouse/jupyter_server-2.21.0+datalayer.1-py3-none-any.whl +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/environments/doctor/__init__.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/environments/doctor/build.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/environments/doctor/report.schema.json +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/environments/errors.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/environments/files.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/environments/image_import.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/environments/lifecycle.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/environments/policy.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/environments/redact.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/environments/schema.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/environments/spec.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/eval_sandbox.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/exceptions.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/filesystem.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/google_colab.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/google_colab_sandbox.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/interfaces.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/jupyter_ingress.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/jupyter_server_sandbox.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/kaggle.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/kaggle_execute.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/kaggle_live.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/kaggle_sandbox.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/lifecycle.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/monty_sandbox.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/provider_ingress.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/code_sandboxes/providers.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docker/Dockerfile +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/.gitignore +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/LICENSE +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/Makefile +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/README.md +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/babel.config.js +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/docs/api-reference/_category_.yml +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/docs/api-reference/index.mdx +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/docs/cli/_category_.yml +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/docs/cli/index.mdx +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/docs/contribute/_category_.yml +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/docs/environments/_category_.yml +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/docs/environments/index.mdx +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/docs/environments/spike-2026-09.mdx +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/docs/examples/_category_.yml +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/docs/examples/index.mdx +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/docs/guide/_category_.yml +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/docs/guide/index.mdx +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/docs/install/_category_.yml +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/docs/install/index.mdx +0 -0
- /code_sandboxes-1.9.36/docs/docs/provider-ingress.mdx → /code_sandboxes-1.9.39/docs/docs/provider-ingress/index.mdx +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/docs/providers/_category_.yml +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/docs/providers/cloudflare.mdx +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/docs/providers/coreweave.mdx +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/docs/providers/datalayer.mdx +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/docs/providers/daytona.mdx +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/docs/providers/docker.mdx +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/docs/providers/e2b.mdx +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/docs/providers/eval.mdx +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/docs/providers/google-colab.mdx +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/docs/providers/jupyter-server.mdx +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/docs/providers/kaggle.mdx +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/docs/providers/monty.mdx +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/sidebars.js +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/src/components/HomepageRow1.js +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/src/components/HomepageRow1.module.css +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/src/components/HomepageRow2.js +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/src/components/HomepageRow2.module.css +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/src/components/HomepageRow3.js +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/src/components/HomepageRow3.module.css +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/src/css/custom.css +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/src/pages/index.module.css +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/src/pages/markdown-page.md +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/src/theme/CustomDocItem.tsx +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/src/theme/IconsTitle.tsx +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/static/img/bricks.svg +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/static/img/building-construction.svg +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/static/img/cloud-sun.svg +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/static/img/cloud.svg +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/static/img/collaboration.svg +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/static/img/copy-left.svg +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/static/img/datalayer/logo.png +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/static/img/datalayer/logo.svg +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/static/img/datalayer/personas/business.svg +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/static/img/datalayer/personas/data-scientist.svg +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/static/img/datalayer/personas/devops.svg +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/static/img/datalayer/project/project-line.svg +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/static/img/favicon.ico +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/static/img/jupyter.svg +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/static/img/open-source.svg +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/static/img/react-js.svg +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/static/img/react-js2.svg +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/static/img/ringed-planet.svg +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/static/img/robot.svg +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/static/img/rocket.svg +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/static/img/shield.svg +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/static/img/sparkles.svg +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/static/img/streamlit.gif +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/static/img/super-hero.svg +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/static/img/target.svg +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/docs/static/img/thumbs-up.svg +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/examples/README.md +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/examples/exec/Makefile +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/examples/exec/cloudflare_sandbox_example.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/examples/exec/coreweave_sandbox_example.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/examples/exec/datalayer_sandbox_example.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/examples/exec/daytona_sandbox_example.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/examples/exec/docker_sandbox_example.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/examples/exec/e2b_sandbox_example.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/examples/exec/eval_sandbox_example.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/examples/exec/google_colab_sandbox_example.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/examples/exec/jupyter_server_sandbox_example.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/examples/exec/kaggle_sandbox_example.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/examples/exec/modal_sandbox_example.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/examples/exec/monty_sandbox_example.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/examples/repl/Makefile +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/examples/repl/cloudflare_sandbox_example.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/examples/repl/coreweave_sandbox_example.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/examples/repl/datalayer_sandbox_example.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/examples/repl/daytona_sandbox_example.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/examples/repl/docker_sandbox_example.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/examples/repl/e2b_sandbox_example.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/examples/repl/eval_sandbox_example.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/examples/repl/google_colab_sandbox_example.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/examples/repl/jupyter_server_sandbox_example.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/examples/repl/kaggle_sandbox_example.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/examples/repl/modal_sandbox_example.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/examples/repl/monty_sandbox_example.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/schemas/environment-v1alpha1.json +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/__init__.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/conftest.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_a_datalayer_sandbox_can_be_interrupted.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_bridge_mount.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_builds.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_cli_exec.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_cli_repl.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_client.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_client_contents.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_client_files.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_client_outcome_error_output.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_cloudflare.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_commands_envelope.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_console.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_contents_contract.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_contents_live_matrix.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_coreweave.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_datalayer_sandbox.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_daytona.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_e2b.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_environment_accounts.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_environment_attest.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_environment_breaker.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_environment_build_secrets.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_environment_builders.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_environment_canonical.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_environment_constraints.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_environment_cross_variant_report.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_environment_dockerfile_source.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_environment_errors.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_environment_image_import.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_environment_lifecycle.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_environment_live_matrix.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_environment_managed_builders.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_environment_modal_builder.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_environment_organization_policy.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_environment_redact.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_environment_resolve.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_environment_resolve_conda.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_environment_spec.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_environment_spec_organization_policy.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_eval.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_every_variant_has_a_real_interrupt.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_factory.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_google_colab.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_integration.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_jupyter_ingress.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_jupyter_server.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_jupyter_server_streaming.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_kaggle.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_kaggle_execute.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_kaggle_live.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_kaggle_session.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_kernel_client_compatibility.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_lifecycle_vocabulary.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_manage_datalayer.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_modal_session.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_models.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_output_line_fidelity.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_provider_catalog_names.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_provider_ingress.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_providers.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_sandboxes.py +0 -0
- {code_sandboxes-1.9.36 → code_sandboxes-1.9.39}/tests/test_the_kill_relaunch_drill.py +0 -0
|
@@ -13,7 +13,7 @@ jobs:
|
|
|
13
13
|
strategy:
|
|
14
14
|
matrix:
|
|
15
15
|
python-version: ['3.11', '3.12']
|
|
16
|
-
uses: ./.github/workflows/reusable-python.
|
|
16
|
+
uses: ./.github/workflows/reusable-python.yaml
|
|
17
17
|
with:
|
|
18
18
|
python-version: ${{ matrix.python-version }}
|
|
19
19
|
install-extras: test,typing,datalayer
|
|
@@ -13,8 +13,8 @@ on:
|
|
|
13
13
|
- '.pre-commit-config.yaml'
|
|
14
14
|
- 'ruff.toml'
|
|
15
15
|
- '.ruff.toml'
|
|
16
|
-
- '.github/workflows/py-code-style.
|
|
17
|
-
- '.github/workflows/reusable-python.
|
|
16
|
+
- '.github/workflows/py-code-style.yaml'
|
|
17
|
+
- '.github/workflows/reusable-python.yaml'
|
|
18
18
|
pull_request:
|
|
19
19
|
branches:
|
|
20
20
|
- main
|
|
@@ -27,8 +27,8 @@ on:
|
|
|
27
27
|
- '.pre-commit-config.yaml'
|
|
28
28
|
- 'ruff.toml'
|
|
29
29
|
- '.ruff.toml'
|
|
30
|
-
- '.github/workflows/py-code-style.
|
|
31
|
-
- '.github/workflows/reusable-python.
|
|
30
|
+
- '.github/workflows/py-code-style.yaml'
|
|
31
|
+
- '.github/workflows/reusable-python.yaml'
|
|
32
32
|
workflow_dispatch:
|
|
33
33
|
|
|
34
34
|
concurrency:
|
|
@@ -37,7 +37,7 @@ concurrency:
|
|
|
37
37
|
|
|
38
38
|
jobs:
|
|
39
39
|
check-code-style:
|
|
40
|
-
uses: ./.github/workflows/reusable-python.
|
|
40
|
+
uses: ./.github/workflows/reusable-python.yaml
|
|
41
41
|
with:
|
|
42
42
|
python-version: '3.11'
|
|
43
43
|
extra-packages: pre-commit
|
|
@@ -11,8 +11,8 @@ on:
|
|
|
11
11
|
- 'setup.py'
|
|
12
12
|
- 'requirements*.txt'
|
|
13
13
|
- '**/*.py'
|
|
14
|
-
- '.github/workflows/py-tests.
|
|
15
|
-
- '.github/workflows/reusable-python.
|
|
14
|
+
- '.github/workflows/py-tests.yaml'
|
|
15
|
+
- '.github/workflows/reusable-python.yaml'
|
|
16
16
|
pull_request:
|
|
17
17
|
branches:
|
|
18
18
|
- main
|
|
@@ -23,8 +23,8 @@ on:
|
|
|
23
23
|
- 'setup.py'
|
|
24
24
|
- 'requirements*.txt'
|
|
25
25
|
- '**/*.py'
|
|
26
|
-
- '.github/workflows/py-tests.
|
|
27
|
-
- '.github/workflows/reusable-python.
|
|
26
|
+
- '.github/workflows/py-tests.yaml'
|
|
27
|
+
- '.github/workflows/reusable-python.yaml'
|
|
28
28
|
|
|
29
29
|
workflow_dispatch:
|
|
30
30
|
|
|
@@ -34,7 +34,7 @@ jobs:
|
|
|
34
34
|
max-parallel: 1
|
|
35
35
|
matrix:
|
|
36
36
|
python-version: ['3.10', '3.11', '3.12', '3.13']
|
|
37
|
-
uses: ./.github/workflows/reusable-python.
|
|
37
|
+
uses: ./.github/workflows/reusable-python.yaml
|
|
38
38
|
with:
|
|
39
39
|
python-version: ${{ matrix.python-version }}
|
|
40
40
|
install-extras: test,datalayer
|
|
@@ -12,8 +12,8 @@ on:
|
|
|
12
12
|
- 'setup.py'
|
|
13
13
|
- 'mypy.ini'
|
|
14
14
|
- '.mypy.ini'
|
|
15
|
-
- '.github/workflows/py-typing.
|
|
16
|
-
- '.github/workflows/reusable-python.
|
|
15
|
+
- '.github/workflows/py-typing.yaml'
|
|
16
|
+
- '.github/workflows/reusable-python.yaml'
|
|
17
17
|
pull_request:
|
|
18
18
|
branches:
|
|
19
19
|
- main
|
|
@@ -25,8 +25,8 @@ on:
|
|
|
25
25
|
- 'setup.py'
|
|
26
26
|
- 'mypy.ini'
|
|
27
27
|
- '.mypy.ini'
|
|
28
|
-
- '.github/workflows/py-typing.
|
|
29
|
-
- '.github/workflows/reusable-python.
|
|
28
|
+
- '.github/workflows/py-typing.yaml'
|
|
29
|
+
- '.github/workflows/reusable-python.yaml'
|
|
30
30
|
workflow_dispatch:
|
|
31
31
|
|
|
32
32
|
concurrency:
|
|
@@ -35,7 +35,7 @@ concurrency:
|
|
|
35
35
|
|
|
36
36
|
jobs:
|
|
37
37
|
type-check:
|
|
38
|
-
uses: ./.github/workflows/reusable-python.
|
|
38
|
+
uses: ./.github/workflows/reusable-python.yaml
|
|
39
39
|
with:
|
|
40
40
|
python-version: '3.12'
|
|
41
41
|
install-extras: typing
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# Copyright (c) 2023-2026 Datalayer, Inc.
|
|
2
|
+
# Distributed under the terms of the BSD 3-Clause License.
|
|
3
|
+
|
|
4
|
+
# Publishes the release a tag names to PyPI, with no stored token: PyPI
|
|
5
|
+
# trusts this workflow file (OIDC trusted publishing, through the `pypi`
|
|
6
|
+
# environment). The tag must name the version in code_sandboxes/__version__.py; a
|
|
7
|
+
# version already published is skipped. See RELEASE.md.
|
|
8
|
+
|
|
9
|
+
name: Release
|
|
10
|
+
|
|
11
|
+
on:
|
|
12
|
+
push:
|
|
13
|
+
tags:
|
|
14
|
+
- 'v*'
|
|
15
|
+
|
|
16
|
+
concurrency:
|
|
17
|
+
group: release-${{ github.ref }}
|
|
18
|
+
cancel-in-progress: false
|
|
19
|
+
|
|
20
|
+
permissions:
|
|
21
|
+
contents: read
|
|
22
|
+
|
|
23
|
+
jobs:
|
|
24
|
+
build:
|
|
25
|
+
runs-on: ubuntu-latest
|
|
26
|
+
outputs:
|
|
27
|
+
python: ${{ steps.plan.outputs.python }}
|
|
28
|
+
steps:
|
|
29
|
+
- uses: actions/checkout@v4
|
|
30
|
+
|
|
31
|
+
- uses: actions/setup-python@v5
|
|
32
|
+
with:
|
|
33
|
+
python-version: '3.12'
|
|
34
|
+
|
|
35
|
+
- name: Check the tag names the version the package carries
|
|
36
|
+
run: |
|
|
37
|
+
set -euo pipefail
|
|
38
|
+
tag="${GITHUB_REF_NAME#v}"
|
|
39
|
+
version="$(python -c "import re;print(re.search(r'__version__\s*=\s*[\"\']([^\"\']+)', open('code_sandboxes/__version__.py').read())[1])")"
|
|
40
|
+
echo "tag=$tag version=$version"
|
|
41
|
+
test "$tag" = "$version"
|
|
42
|
+
|
|
43
|
+
- name: Find whether it is published yet
|
|
44
|
+
id: plan
|
|
45
|
+
run: |
|
|
46
|
+
set -euo pipefail
|
|
47
|
+
version="${GITHUB_REF_NAME#v}"
|
|
48
|
+
status="$(curl -sL -o /dev/null -w '%{http_code}' "https://pypi.org/pypi/code-sandboxes/$version/json")"
|
|
49
|
+
if [ "$status" = "200" ]; then
|
|
50
|
+
echo "PyPI: code-sandboxes $version is already published, skipping"
|
|
51
|
+
echo "python=" >> "$GITHUB_OUTPUT"
|
|
52
|
+
else
|
|
53
|
+
echo "PyPI: code-sandboxes $version will be published"
|
|
54
|
+
echo "python=yes" >> "$GITHUB_OUTPUT"
|
|
55
|
+
fi
|
|
56
|
+
|
|
57
|
+
- name: Build
|
|
58
|
+
if: steps.plan.outputs.python != ''
|
|
59
|
+
run: |
|
|
60
|
+
set -euo pipefail
|
|
61
|
+
python -m pip install --upgrade pip build
|
|
62
|
+
python -m build --sdist --wheel --outdir dist .
|
|
63
|
+
ls -la dist
|
|
64
|
+
|
|
65
|
+
- uses: actions/upload-artifact@v4
|
|
66
|
+
if: steps.plan.outputs.python != ''
|
|
67
|
+
with:
|
|
68
|
+
name: python
|
|
69
|
+
path: dist/*
|
|
70
|
+
|
|
71
|
+
pypi:
|
|
72
|
+
needs: build
|
|
73
|
+
if: needs.build.outputs.python != ''
|
|
74
|
+
runs-on: ubuntu-latest
|
|
75
|
+
environment: pypi
|
|
76
|
+
permissions:
|
|
77
|
+
id-token: write
|
|
78
|
+
steps:
|
|
79
|
+
- uses: actions/download-artifact@v4
|
|
80
|
+
with:
|
|
81
|
+
name: python
|
|
82
|
+
path: dist
|
|
83
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
84
|
+
with:
|
|
85
|
+
skip-existing: true
|
|
86
|
+
|
|
87
|
+
release:
|
|
88
|
+
name: GitHub release
|
|
89
|
+
needs: [build, pypi]
|
|
90
|
+
if: always() && needs.build.result == 'success' && needs.pypi.result != 'failure'
|
|
91
|
+
runs-on: ubuntu-latest
|
|
92
|
+
permissions:
|
|
93
|
+
contents: write
|
|
94
|
+
steps:
|
|
95
|
+
- uses: actions/checkout@v4
|
|
96
|
+
with:
|
|
97
|
+
fetch-depth: 0
|
|
98
|
+
- name: Create the release with generated notes
|
|
99
|
+
run: |
|
|
100
|
+
version="${GITHUB_REF_NAME#v}"
|
|
101
|
+
gh release view "$GITHUB_REF_NAME" >/dev/null 2>&1 && exit 0
|
|
102
|
+
gh release create "$GITHUB_REF_NAME" --title "Release $version" --generate-notes \
|
|
103
|
+
--notes "- [PyPI code-sandboxes](https://pypi.org/project/code-sandboxes/$version/)"
|
|
104
|
+
env:
|
|
105
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -8,6 +8,49 @@
|
|
|
8
8
|
|
|
9
9
|
## Unreleased
|
|
10
10
|
|
|
11
|
+
## 1.9.39
|
|
12
|
+
|
|
13
|
+
- The GitHub workflow files are all `.yaml` now (`build`, `py-tests`,
|
|
14
|
+
`py-code-style`, `py-typing`, `reusable-python`, `environments-live`), the
|
|
15
|
+
spelling `release.yaml` already had; the reusable workflow's callers and
|
|
16
|
+
the contributing page follow.
|
|
17
|
+
- **Marimo reactivity through the Jupyter-shaped API** (#37). `run_code`
|
|
18
|
+
names its cell through the execution context (`Context(id=...)`; the same
|
|
19
|
+
id replaces the cell) and the result says what happened: `cell_id`, and
|
|
20
|
+
`reactions` — every cell re-run because of it, each a `Reaction` with its
|
|
21
|
+
code and its own `ExecutionResult`. `CodeSandboxClient.execute`,
|
|
22
|
+
`execute_code` and `execute_code_streaming` take `cell_id`; a reply carries
|
|
23
|
+
the reactions under `marimo` with their own Jupyter-shaped outputs;
|
|
24
|
+
`execute_interactive` emits them after the cell's own, each message tagged
|
|
25
|
+
`metadata.marimo = {cell_id, reaction}`; the stream tags every event with
|
|
26
|
+
`marimo_cell_id`. The client passes `run_cell`, `register_cell`,
|
|
27
|
+
`remove_cell`, `plan`, `graph` and `cells` through to a reactive sandbox and
|
|
28
|
+
says so with `reactive`. The `marimo_reactions` extra attribute is replaced
|
|
29
|
+
by the typed `reactions` field. Nothing changes on the wire.
|
|
30
|
+
|
|
31
|
+
## 1.9.38
|
|
32
|
+
|
|
33
|
+
- **The environments line and main are one branch again**: everything
|
|
34
|
+
released from `feat/env-custom` as 1.9.13 through 1.9.37 (custom
|
|
35
|
+
environments: resolve, build, attest, sign, the egress proxy, conda
|
|
36
|
+
artifacts, the contract's working directory) is on `main`, rebased onto
|
|
37
|
+
the marimo sandbox. The `1.9.13` entry below is what PyPI's 1.9.13 shipped;
|
|
38
|
+
main's own "1.9.13: the marimo sandbox" never reached PyPI (the version was
|
|
39
|
+
taken) and is this release instead:
|
|
40
|
+
- **`marimo` sandbox** (#34, #35): a Jupyter server sandbox whose kernel also
|
|
41
|
+
holds Marimo's dataflow graph. `run_cell(cell_id, code)` runs a cell, then
|
|
42
|
+
the cells that depend on what it defined, in dependency order; a failing
|
|
43
|
+
cell stops the reaction. `register_cell`, `remove_cell`, `plan`, `graph`
|
|
44
|
+
and `cells` expose the graph; `run_code` keeps working, each call a cell of
|
|
45
|
+
its own, with the re-run cell ids on the result as `marimo_reactions`. The
|
|
46
|
+
graph is Marimo's own (`marimo._runtime.dataflow`), installed into the
|
|
47
|
+
kernel by one execute request and asked over the Jupyter protocol; marimo
|
|
48
|
+
is pip-installed into a kernel that lacks it unless `install_marimo=False`.
|
|
49
|
+
`get_manager("marimo")` is the `jupyter-server` manager under the marimo
|
|
50
|
+
variant. The same helper source drives jupyter-react's `variant="marimo"`.
|
|
51
|
+
- Releases are cut by a `v*` tag now (`.github/workflows/release.yaml`,
|
|
52
|
+
trusted publishing); see RELEASE.md.
|
|
53
|
+
|
|
11
54
|
## 1.9.18
|
|
12
55
|
|
|
13
56
|
- **A lock no longer carries a wall clock, so the build cache can hit**
|
|
@@ -314,7 +357,7 @@
|
|
|
314
357
|
that `stop()` skipped entirely, orphaned for good. Fixed identically in
|
|
315
358
|
`daytona_sandbox.py`, `modal_sandbox.py` and `e2b_sandbox.py`.
|
|
316
359
|
- **A nightly live matrix for the three managed builders**
|
|
317
|
-
(`.github/workflows/environments-live.
|
|
360
|
+
(`.github/workflows/environments-live.yaml`, PLAN_ENV.md E2-11). Builds a
|
|
318
361
|
real artifact on each real provider from a real, hash-verified lock,
|
|
319
362
|
launches a sandbox from it, and runs the formal core tier — opening (or
|
|
320
363
|
commenting on) an issue naming the provider and the check on a genuine
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: code_sandboxes
|
|
3
|
-
Version: 1.9.
|
|
3
|
+
Version: 1.9.39
|
|
4
4
|
Project-URL: Home, https://github.com/datalayer/code-sandboxes
|
|
5
5
|
Author-email: Datalayer <info@datalayer.io>
|
|
6
6
|
License: BSD 3-Clause License
|
|
@@ -59,7 +59,7 @@ Requires-Dist: kaggle>=1.6; extra == 'all'
|
|
|
59
59
|
Requires-Dist: modal>=1.5.2; extra == 'all'
|
|
60
60
|
Requires-Dist: pydantic-monty; extra == 'all'
|
|
61
61
|
Provides-Extra: bridge
|
|
62
|
-
Requires-Dist: datalayer-core>=1.
|
|
62
|
+
Requires-Dist: datalayer-core>=1.2.12; extra == 'bridge'
|
|
63
63
|
Requires-Dist: fusepy>=3.0; extra == 'bridge'
|
|
64
64
|
Requires-Dist: websockets>=12; extra == 'bridge'
|
|
65
65
|
Provides-Extra: cloudflare
|
|
@@ -67,7 +67,7 @@ Requires-Dist: httpx>=0.27; extra == 'cloudflare'
|
|
|
67
67
|
Provides-Extra: coreweave
|
|
68
68
|
Requires-Dist: cwsandbox>=1.6; extra == 'coreweave'
|
|
69
69
|
Provides-Extra: datalayer
|
|
70
|
-
Requires-Dist: agent-runtimes>=1.
|
|
70
|
+
Requires-Dist: agent-runtimes>=1.3.13; extra == 'datalayer'
|
|
71
71
|
Provides-Extra: daytona
|
|
72
72
|
Requires-Dist: daytona>=0.205.1; extra == 'daytona'
|
|
73
73
|
Provides-Extra: docker
|
|
@@ -127,6 +127,7 @@ Canonical variant names:
|
|
|
127
127
|
- `google-colab`
|
|
128
128
|
- `jupyter-server`
|
|
129
129
|
- `kaggle`
|
|
130
|
+
- `marimo`
|
|
130
131
|
- `modal`
|
|
131
132
|
- `monty`
|
|
132
133
|
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
~ Copyright (c) 2023-2026 Datalayer, Inc.
|
|
3
|
+
~
|
|
4
|
+
~ BSD 3-Clause License
|
|
5
|
+
-->
|
|
6
|
+
|
|
7
|
+
# Making a release
|
|
8
|
+
|
|
9
|
+
A tag releases `code-sandboxes` to PyPI, with no stored token: PyPI trusts
|
|
10
|
+
`.github/workflows/release.yaml` through OIDC (trusted publishing, GitHub
|
|
11
|
+
environment `pypi`). The version lives in `code_sandboxes/__version__.py`, which
|
|
12
|
+
hatch reads too.
|
|
13
|
+
|
|
14
|
+
## Steps
|
|
15
|
+
|
|
16
|
+
1. Bump `__version__` on a branch and open a pull request.
|
|
17
|
+
|
|
18
|
+
1. Merge, then tag the merge commit and push the tag:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
git checkout main && git pull
|
|
22
|
+
git tag vX.Y.Z
|
|
23
|
+
git push origin vX.Y.Z
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
1. The `Release` workflow checks that the tag names the version, builds the
|
|
27
|
+
wheel and the sdist, publishes them unless PyPI already has that version,
|
|
28
|
+
and creates a GitHub release with generated notes.
|
|
29
|
+
|
|
30
|
+
## Trusted publishing
|
|
31
|
+
|
|
32
|
+
PyPI project `code-sandboxes`: owner `datalayer`, repository `code-sandboxes`, workflow
|
|
33
|
+
`release.yaml`, environment `pypi`. The registry matches the repository,
|
|
34
|
+
the workflow filename and the environment exactly; renaming any of them
|
|
35
|
+
means re-registering.
|
|
@@ -14,6 +14,7 @@ sandboxes (in-process execution):
|
|
|
14
14
|
Remote sandboxes (out-of-process execution via Jupyter kernel protocol):
|
|
15
15
|
- DockerSandbox: Docker container based, good isolation
|
|
16
16
|
- JupyterServerSandbox: Jupyter Server with persistent kernel state
|
|
17
|
+
- MarimoSandbox: a Jupyter Server kernel holding Marimo's reactive cell graph
|
|
17
18
|
- DatalayerSandbox: Cloud-based Datalayer runtime, full isolation
|
|
18
19
|
- GoogleColabSandbox: Google Colab runtime, connects to an assigned kernel
|
|
19
20
|
- KaggleSandbox: Kaggle runtime, connects to an interactive notebook kernel
|
|
@@ -156,6 +157,8 @@ from .manage import (
|
|
|
156
157
|
get_manager,
|
|
157
158
|
manageable_variants,
|
|
158
159
|
)
|
|
160
|
+
from .marimo_cells import CellReply, CellsRun, MarimoCells
|
|
161
|
+
from .marimo_sandbox import CellRun, MarimoRun, MarimoSandbox
|
|
159
162
|
from .modal_sandbox import ModalSandbox
|
|
160
163
|
from .models import (
|
|
161
164
|
CodeError,
|
|
@@ -168,6 +171,7 @@ from .models import (
|
|
|
168
171
|
MIMEType,
|
|
169
172
|
OutputHandler,
|
|
170
173
|
OutputMessage,
|
|
174
|
+
Reaction,
|
|
171
175
|
ResourceConfig,
|
|
172
176
|
Result,
|
|
173
177
|
SandboxConfig,
|
|
@@ -202,6 +206,9 @@ __all__ = [
|
|
|
202
206
|
"RUNTIMES_API_PREFIX",
|
|
203
207
|
"BuildEntry",
|
|
204
208
|
"BuiltArtifact",
|
|
209
|
+
"CellReply",
|
|
210
|
+
"CellRun",
|
|
211
|
+
"CellsRun",
|
|
205
212
|
"CloudflareSandbox",
|
|
206
213
|
"CodeError",
|
|
207
214
|
"CodeExecutionOutcome",
|
|
@@ -240,6 +247,9 @@ __all__ = [
|
|
|
240
247
|
"Logs",
|
|
241
248
|
"MIMEType",
|
|
242
249
|
"ManifestLocation",
|
|
250
|
+
"MarimoCells",
|
|
251
|
+
"MarimoRun",
|
|
252
|
+
"MarimoSandbox",
|
|
243
253
|
"MaterializeEntry",
|
|
244
254
|
"ModalSandbox",
|
|
245
255
|
"MontySandbox",
|
|
@@ -248,6 +258,7 @@ __all__ = [
|
|
|
248
258
|
"PreparedAttachment",
|
|
249
259
|
"ProcessHandle",
|
|
250
260
|
"ProviderRequirement",
|
|
261
|
+
"Reaction",
|
|
251
262
|
"ResourceConfig",
|
|
252
263
|
"Result",
|
|
253
264
|
"Sandbox",
|
|
@@ -534,6 +534,7 @@ class Sandbox(ABC):
|
|
|
534
534
|
- "eval": Simple Python exec() based, minimal isolation
|
|
535
535
|
- "docker": Docker container based (requires Docker)
|
|
536
536
|
- "jupyter-server": Jupyter Server with persistent kernel state
|
|
537
|
+
- "marimo": Jupyter Server whose kernel holds Marimo's reactive cell graph
|
|
537
538
|
- "datalayer": Cloud-based Datalayer runtime (default)
|
|
538
539
|
config: Optional full configuration object (overrides individual params).
|
|
539
540
|
timeout: Default timeout for code execution in seconds.
|
|
@@ -623,6 +624,10 @@ class Sandbox(ABC):
|
|
|
623
624
|
from .jupyter_server_sandbox import JupyterServerSandbox
|
|
624
625
|
|
|
625
626
|
sandbox = JupyterServerSandbox(config=config, **kwargs)
|
|
627
|
+
elif variant_value == "marimo":
|
|
628
|
+
from .marimo_sandbox import MarimoSandbox
|
|
629
|
+
|
|
630
|
+
sandbox = MarimoSandbox(config=config, **kwargs)
|
|
626
631
|
elif variant_value == "datalayer":
|
|
627
632
|
from .datalayer_sandbox import DatalayerSandbox
|
|
628
633
|
|
|
@@ -721,6 +726,10 @@ class Sandbox(ABC):
|
|
|
721
726
|
from .jupyter_server_sandbox import JupyterServerSandbox
|
|
722
727
|
|
|
723
728
|
return JupyterServerSandbox.list_environments()
|
|
729
|
+
if variant_value == "marimo":
|
|
730
|
+
from .marimo_sandbox import MarimoSandbox
|
|
731
|
+
|
|
732
|
+
return MarimoSandbox.list_environments()
|
|
724
733
|
if variant_value == "monty":
|
|
725
734
|
from .monty_sandbox import MontySandbox
|
|
726
735
|
|
|
@@ -60,6 +60,7 @@ from .contents import (
|
|
|
60
60
|
from .filesystem import FileInfo, SandboxFilesystem
|
|
61
61
|
from .models import (
|
|
62
62
|
CodeError,
|
|
63
|
+
Context,
|
|
63
64
|
ExecutionResult,
|
|
64
65
|
OutputMessage,
|
|
65
66
|
Result,
|
|
@@ -114,11 +115,32 @@ def execution_result_to_reply(execution: ExecutionResult) -> dict[str, Any]:
|
|
|
114
115
|
}
|
|
115
116
|
)
|
|
116
117
|
|
|
117
|
-
|
|
118
|
+
reply: dict[str, Any] = {
|
|
118
119
|
"execution_count": execution.execution_count,
|
|
119
120
|
"outputs": outputs,
|
|
120
121
|
"status": "ok" if execution.success else "error",
|
|
121
122
|
}
|
|
123
|
+
if execution.cell_id is not None or execution.reactions:
|
|
124
|
+
# A reactive sandbox (Marimo): which cell this was, and what else
|
|
125
|
+
# ran because of it, each with its own Jupyter-shaped outputs — so a
|
|
126
|
+
# caller that only reads replies still sees every changed cell.
|
|
127
|
+
reply["marimo"] = {
|
|
128
|
+
"cell_id": execution.cell_id,
|
|
129
|
+
"reactions": [
|
|
130
|
+
{
|
|
131
|
+
"cell_id": reaction.cell_id,
|
|
132
|
+
"code": reaction.code,
|
|
133
|
+
# The same predicate as the reply's own status: a reaction
|
|
134
|
+
# that was interrupted, failed in the infrastructure or
|
|
135
|
+
# exited non-zero is not "ok" either.
|
|
136
|
+
"status": "ok" if reaction.result.success else "error",
|
|
137
|
+
"execution_count": reaction.result.execution_count,
|
|
138
|
+
"outputs": execution_result_to_reply(reaction.result)["outputs"],
|
|
139
|
+
}
|
|
140
|
+
for reaction in execution.reactions
|
|
141
|
+
],
|
|
142
|
+
}
|
|
143
|
+
return reply
|
|
122
144
|
|
|
123
145
|
|
|
124
146
|
@dataclass
|
|
@@ -405,19 +427,33 @@ class CodeSandboxClient:
|
|
|
405
427
|
else:
|
|
406
428
|
self.close()
|
|
407
429
|
|
|
430
|
+
def _cell_kwargs(self, cell_id: str | None) -> dict[str, Any]:
|
|
431
|
+
"""The execution context that names a cell, only when one was named.
|
|
432
|
+
|
|
433
|
+
Passed as a keyword only then: a sandbox with no notion of cells —
|
|
434
|
+
every variant but Marimo, and any subclass someone wrote against the
|
|
435
|
+
older signatures — is called exactly as before.
|
|
436
|
+
"""
|
|
437
|
+
return {"context": Context(id=cell_id)} if cell_id else {}
|
|
438
|
+
|
|
408
439
|
def execute_code(
|
|
409
440
|
self,
|
|
410
441
|
code: str,
|
|
411
442
|
language: str = "python",
|
|
412
443
|
timeout: float | None = None,
|
|
413
444
|
envs: dict[str, str] | None = None,
|
|
445
|
+
cell_id: str | None = None,
|
|
414
446
|
) -> CodeExecutionOutcome:
|
|
415
447
|
"""Execute code and return a normalized outcome.
|
|
416
448
|
|
|
417
|
-
The sandbox is started automatically if needed.
|
|
449
|
+
The sandbox is started automatically if needed. ``cell_id`` names the
|
|
450
|
+
cell on a reactive sandbox (Marimo): the same id again replaces the
|
|
451
|
+
cell, and the cells depending on it re-run.
|
|
418
452
|
"""
|
|
419
453
|
self.start()
|
|
420
|
-
execution = self._sandbox.run_code(
|
|
454
|
+
execution = self._sandbox.run_code(
|
|
455
|
+
code, language=language, timeout=timeout, envs=envs, **self._cell_kwargs(cell_id)
|
|
456
|
+
)
|
|
421
457
|
return CodeExecutionOutcome.from_execution_result(execution)
|
|
422
458
|
|
|
423
459
|
def execute(
|
|
@@ -425,12 +461,17 @@ class CodeSandboxClient:
|
|
|
425
461
|
code: str,
|
|
426
462
|
silent: bool = False,
|
|
427
463
|
timeout: float | None = None,
|
|
464
|
+
cell_id: str | None = None,
|
|
428
465
|
**kwargs: Any,
|
|
429
466
|
) -> dict[str, Any]:
|
|
430
|
-
"""Execute code and return a backend-neutral Jupyter-shaped reply.
|
|
467
|
+
"""Execute code and return a backend-neutral Jupyter-shaped reply.
|
|
468
|
+
|
|
469
|
+
On a reactive sandbox the reply also carries ``marimo``: the cell this
|
|
470
|
+
ran as and the reactions, each with its own outputs.
|
|
471
|
+
"""
|
|
431
472
|
del silent, kwargs
|
|
432
473
|
self.start()
|
|
433
|
-
execution = self._sandbox.run_code(code, timeout=timeout)
|
|
474
|
+
execution = self._sandbox.run_code(code, timeout=timeout, **self._cell_kwargs(cell_id))
|
|
434
475
|
return execution_result_to_reply(execution)
|
|
435
476
|
|
|
436
477
|
def execute_interactive(
|
|
@@ -457,21 +498,75 @@ class CodeSandboxClient:
|
|
|
457
498
|
"""
|
|
458
499
|
reply = self.execute(code, silent=silent, timeout=timeout, **kwargs)
|
|
459
500
|
if output_hook is not None:
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
501
|
+
marimo = reply.get("marimo") or {}
|
|
502
|
+
# The cell's own outputs, then each reaction's: every message
|
|
503
|
+
# says which cell it belongs to, the way a kernel's IOPub
|
|
504
|
+
# messages carry their parent header.
|
|
505
|
+
batches = [(marimo.get("cell_id"), False, reply["outputs"])] + [
|
|
506
|
+
(reaction["cell_id"], True, reaction["outputs"])
|
|
507
|
+
for reaction in marimo.get("reactions", [])
|
|
508
|
+
]
|
|
509
|
+
for cell_id, is_reaction, outputs in batches:
|
|
510
|
+
for output in outputs:
|
|
511
|
+
msg_type = output.get("output_type", "display_data")
|
|
512
|
+
message: dict[str, Any] = {
|
|
464
513
|
"header": {"msg_type": msg_type},
|
|
465
514
|
"msg_type": msg_type,
|
|
466
515
|
"content": output,
|
|
467
516
|
}
|
|
468
|
-
|
|
517
|
+
if cell_id is not None:
|
|
518
|
+
message["metadata"] = {
|
|
519
|
+
"marimo": {"cell_id": cell_id, "reaction": is_reaction}
|
|
520
|
+
}
|
|
521
|
+
output_hook(message)
|
|
469
522
|
reply["content"] = {
|
|
470
523
|
"status": reply.get("status", "ok"),
|
|
471
524
|
"execution_count": reply.get("execution_count"),
|
|
472
525
|
}
|
|
473
526
|
return reply
|
|
474
527
|
|
|
528
|
+
# -- reactivity (the Marimo variant) ------------------------------------
|
|
529
|
+
|
|
530
|
+
@property
|
|
531
|
+
def reactive(self) -> bool:
|
|
532
|
+
"""Whether the sandbox keeps a cell graph and re-runs dependents."""
|
|
533
|
+
return hasattr(self._sandbox, "run_cell")
|
|
534
|
+
|
|
535
|
+
def _reactive_sandbox(self) -> Any:
|
|
536
|
+
if not self.reactive:
|
|
537
|
+
raise TypeError(
|
|
538
|
+
f"The {self.variant or 'current'} sandbox is not reactive; "
|
|
539
|
+
"cells and reactions are the marimo variant's."
|
|
540
|
+
)
|
|
541
|
+
self.start()
|
|
542
|
+
return self._sandbox
|
|
543
|
+
|
|
544
|
+
def run_cell(
|
|
545
|
+
self, cell_id: str, code: str, *, react: bool = True, timeout: float | None = None
|
|
546
|
+
) -> Any:
|
|
547
|
+
"""Run one named cell, then the cells that depend on it (`MarimoRun`)."""
|
|
548
|
+
return self._reactive_sandbox().run_cell(cell_id, code, react=react, timeout=timeout)
|
|
549
|
+
|
|
550
|
+
def register_cell(self, cell_id: str, code: str) -> dict[str, Any]:
|
|
551
|
+
"""Put a cell in the graph without running it; answers its names."""
|
|
552
|
+
return self._reactive_sandbox().register_cell(cell_id, code)
|
|
553
|
+
|
|
554
|
+
def remove_cell(self, cell_id: str) -> None:
|
|
555
|
+
self._reactive_sandbox().remove_cell(cell_id)
|
|
556
|
+
|
|
557
|
+
def plan(self, cell_id: str) -> list[str]:
|
|
558
|
+
"""The cells that re-run after `cell_id`, in dependency order."""
|
|
559
|
+
return self._reactive_sandbox().plan(cell_id)
|
|
560
|
+
|
|
561
|
+
def graph(self) -> dict[str, Any]:
|
|
562
|
+
"""Every cell's names and neighbours, the conflicts and the cycles."""
|
|
563
|
+
return self._reactive_sandbox().graph()
|
|
564
|
+
|
|
565
|
+
@property
|
|
566
|
+
def cells(self) -> dict[str, str]:
|
|
567
|
+
"""The registered cells' source, by id."""
|
|
568
|
+
return dict(self._reactive_sandbox().cells)
|
|
569
|
+
|
|
475
570
|
def get_variable(self, name: str) -> Any:
|
|
476
571
|
"""Read a variable through the wrapped sandbox."""
|
|
477
572
|
self.start()
|
|
@@ -546,18 +641,17 @@ class CodeSandboxClient:
|
|
|
546
641
|
language: str = "python",
|
|
547
642
|
timeout: float | None = None,
|
|
548
643
|
envs: dict[str, str] | None = None,
|
|
644
|
+
cell_id: str | None = None,
|
|
549
645
|
) -> Iterator[StreamingItem]:
|
|
550
646
|
"""Execute code and stream output events.
|
|
551
647
|
|
|
552
648
|
This is a thin variant-agnostic wrapper over
|
|
553
|
-
``Sandbox.run_code_streaming``.
|
|
649
|
+
``Sandbox.run_code_streaming``. On a reactive sandbox the reactions'
|
|
650
|
+
events follow the cell's own, each tagged with ``marimo_cell_id``.
|
|
554
651
|
"""
|
|
555
652
|
self.start()
|
|
556
653
|
yield from self._sandbox.run_code_streaming(
|
|
557
|
-
code,
|
|
558
|
-
language=language,
|
|
559
|
-
timeout=timeout,
|
|
560
|
-
envs=envs,
|
|
654
|
+
code, language=language, timeout=timeout, envs=envs, **self._cell_kwargs(cell_id)
|
|
561
655
|
)
|
|
562
656
|
|
|
563
657
|
async def execute_code_streaming_async(
|