code-sandboxes 1.9.26__tar.gz → 1.9.27__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.26 → code_sandboxes-1.9.27}/PKG-INFO +1 -1
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/__version__.py +1 -1
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/environments/adapters/datalayer.py +4 -2
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/environments/adapters/daytona.py +2 -3
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/environments/conformance.py +8 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/environments/resolve_conda.py +146 -1
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_environment_datalayer_builder.py +8 -1
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_environment_daytona_builder.py +4 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_environment_resolve_conda.py +93 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/.github/workflows/build.yml +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/.github/workflows/environments-live.yml +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/.github/workflows/py-code-style.yml +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/.github/workflows/py-tests.yml +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/.github/workflows/py-typing.yml +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/.github/workflows/reusable-python.yml +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/.gitignore +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/.licenserc.yaml +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/.pre-commit-config.yaml +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/.vscode/settings.json +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/CHANGELOG.md +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/Dockerfile +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/LICENSE +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/Makefile +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/README.md +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/__init__.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/base.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/bridge_mount.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/builds.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/cli.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/client.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/cloudflare_sandbox.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/commands.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/console.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/contents.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/coreweave_sandbox.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/datalayer_sandbox.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/daytona_sandbox.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/docker_sandbox.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/e2b_sandbox.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/environments/__init__.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/environments/__main__.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/environments/accounts.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/environments/adapters/__init__.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/environments/adapters/e2b.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/environments/adapters/managed.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/environments/adapters/modal.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/environments/attest.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/environments/bases.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/environments/breaker.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/environments/build_secrets.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/environments/builders.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/environments/canonical.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/environments/constraints/sandbox-contract-v1.txt +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/environments/constraints/wheelhouse/README.md +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/environments/constraints/wheelhouse/jupyter_server-2.21.0+datalayer.1-py3-none-any.whl +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/environments/contract.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/environments/doctor/__init__.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/environments/doctor/build.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/environments/doctor/datalayer_sandbox.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/environments/doctor/report.schema.json +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/environments/errors.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/environments/files.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/environments/image_import.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/environments/lifecycle.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/environments/policy.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/environments/redact.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/environments/resolve.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/environments/schema.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/environments/spec.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/eval_sandbox.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/exceptions.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/filesystem.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/google_colab.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/google_colab_sandbox.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/interfaces.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/jupyter_ingress.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/jupyter_server_sandbox.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/kaggle.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/kaggle_execute.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/kaggle_live.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/kaggle_sandbox.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/lifecycle.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/manage.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/modal_sandbox.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/models.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/monty_sandbox.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/provider_ingress.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/providers.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docker/Dockerfile +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/.gitignore +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/LICENSE +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/Makefile +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/README.md +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/babel.config.js +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/docs/api-reference/_category_.yml +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/docs/api-reference/index.mdx +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/docs/cli/_category_.yml +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/docs/cli/index.mdx +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/docs/contribute/_category_.yml +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/docs/contribute/index.mdx +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/docs/environments/_category_.yml +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/docs/environments/contract.mdx +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/docs/environments/index.mdx +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/docs/environments/specification.mdx +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/docs/environments/spike-2026-09.mdx +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/docs/examples/_category_.yml +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/docs/examples/index.mdx +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/docs/guide/_category_.yml +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/docs/guide/index.mdx +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/docs/index.mdx +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/docs/install/_category_.yml +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/docs/install/index.mdx +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/docs/provider-ingress.mdx +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/docs/providers/_category_.yml +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/docs/providers/cloudflare.mdx +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/docs/providers/coreweave.mdx +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/docs/providers/datalayer.mdx +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/docs/providers/daytona.mdx +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/docs/providers/docker.mdx +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/docs/providers/e2b.mdx +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/docs/providers/eval.mdx +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/docs/providers/google-colab.mdx +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/docs/providers/index.mdx +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/docs/providers/jupyter-server.mdx +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/docs/providers/kaggle.mdx +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/docs/providers/modal.mdx +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/docs/providers/monty.mdx +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/docusaurus.config.js +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/package.json +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/sidebars.js +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/src/components/HomepageRow1.js +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/src/components/HomepageRow1.module.css +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/src/components/HomepageRow2.js +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/src/components/HomepageRow2.module.css +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/src/components/HomepageRow3.js +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/src/components/HomepageRow3.module.css +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/src/css/custom.css +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/src/pages/index.module.css +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/src/pages/markdown-page.md +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/src/theme/CustomDocItem.tsx +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/src/theme/IconsTitle.tsx +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/static/img/bricks.svg +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/static/img/building-construction.svg +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/static/img/cloud-sun.svg +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/static/img/cloud.svg +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/static/img/collaboration.svg +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/static/img/copy-left.svg +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/static/img/datalayer/logo.png +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/static/img/datalayer/logo.svg +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/static/img/datalayer/personas/business.svg +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/static/img/datalayer/personas/data-scientist.svg +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/static/img/datalayer/personas/devops.svg +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/static/img/datalayer/project/project-line.svg +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/static/img/favicon.ico +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/static/img/jupyter.svg +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/static/img/open-source.svg +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/static/img/react-js.svg +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/static/img/react-js2.svg +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/static/img/ringed-planet.svg +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/static/img/robot.svg +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/static/img/rocket.svg +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/static/img/shield.svg +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/static/img/sparkles.svg +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/static/img/streamlit.gif +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/static/img/super-hero.svg +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/static/img/target.svg +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/docs/static/img/thumbs-up.svg +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/examples/README.md +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/examples/exec/Makefile +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/examples/exec/cloudflare_sandbox_example.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/examples/exec/coreweave_sandbox_example.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/examples/exec/datalayer_sandbox_example.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/examples/exec/daytona_sandbox_example.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/examples/exec/docker_sandbox_example.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/examples/exec/e2b_sandbox_example.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/examples/exec/eval_sandbox_example.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/examples/exec/google_colab_sandbox_example.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/examples/exec/jupyter_server_sandbox_example.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/examples/exec/kaggle_sandbox_example.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/examples/exec/modal_sandbox_example.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/examples/exec/monty_sandbox_example.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/examples/repl/Makefile +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/examples/repl/cloudflare_sandbox_example.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/examples/repl/coreweave_sandbox_example.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/examples/repl/datalayer_sandbox_example.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/examples/repl/daytona_sandbox_example.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/examples/repl/docker_sandbox_example.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/examples/repl/e2b_sandbox_example.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/examples/repl/eval_sandbox_example.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/examples/repl/google_colab_sandbox_example.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/examples/repl/jupyter_server_sandbox_example.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/examples/repl/kaggle_sandbox_example.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/examples/repl/modal_sandbox_example.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/examples/repl/monty_sandbox_example.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/pyproject.toml +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/schemas/environment-v1alpha1.json +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/__init__.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/conftest.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_a_datalayer_sandbox_can_be_interrupted.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_bridge_mount.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_builds.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_cli_exec.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_cli_repl.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_client.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_client_contents.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_client_files.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_client_outcome_error_output.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_cloudflare.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_commands_envelope.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_console.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_contents_contract.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_contents_live_matrix.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_coreweave.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_datalayer_sandbox.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_daytona.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_e2b.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_environment_accounts.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_environment_attest.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_environment_bases.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_environment_breaker.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_environment_build_secrets.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_environment_builders.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_environment_canonical.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_environment_conformance.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_environment_constraints.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_environment_contract.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_environment_cross_variant_report.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_environment_doctor.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_environment_e2b_builder.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_environment_errors.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_environment_image_import.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_environment_lifecycle.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_environment_live_matrix.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_environment_managed_builders.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_environment_modal_builder.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_environment_organization_policy.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_environment_redact.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_environment_resolve.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_environment_spec.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_environment_spec_organization_policy.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_eval.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_every_variant_has_a_real_interrupt.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_factory.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_google_colab.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_integration.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_jupyter_ingress.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_jupyter_server.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_jupyter_server_streaming.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_kaggle.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_kaggle_execute.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_kaggle_live.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_kaggle_session.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_kernel_client_compatibility.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_lifecycle_vocabulary.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_manage.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_manage_datalayer.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_modal_google_colab_sandbox.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_modal_session.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_models.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_output_line_fidelity.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_provider_catalog_names.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_provider_ingress.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_providers.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_sandboxes.py +0 -0
- {code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/tests/test_the_kill_relaunch_drill.py +0 -0
{code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/environments/adapters/datalayer.py
RENAMED
|
@@ -83,6 +83,7 @@ from ..resolve_conda import (
|
|
|
83
83
|
conda_lock_pip_requirements,
|
|
84
84
|
is_conda_lock,
|
|
85
85
|
micromamba_bootstrap_dockerfile_line,
|
|
86
|
+
micromamba_install_command,
|
|
86
87
|
)
|
|
87
88
|
from ..spec import BuildSecret, Environment, command_names_secret
|
|
88
89
|
|
|
@@ -364,8 +365,9 @@ class Builder:
|
|
|
364
365
|
micromamba_bootstrap_dockerfile_line(),
|
|
365
366
|
"COPY lock.txt /opt/datalayer/lock.txt",
|
|
366
367
|
"RUN --mount=type=cache,target=/opt/conda/pkgs "
|
|
367
|
-
|
|
368
|
-
|
|
368
|
+
+ micromamba_install_command(
|
|
369
|
+
"/opt/datalayer/lock.txt", micromamba=MICROMAMBA_BINARY
|
|
370
|
+
),
|
|
369
371
|
]
|
|
370
372
|
)
|
|
371
373
|
if pip_requirements:
|
{code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/environments/adapters/daytona.py
RENAMED
|
@@ -116,6 +116,7 @@ from ..resolve_conda import (
|
|
|
116
116
|
conda_lock_pip_requirements,
|
|
117
117
|
is_conda_lock,
|
|
118
118
|
micromamba_bootstrap_command,
|
|
119
|
+
micromamba_install_command,
|
|
119
120
|
)
|
|
120
121
|
from ..spec import GPU_SIZE_CLASSES, Environment
|
|
121
122
|
from .managed import ManagedBuilder
|
|
@@ -373,9 +374,7 @@ class Builder(ManagedBuilder):
|
|
|
373
374
|
# present the same as for a pip source. micromamba is
|
|
374
375
|
# installed first: the approved base bakes uv but not it.
|
|
375
376
|
image = image.run_commands(micromamba_bootstrap_command())
|
|
376
|
-
image = image.run_commands(
|
|
377
|
-
f"micromamba install --yes --name base --file {_LOCK_PATH}"
|
|
378
|
-
)
|
|
377
|
+
image = image.run_commands(micromamba_install_command(_LOCK_PATH))
|
|
379
378
|
pip_requirements = conda_lock_pip_requirements(request.lock_text)
|
|
380
379
|
if pip_requirements:
|
|
381
380
|
requirements = " ".join(shlex.quote(req) for req in pip_requirements)
|
|
@@ -477,6 +477,14 @@ def expected_packages(environment: Any, lock_text: str) -> dict[str, str]:
|
|
|
477
477
|
|
|
478
478
|
from .resolve import locked_versions
|
|
479
479
|
|
|
480
|
+
dependency_file = environment.spec.build.dependency_file
|
|
481
|
+
if dependency_file is not None and dependency_file.source_format == "conda":
|
|
482
|
+
# A conda source names its packages in the file, not in
|
|
483
|
+
# `packages.python`, and its lock is not a pip one (E3-02). Read the
|
|
484
|
+
# other way, check 5 was handed nothing and passed for it.
|
|
485
|
+
from .resolve_conda import conda_expected_packages
|
|
486
|
+
|
|
487
|
+
return conda_expected_packages(dependency_file.content, lock_text or "")
|
|
480
488
|
pinned = locked_versions(lock_text) if lock_text else {}
|
|
481
489
|
names: list[str] = []
|
|
482
490
|
for text in environment.spec.packages.python.dependencies:
|
{code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/environments/resolve_conda.py
RENAMED
|
@@ -148,6 +148,30 @@ def micromamba_bootstrap_command() -> str:
|
|
|
148
148
|
)
|
|
149
149
|
|
|
150
150
|
|
|
151
|
+
#: Where an approved Datalayer base keeps its interpreter: `python` on the
|
|
152
|
+
#: PATH is `/opt/conda/bin/python` (E1-05), and that is the environment a
|
|
153
|
+
#: sandbox's kernel runs in.
|
|
154
|
+
CONDA_PREFIX = "/opt/conda"
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def micromamba_install_command(lock_path: str, *, micromamba: str = "micromamba") -> str:
|
|
158
|
+
"""The command that installs an explicit lock into the base's own interpreter.
|
|
159
|
+
|
|
160
|
+
**Into `/opt/conda`, by name.** The base sets no `MAMBA_ROOT_PREFIX`, and
|
|
161
|
+
left to itself `micromamba install --name base` makes a *new* `base` under
|
|
162
|
+
`~/.local/share/mamba` — for a Datalayer base, inside the very home the
|
|
163
|
+
runtime mounts a person's content over, and nowhere `python` looks. The
|
|
164
|
+
first real conda build (2026-09-18) installed all 81 packages there, and
|
|
165
|
+
then failed its own `postInstall` with `No module named 'osgeo'`. Both the
|
|
166
|
+
root and the target prefix are named, so nothing depends on which user the
|
|
167
|
+
step happens to run as.
|
|
168
|
+
"""
|
|
169
|
+
return (
|
|
170
|
+
f"{micromamba} install --yes --root-prefix {CONDA_PREFIX} "
|
|
171
|
+
f"--prefix {CONDA_PREFIX} --file {lock_path}"
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
|
|
151
175
|
def _utcnow() -> datetime:
|
|
152
176
|
return datetime.now(timezone.utc)
|
|
153
177
|
|
|
@@ -416,6 +440,46 @@ def pip_requirements_from_env_yaml(text: str) -> tuple[str, ...]:
|
|
|
416
440
|
return tuple(requirements)
|
|
417
441
|
|
|
418
442
|
|
|
443
|
+
#: What the solved prefix's own interpreter is asked, to list the pip layer
|
|
444
|
+
#: whole. Standard library only, and it runs inside the prefix.
|
|
445
|
+
#:
|
|
446
|
+
#: ``micromamba env export`` names the pip packages the *file* asked for and
|
|
447
|
+
#: nothing they pulled in: the first real solve (2026-09-18) exported 7 pip
|
|
448
|
+
#: pins where pip had installed several dozen distributions, so every build
|
|
449
|
+
#: would have resolved ``tornado``, ``pyzmq``, ``traitlets`` and the rest
|
|
450
|
+
#: afresh — on each variant, on whichever day it ran — under a lock that
|
|
451
|
+
#: claimed to say the whole of what a build installs. A distribution records
|
|
452
|
+
#: who installed it in its own ``INSTALLER`` file, which is what tells the pip
|
|
453
|
+
#: layer from the conda packages that also carry Python metadata.
|
|
454
|
+
PIP_LAYER_SCRIPT = """\
|
|
455
|
+
import importlib.metadata as metadata
|
|
456
|
+
|
|
457
|
+
layer = {}
|
|
458
|
+
for distribution in metadata.distributions():
|
|
459
|
+
installer = (distribution.read_text("INSTALLER") or "").strip().lower()
|
|
460
|
+
name = distribution.metadata["Name"]
|
|
461
|
+
if installer in ("pip", "uv") and name:
|
|
462
|
+
layer[name.lower().replace("_", "-")] = distribution.version
|
|
463
|
+
for name in sorted(layer):
|
|
464
|
+
print(f"{name}=={layer[name]}")
|
|
465
|
+
"""
|
|
466
|
+
|
|
467
|
+
|
|
468
|
+
def pip_requirements_from_listing(text: str) -> tuple[str, ...]:
|
|
469
|
+
"""The pip layer :data:`PIP_LAYER_SCRIPT` printed: ``name==version`` lines.
|
|
470
|
+
|
|
471
|
+
Anything else on a line — a warning an interpreter wrote to the same
|
|
472
|
+
stream — is dropped rather than installed.
|
|
473
|
+
"""
|
|
474
|
+
requirements: list[str] = []
|
|
475
|
+
for line in text.splitlines():
|
|
476
|
+
entry = line.strip()
|
|
477
|
+
name, separator, version = entry.partition("==")
|
|
478
|
+
if separator and name and version and " " not in entry:
|
|
479
|
+
requirements.append(entry)
|
|
480
|
+
return tuple(requirements)
|
|
481
|
+
|
|
482
|
+
|
|
419
483
|
class CondaResolveRunner(Protocol):
|
|
420
484
|
"""Where a conda solve runs."""
|
|
421
485
|
|
|
@@ -559,9 +623,16 @@ class MicromambaResolveRunner:
|
|
|
559
623
|
[self._micromamba, "env", "export", "--prefix", str(prefix)],
|
|
560
624
|
say,
|
|
561
625
|
)
|
|
626
|
+
# Every distribution pip installed, the transitive ones included:
|
|
627
|
+
# the export above names only what the file asked for.
|
|
628
|
+
listing = self._export(
|
|
629
|
+
[str(prefix / "bin" / "python"), "-c", PIP_LAYER_SCRIPT],
|
|
630
|
+
say,
|
|
631
|
+
)
|
|
562
632
|
return CondaResolveOutcome(
|
|
563
633
|
lock_text=export.stdout,
|
|
564
|
-
pip_lock=
|
|
634
|
+
pip_lock=pip_requirements_from_listing(listing.stdout)
|
|
635
|
+
or pip_requirements_from_env_yaml(pip_export.stdout),
|
|
565
636
|
)
|
|
566
637
|
|
|
567
638
|
def _export(
|
|
@@ -659,9 +730,14 @@ class BuildkitCondaResolveRunner:
|
|
|
659
730
|
f"RUN {micromamba} env export --explicit "
|
|
660
731
|
"--prefix /solve/prefix > /solve/lock.txt",
|
|
661
732
|
f"RUN {micromamba} env export --prefix /solve/prefix > /solve/pip-env.yml",
|
|
733
|
+
# The pip layer whole, from the prefix's own interpreter:
|
|
734
|
+
# a file of this package's, never a spec field.
|
|
735
|
+
"COPY pip_layer.py ./pip_layer.py",
|
|
736
|
+
"RUN /solve/prefix/bin/python pip_layer.py > /solve/pip-lock.txt",
|
|
662
737
|
"FROM scratch",
|
|
663
738
|
"COPY --from=solve /solve/lock.txt /lock.txt",
|
|
664
739
|
"COPY --from=solve /solve/pip-env.yml /pip-env.yml",
|
|
740
|
+
"COPY --from=solve /solve/pip-lock.txt /pip-lock.txt",
|
|
665
741
|
]
|
|
666
742
|
)
|
|
667
743
|
+ "\n"
|
|
@@ -686,6 +762,7 @@ class BuildkitCondaResolveRunner:
|
|
|
686
762
|
with tempfile.TemporaryDirectory(prefix="dl-conda-solve-") as directory:
|
|
687
763
|
root = Path(directory)
|
|
688
764
|
(root / "environment.yml").write_text(request.environment_yml, encoding="utf-8")
|
|
765
|
+
(root / "pip_layer.py").write_text(PIP_LAYER_SCRIPT, encoding="utf-8")
|
|
689
766
|
(root / "Dockerfile").write_text(self.dockerfile(request), encoding="utf-8")
|
|
690
767
|
out = root / "out"
|
|
691
768
|
command = [
|
|
@@ -724,7 +801,12 @@ class BuildkitCondaResolveRunner:
|
|
|
724
801
|
raise parse_conda_failure(finished.stderr or finished.stdout or "")
|
|
725
802
|
lock = (out / "lock.txt").read_text(encoding="utf-8")
|
|
726
803
|
pip_env = out / "pip-env.yml"
|
|
804
|
+
pip_listing = out / "pip-lock.txt"
|
|
727
805
|
pip_lock = (
|
|
806
|
+
pip_requirements_from_listing(pip_listing.read_text(encoding="utf-8"))
|
|
807
|
+
if pip_listing.exists()
|
|
808
|
+
else ()
|
|
809
|
+
) or (
|
|
728
810
|
pip_requirements_from_env_yaml(pip_env.read_text(encoding="utf-8"))
|
|
729
811
|
if pip_env.exists()
|
|
730
812
|
else ()
|
|
@@ -763,6 +845,69 @@ def explicit_lock_packages(lock_text: str) -> list[str]:
|
|
|
763
845
|
return packages
|
|
764
846
|
|
|
765
847
|
|
|
848
|
+
#: `name-version-build.conda` (or `.tar.bz2`), as the last segment of an
|
|
849
|
+
#: explicit lock's URL. A conda name may itself contain `-`, so the version and
|
|
850
|
+
#: the build are the last two dash-separated fields, never the first two.
|
|
851
|
+
_EXPLICIT_PACKAGE = re.compile(
|
|
852
|
+
r"/(?P<name>[^/]+)-(?P<version>[^-/]+)-(?P<build>[^-/]+)\.(?:conda|tar\.bz2)(?:#.*)?$"
|
|
853
|
+
)
|
|
854
|
+
|
|
855
|
+
|
|
856
|
+
def conda_lock_python_packages(lock_text: str) -> dict[str, str]:
|
|
857
|
+
"""The Python distributions an explicit lock installs, by name, with their versions.
|
|
858
|
+
|
|
859
|
+
Only the ones a build string marks as Python packages — `py313h…` for a
|
|
860
|
+
compiled one, `pyh…`/`pyhd8ed…` for a noarch one. A conda lock is mostly
|
|
861
|
+
libraries with no Python metadata at all (`libgdal-core`, `proj`, `openssl`),
|
|
862
|
+
and Appendix B check 5 asks the interpreter for a distribution's version:
|
|
863
|
+
handing it `proj` would fail a check with nothing wrong to report.
|
|
864
|
+
"""
|
|
865
|
+
found: dict[str, str] = {}
|
|
866
|
+
for url in explicit_lock_packages(lock_text):
|
|
867
|
+
match = _EXPLICIT_PACKAGE.search(url)
|
|
868
|
+
if match and match["build"].startswith("py"):
|
|
869
|
+
found[match["name"].lower()] = match["version"]
|
|
870
|
+
return found
|
|
871
|
+
|
|
872
|
+
|
|
873
|
+
def conda_expected_packages(environment_yml: str, lock_text: str) -> dict[str, str]:
|
|
874
|
+
"""What an `environment.yml` names at its top level, pinned to what its lock resolved.
|
|
875
|
+
|
|
876
|
+
Check 5's question, for a conda source (E3-02): the file's own `pip:`
|
|
877
|
+
requirements, and the conda packages it names that are Python
|
|
878
|
+
distributions. The interpreter is left out — check 3 asks about it, and
|
|
879
|
+
`python` is not a distribution the interpreter reports about itself.
|
|
880
|
+
Empty for a file that cannot be read: the spec's own validation refuses
|
|
881
|
+
one long before a build, and a smoke test is not where to say so again.
|
|
882
|
+
"""
|
|
883
|
+
from packaging.requirements import InvalidRequirement, Requirement
|
|
884
|
+
from packaging.utils import canonicalize_name
|
|
885
|
+
|
|
886
|
+
try:
|
|
887
|
+
environment = parse_conda_environment(environment_yml)
|
|
888
|
+
except EnvironmentsError:
|
|
889
|
+
return {}
|
|
890
|
+
expected: dict[str, str] = {}
|
|
891
|
+
pythons = conda_lock_python_packages(lock_text)
|
|
892
|
+
for spec in environment.conda_dependencies:
|
|
893
|
+
name = _conda_package_name(spec)
|
|
894
|
+
if name != "python" and name in pythons:
|
|
895
|
+
expected[canonicalize_name(name)] = pythons[name]
|
|
896
|
+
pinned: dict[str, str] = {}
|
|
897
|
+
for requirement in conda_lock_pip_requirements(lock_text):
|
|
898
|
+
name, separator, version = requirement.partition("==")
|
|
899
|
+
if separator:
|
|
900
|
+
pinned[canonicalize_name(name.strip())] = version.strip()
|
|
901
|
+
for text in environment.pip_dependencies:
|
|
902
|
+
try:
|
|
903
|
+
name = canonicalize_name(Requirement(text).name)
|
|
904
|
+
except InvalidRequirement:
|
|
905
|
+
continue
|
|
906
|
+
if name in pinned:
|
|
907
|
+
expected[name] = pinned[name]
|
|
908
|
+
return expected
|
|
909
|
+
|
|
910
|
+
|
|
766
911
|
def is_conda_lock(lock_text: str | None) -> bool:
|
|
767
912
|
"""Whether a lock is a conda explicit lock, and not the pip one.
|
|
768
913
|
|
|
@@ -277,7 +277,14 @@ class TestTheDockerfileItGenerates:
|
|
|
277
277
|
follows, so the kernel stack (E1-04) is present the same."""
|
|
278
278
|
request = a_request(lock_text=CONDA_LOCK, spec=CONDA_SPEC)
|
|
279
279
|
dockerfile = a_builder().dockerfile(request)
|
|
280
|
-
|
|
280
|
+
# Into the base's own interpreter, by name: left to itself micromamba
|
|
281
|
+
# made a new `base` under the content home, where `python` never looks
|
|
282
|
+
# (found on the first real conda build, 2026-09-18).
|
|
283
|
+
assert (
|
|
284
|
+
"micromamba install --yes --root-prefix /opt/conda --prefix /opt/conda "
|
|
285
|
+
"--file /opt/datalayer/lock.txt"
|
|
286
|
+
) in dockerfile
|
|
287
|
+
assert "--name base" not in dockerfile
|
|
281
288
|
# micromamba is copied in from its pinned image before it is invoked.
|
|
282
289
|
bootstrap = dockerfile.index("COPY --from=mambaorg/micromamba")
|
|
283
290
|
micromamba = dockerfile.index("micromamba install")
|
|
@@ -503,6 +503,10 @@ class TestBuildingASnapshot:
|
|
|
503
503
|
pip = next(i for i, call in enumerate(runs) if "ipykernel==7.3.0" in call.args[0])
|
|
504
504
|
assert bootstrap < micromamba < pip
|
|
505
505
|
assert not any("uv pip sync" in call.args[0] for call in runs)
|
|
506
|
+
# The interpreter a sandbox runs, not a new `base` under the content
|
|
507
|
+
# home (2026-09-18): the same command the Datalayer builder emits.
|
|
508
|
+
assert "--root-prefix /opt/conda --prefix /opt/conda" in runs[micromamba].args[0]
|
|
509
|
+
assert "--name base" not in runs[micromamba].args[0]
|
|
506
510
|
|
|
507
511
|
def test_user_root_brackets_the_install_steps(self) -> None:
|
|
508
512
|
"""Daytona honours the base's `USER`, unlike E2B (E0-04): no synthetic
|
|
@@ -20,16 +20,20 @@ from code_sandboxes.environments.errors import EnvironmentsError
|
|
|
20
20
|
from code_sandboxes.environments.resolve import protected_pins
|
|
21
21
|
from code_sandboxes.environments.resolve_conda import (
|
|
22
22
|
CONDA_LOCK_FORMAT,
|
|
23
|
+
PIP_LAYER_SCRIPT,
|
|
23
24
|
BuildkitCondaResolveRunner,
|
|
24
25
|
CondaResolveOutcome,
|
|
25
26
|
CondaResolveRequest,
|
|
26
27
|
MicromambaResolveRunner,
|
|
28
|
+
conda_expected_packages,
|
|
27
29
|
conda_lock_document,
|
|
30
|
+
conda_lock_python_packages,
|
|
28
31
|
explicit_lock_packages,
|
|
29
32
|
merge_conda_pip,
|
|
30
33
|
parse_conda_environment,
|
|
31
34
|
parse_conda_failure,
|
|
32
35
|
pip_requirements_from_env_yaml,
|
|
36
|
+
pip_requirements_from_listing,
|
|
33
37
|
rendered_environment,
|
|
34
38
|
resolve_conda_environment,
|
|
35
39
|
)
|
|
@@ -393,6 +397,95 @@ class TestTheRunners:
|
|
|
393
397
|
assert "COPY --from=mambaorg/micromamba" in dockerfile
|
|
394
398
|
assert "env export --prefix /solve/prefix > /solve/pip-env.yml" in dockerfile
|
|
395
399
|
assert "COPY --from=solve /solve/pip-env.yml /pip-env.yml" in dockerfile
|
|
400
|
+
# And the pip layer whole, asked of the prefix's own interpreter: the
|
|
401
|
+
# export names what the file asked for and nothing it pulled in.
|
|
402
|
+
assert "COPY pip_layer.py ./pip_layer.py" in dockerfile
|
|
403
|
+
assert "RUN /solve/prefix/bin/python pip_layer.py > /solve/pip-lock.txt" in dockerfile
|
|
404
|
+
assert "COPY --from=solve /solve/pip-lock.txt /pip-lock.txt" in dockerfile
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
class TestThePipLayerIsWhole:
|
|
408
|
+
"""`micromamba env export` named 7 pip pins where pip had installed 310
|
|
409
|
+
distributions (the first real solve, 2026-09-18): everything they pulled
|
|
410
|
+
in would have been resolved afresh by each build, on each variant."""
|
|
411
|
+
|
|
412
|
+
def test_the_script_lists_what_pip_installed_and_not_what_conda_did(self, tmp_path) -> None:
|
|
413
|
+
import subprocess as process
|
|
414
|
+
import sys
|
|
415
|
+
|
|
416
|
+
site = tmp_path / "site"
|
|
417
|
+
for name, version, installer in (
|
|
418
|
+
("Tornado", "6.5.10", "pip"),
|
|
419
|
+
("jupyter_server", "2.21.0+datalayer.1", "uv"),
|
|
420
|
+
("GDAL", "3.11.5", "conda"),
|
|
421
|
+
("unknown", "1.0", ""),
|
|
422
|
+
):
|
|
423
|
+
info = site / f"{name}-{version}.dist-info"
|
|
424
|
+
info.mkdir(parents=True)
|
|
425
|
+
(info / "METADATA").write_text(
|
|
426
|
+
f"Metadata-Version: 2.1\nName: {name}\nVersion: {version}\n"
|
|
427
|
+
)
|
|
428
|
+
(info / "INSTALLER").write_text(installer + "\n")
|
|
429
|
+
listed = process.run( # noqa: S603 - this interpreter, this package's script
|
|
430
|
+
[
|
|
431
|
+
sys.executable,
|
|
432
|
+
"-S",
|
|
433
|
+
"-c",
|
|
434
|
+
f"import sys; sys.path[:] = [{str(site)!r}] + sys.path\n" + PIP_LAYER_SCRIPT,
|
|
435
|
+
],
|
|
436
|
+
capture_output=True,
|
|
437
|
+
text=True,
|
|
438
|
+
check=True,
|
|
439
|
+
).stdout
|
|
440
|
+
assert pip_requirements_from_listing(listed) == (
|
|
441
|
+
"jupyter-server==2.21.0+datalayer.1",
|
|
442
|
+
"tornado==6.5.10",
|
|
443
|
+
)
|
|
444
|
+
|
|
445
|
+
def test_a_line_that_is_not_a_pin_is_never_installed(self) -> None:
|
|
446
|
+
listing = "a==1\nWARNING: something was said\n\nb-c==2.0\n== \n"
|
|
447
|
+
assert pip_requirements_from_listing(listing) == ("a==1", "b-c==2.0")
|
|
448
|
+
|
|
449
|
+
|
|
450
|
+
class TestWhatCheckFiveExpectsOfACondaLock:
|
|
451
|
+
LOCK = (
|
|
452
|
+
"# datalayer-pip: shapely==2.1.2\n# datalayer-pip: tornado==6.5.10\n@EXPLICIT\n"
|
|
453
|
+
"https://conda.anaconda.org/conda-forge/linux-64/libgdal-core-3.11.5-h4f65170_7.conda#aa\n"
|
|
454
|
+
"https://conda.anaconda.org/conda-forge/linux-64/gdal-3.11.5-py313h1ee8c46_7.conda#bb\n"
|
|
455
|
+
"https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-pyhcf101f3_0.conda#cc\n"
|
|
456
|
+
"https://conda.anaconda.org/conda-forge/linux-64/python-3.13.15-h2b335a9_0_cp313.conda#dd\n"
|
|
457
|
+
)
|
|
458
|
+
FILE = (
|
|
459
|
+
"channels: [conda-forge]\n"
|
|
460
|
+
"dependencies:\n"
|
|
461
|
+
" - python=3.13\n"
|
|
462
|
+
" - gdal=3.11\n"
|
|
463
|
+
" - libgdal-core\n"
|
|
464
|
+
" - pip:\n"
|
|
465
|
+
" - shapely==2.1.2\n"
|
|
466
|
+
)
|
|
467
|
+
|
|
468
|
+
def test_only_python_distributions_are_read_out_of_the_lock(self) -> None:
|
|
469
|
+
"""`libgdal-core` has no Python metadata: asking the interpreter for
|
|
470
|
+
its version would fail a check with nothing wrong to report."""
|
|
471
|
+
assert conda_lock_python_packages(self.LOCK) == {
|
|
472
|
+
"gdal": "3.11.5",
|
|
473
|
+
"typing-extensions": "4.15.0",
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
def test_it_is_what_the_file_names_pinned_to_what_the_lock_resolved(self) -> None:
|
|
477
|
+
assert conda_expected_packages(self.FILE, self.LOCK) == {
|
|
478
|
+
"gdal": "3.11.5",
|
|
479
|
+
"shapely": "2.1.2",
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
def test_check_five_is_handed_them_for_a_conda_version(self) -> None:
|
|
483
|
+
"""Read from `packages.python`, as a pip source is, it was handed
|
|
484
|
+
nothing, and check 5 passed for having nothing to check."""
|
|
485
|
+
from code_sandboxes.environments.conformance import expected_packages
|
|
486
|
+
|
|
487
|
+
environment = validate_environment(a_conda_spec(content=self.FILE))
|
|
488
|
+
assert expected_packages(environment, self.LOCK) == {"gdal": "3.11.5", "shapely": "2.1.2"}
|
|
396
489
|
|
|
397
490
|
|
|
398
491
|
# -- The whole resolve, through the recorded runner --------------------------
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/environments/adapters/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/environments/adapters/managed.py
RENAMED
|
File without changes
|
{code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/environments/adapters/modal.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/environments/build_secrets.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{code_sandboxes-1.9.26 → code_sandboxes-1.9.27}/code_sandboxes/environments/doctor/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|