code-sandboxes 1.9.35__tar.gz → 1.9.37__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.35 → code_sandboxes-1.9.37}/PKG-INFO +1 -1
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/__version__.py +1 -1
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/environments/adapters/datalayer.py +32 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/environments/adapters/modal.py +24 -1
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/environments/resolve.py +129 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/environments/resolve_conda.py +21 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/modal_sandbox.py +10 -1
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/docs/environments/specification.mdx +1 -1
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/docs/providers/modal.mdx +24 -8
- code_sandboxes-1.9.37/tests/egress_logs/buildctl-base.log +16 -0
- code_sandboxes-1.9.37/tests/egress_logs/buildctl-curl.log +41 -0
- code_sandboxes-1.9.37/tests/egress_logs/buildctl-pip.log +43 -0
- code_sandboxes-1.9.37/tests/egress_logs/buildctl-uv.log +54 -0
- code_sandboxes-1.9.37/tests/egress_logs/micromamba.log +30 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_environment_datalayer_builder.py +26 -2
- code_sandboxes-1.9.37/tests/test_environment_egress_refusals.py +146 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_environment_modal_builder.py +18 -4
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_environment_resolve.py +28 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_environment_resolve_conda.py +24 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_modal_google_colab_sandbox.py +51 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/.github/workflows/build.yml +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/.github/workflows/environments-live.yml +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/.github/workflows/py-code-style.yml +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/.github/workflows/py-tests.yml +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/.github/workflows/py-typing.yml +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/.github/workflows/reusable-python.yml +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/.gitignore +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/.licenserc.yaml +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/.pre-commit-config.yaml +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/.vscode/settings.json +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/CHANGELOG.md +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/Dockerfile +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/LICENSE +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/Makefile +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/README.md +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/__init__.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/base.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/bridge_mount.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/builds.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/cli.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/client.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/cloudflare_sandbox.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/commands.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/console.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/contents.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/coreweave_sandbox.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/datalayer_sandbox.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/daytona_sandbox.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/docker_sandbox.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/e2b_sandbox.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/environments/__init__.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/environments/__main__.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/environments/accounts.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/environments/adapters/__init__.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/environments/adapters/daytona.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/environments/adapters/e2b.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/environments/adapters/managed.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/environments/attest.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/environments/bases.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/environments/breaker.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/environments/build_secrets.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/environments/builders.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/environments/canonical.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/environments/conformance.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/environments/constraints/sandbox-contract-v1.txt +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/environments/constraints/wheelhouse/README.md +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/environments/constraints/wheelhouse/jupyter_server-2.21.0+datalayer.1-py3-none-any.whl +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/environments/contract.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/environments/doctor/__init__.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/environments/doctor/build.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/environments/doctor/datalayer_sandbox.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/environments/doctor/report.schema.json +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/environments/errors.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/environments/files.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/environments/image_import.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/environments/lifecycle.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/environments/policy.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/environments/redact.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/environments/schema.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/environments/spec.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/eval_sandbox.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/exceptions.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/filesystem.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/google_colab.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/google_colab_sandbox.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/interfaces.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/jupyter_ingress.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/jupyter_server_sandbox.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/kaggle.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/kaggle_execute.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/kaggle_live.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/kaggle_sandbox.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/lifecycle.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/manage.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/models.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/monty_sandbox.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/provider_ingress.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/providers.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docker/Dockerfile +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/.gitignore +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/LICENSE +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/Makefile +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/README.md +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/babel.config.js +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/docs/api-reference/_category_.yml +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/docs/api-reference/index.mdx +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/docs/cli/_category_.yml +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/docs/cli/index.mdx +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/docs/contribute/_category_.yml +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/docs/contribute/index.mdx +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/docs/environments/_category_.yml +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/docs/environments/contract.mdx +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/docs/environments/index.mdx +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/docs/environments/spike-2026-09.mdx +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/docs/examples/_category_.yml +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/docs/examples/index.mdx +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/docs/guide/_category_.yml +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/docs/guide/index.mdx +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/docs/index.mdx +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/docs/install/_category_.yml +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/docs/install/index.mdx +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/docs/provider-ingress.mdx +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/docs/providers/_category_.yml +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/docs/providers/cloudflare.mdx +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/docs/providers/coreweave.mdx +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/docs/providers/datalayer.mdx +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/docs/providers/daytona.mdx +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/docs/providers/docker.mdx +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/docs/providers/e2b.mdx +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/docs/providers/eval.mdx +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/docs/providers/google-colab.mdx +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/docs/providers/index.mdx +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/docs/providers/jupyter-server.mdx +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/docs/providers/kaggle.mdx +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/docs/providers/monty.mdx +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/docusaurus.config.js +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/package.json +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/sidebars.js +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/src/components/HomepageRow1.js +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/src/components/HomepageRow1.module.css +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/src/components/HomepageRow2.js +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/src/components/HomepageRow2.module.css +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/src/components/HomepageRow3.js +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/src/components/HomepageRow3.module.css +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/src/css/custom.css +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/src/pages/index.module.css +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/src/pages/markdown-page.md +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/src/theme/CustomDocItem.tsx +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/src/theme/IconsTitle.tsx +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/static/img/bricks.svg +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/static/img/building-construction.svg +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/static/img/cloud-sun.svg +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/static/img/cloud.svg +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/static/img/collaboration.svg +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/static/img/copy-left.svg +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/static/img/datalayer/logo.png +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/static/img/datalayer/logo.svg +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/static/img/datalayer/personas/business.svg +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/static/img/datalayer/personas/data-scientist.svg +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/static/img/datalayer/personas/devops.svg +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/static/img/datalayer/project/project-line.svg +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/static/img/favicon.ico +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/static/img/jupyter.svg +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/static/img/open-source.svg +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/static/img/react-js.svg +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/static/img/react-js2.svg +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/static/img/ringed-planet.svg +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/static/img/robot.svg +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/static/img/rocket.svg +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/static/img/shield.svg +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/static/img/sparkles.svg +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/static/img/streamlit.gif +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/static/img/super-hero.svg +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/static/img/target.svg +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/docs/static/img/thumbs-up.svg +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/examples/README.md +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/examples/exec/Makefile +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/examples/exec/cloudflare_sandbox_example.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/examples/exec/coreweave_sandbox_example.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/examples/exec/datalayer_sandbox_example.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/examples/exec/daytona_sandbox_example.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/examples/exec/docker_sandbox_example.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/examples/exec/e2b_sandbox_example.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/examples/exec/eval_sandbox_example.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/examples/exec/google_colab_sandbox_example.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/examples/exec/jupyter_server_sandbox_example.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/examples/exec/kaggle_sandbox_example.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/examples/exec/modal_sandbox_example.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/examples/exec/monty_sandbox_example.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/examples/repl/Makefile +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/examples/repl/cloudflare_sandbox_example.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/examples/repl/coreweave_sandbox_example.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/examples/repl/datalayer_sandbox_example.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/examples/repl/daytona_sandbox_example.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/examples/repl/docker_sandbox_example.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/examples/repl/e2b_sandbox_example.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/examples/repl/eval_sandbox_example.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/examples/repl/google_colab_sandbox_example.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/examples/repl/jupyter_server_sandbox_example.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/examples/repl/kaggle_sandbox_example.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/examples/repl/modal_sandbox_example.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/examples/repl/monty_sandbox_example.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/pyproject.toml +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/schemas/environment-v1alpha1.json +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/__init__.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/conftest.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_a_datalayer_sandbox_can_be_interrupted.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_bridge_mount.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_builds.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_cli_exec.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_cli_repl.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_client.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_client_contents.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_client_files.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_client_outcome_error_output.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_cloudflare.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_commands_envelope.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_console.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_contents_contract.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_contents_live_matrix.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_coreweave.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_datalayer_sandbox.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_daytona.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_e2b.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_environment_accounts.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_environment_attest.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_environment_bases.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_environment_breaker.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_environment_build_secrets.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_environment_builders.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_environment_canonical.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_environment_conformance.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_environment_constraints.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_environment_contract.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_environment_cross_variant_report.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_environment_daytona_builder.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_environment_dockerfile_source.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_environment_doctor.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_environment_e2b_builder.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_environment_errors.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_environment_image_import.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_environment_lifecycle.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_environment_live_matrix.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_environment_managed_builders.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_environment_organization_policy.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_environment_redact.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_environment_spec.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_environment_spec_organization_policy.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_eval.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_every_variant_has_a_real_interrupt.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_factory.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_google_colab.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_integration.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_jupyter_ingress.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_jupyter_server.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_jupyter_server_streaming.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_kaggle.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_kaggle_execute.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_kaggle_live.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_kaggle_session.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_kernel_client_compatibility.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_lifecycle_vocabulary.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_manage.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_manage_datalayer.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_modal_session.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_models.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_output_line_fidelity.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_provider_catalog_names.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_provider_ingress.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_providers.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_sandboxes.py +0 -0
- {code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/tests/test_the_kill_relaunch_drill.py +0 -0
{code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/environments/adapters/datalayer.py
RENAMED
|
@@ -76,6 +76,11 @@ from ..resolve import (
|
|
|
76
76
|
WHEELHOUSE_PATH,
|
|
77
77
|
apt_pins_in,
|
|
78
78
|
apt_snapshot_in,
|
|
79
|
+
buildkit_proxy,
|
|
80
|
+
buildkit_proxy_options,
|
|
81
|
+
egress_findings,
|
|
82
|
+
egress_hosts_text,
|
|
83
|
+
egress_refused_hosts,
|
|
79
84
|
locked_versions,
|
|
80
85
|
)
|
|
81
86
|
from ..resolve_conda import (
|
|
@@ -214,6 +219,11 @@ class Builder:
|
|
|
214
219
|
importing this module needs no credentials.
|
|
215
220
|
run
|
|
216
221
|
How a subprocess is run, so a test can watch the argv without a daemon.
|
|
222
|
+
proxy
|
|
223
|
+
The build pool's egress proxy, as ``buildkitd`` reaches it (E1-06):
|
|
224
|
+
every step of the build goes through it. ``DATALAYER_BUILDKIT_PROXY``
|
|
225
|
+
by default; empty is a ``buildkitd`` whose steps reach the network
|
|
226
|
+
directly.
|
|
217
227
|
"""
|
|
218
228
|
|
|
219
229
|
variant = "datalayer"
|
|
@@ -233,6 +243,7 @@ class Builder:
|
|
|
233
243
|
run: Callable[..., subprocess.CompletedProcess[str]] | None = None,
|
|
234
244
|
max_build_seconds: int = DEFAULT_MAX_BUILD_SECONDS,
|
|
235
245
|
resolve_secret: Callable[..., str] = resolve_build_secret,
|
|
246
|
+
proxy: str | None = None,
|
|
236
247
|
) -> None:
|
|
237
248
|
self._log = log or (lambda _line: None)
|
|
238
249
|
self._credential = credential
|
|
@@ -241,6 +252,8 @@ class Builder:
|
|
|
241
252
|
self._tlscert = tlscert or os.environ.get("DATALAYER_BUILDKIT_TLSCERT", "").strip()
|
|
242
253
|
self._tlskey = tlskey or os.environ.get("DATALAYER_BUILDKIT_TLSKEY", "").strip()
|
|
243
254
|
self._tlscacert = tlscacert or os.environ.get("DATALAYER_BUILDKIT_TLSCACERT", "").strip()
|
|
255
|
+
#: The build pool's egress proxy (E1-06), or `DATALAYER_BUILDKIT_PROXY`.
|
|
256
|
+
self._proxy = buildkit_proxy(proxy)
|
|
244
257
|
self._region = region or os.environ.get("AWS_REGION", "us-east-1")
|
|
245
258
|
self._ecr = ecr
|
|
246
259
|
self._run = run or subprocess.run
|
|
@@ -530,11 +543,30 @@ class Builder:
|
|
|
530
543
|
"--metadata-file",
|
|
531
544
|
str(metadata),
|
|
532
545
|
*self._cache_options(request),
|
|
546
|
+
*buildkit_proxy_options(self._proxy),
|
|
533
547
|
*secret_args,
|
|
534
548
|
]
|
|
535
549
|
self._log(f"Building {reference} from {request.resolved_base}")
|
|
536
550
|
finished = self._invoke(command, timeout=self._max_build_seconds)
|
|
537
551
|
if finished.returncode != 0:
|
|
552
|
+
refused = egress_refused_hosts(finished.stderr or "", proxy=self._proxy)
|
|
553
|
+
if refused:
|
|
554
|
+
# The one failure a log line hid best: a host the build
|
|
555
|
+
# pool may not reach, named as a finding (E2-19).
|
|
556
|
+
raise EnvironmentsError(
|
|
557
|
+
BUILD_FAILED,
|
|
558
|
+
f"The build pool's egress proxy refused {egress_hosts_text(refused)}: "
|
|
559
|
+
"a build reaches only the package indexes, mirrors and registries "
|
|
560
|
+
"the build pool allows. Put what it fetches in the build, or ask "
|
|
561
|
+
"for the host to be allowed",
|
|
562
|
+
detail={
|
|
563
|
+
"variant": self.variant,
|
|
564
|
+
"reference": reference,
|
|
565
|
+
"exit": finished.returncode,
|
|
566
|
+
"refused_hosts": refused,
|
|
567
|
+
"findings": egress_findings(refused),
|
|
568
|
+
},
|
|
569
|
+
)
|
|
538
570
|
raise EnvironmentsError(
|
|
539
571
|
BUILD_FAILED,
|
|
540
572
|
"The build failed; its log says where",
|
{code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/environments/adapters/modal.py
RENAMED
|
@@ -96,6 +96,15 @@ end and the container exited before that first real exec ever reached it.
|
|
|
96
96
|
The entrypoint now execs `sleep infinity` when it is given no arguments,
|
|
97
97
|
and `"$@"` when it is — correct either way a caller invokes it.
|
|
98
98
|
|
|
99
|
+
**And a sandbox with no command is not given no arguments** (found live on
|
|
100
|
+
2026-09-18): Modal keeps the base's own CMD, `start-jupyter.sh`, under the
|
|
101
|
+
new ENTRYPOINT where Docker would reset it, so the main process was a
|
|
102
|
+
Jupyter server, which exits within a minute and ends the sandbox. A smoke
|
|
103
|
+
test's restarted sandbox, started warm, died between checks 8 and 9. The
|
|
104
|
+
artifact now sets its CMD to `sleep infinity`, and `ModalSandbox` names the
|
|
105
|
+
same command when it launches an artifact, which also covers the ones built
|
|
106
|
+
before.
|
|
107
|
+
|
|
99
108
|
**A GPU is a launch option on Modal, not part of the image** (section 11.4
|
|
100
109
|
item 10, E2-17). A GPU version builds the same image any version does, on the
|
|
101
110
|
CUDA base; the spec's `accelerator` names one of Modal's GPUs, checked at
|
|
@@ -206,6 +215,8 @@ _ENTRYPOINT_PATH = "/opt/datalayer/bin/entrypoint.sh"
|
|
|
206
215
|
#: is given keeps it alive for that; `exec "$@"` still wins when something
|
|
207
216
|
#: is, for a caller that does supply a command directly.
|
|
208
217
|
_ENTRYPOINT_SCRIPT = '#!/bin/sh\nif [ "$#" -eq 0 ]; then exec sleep infinity; fi\nexec "$@"\n'
|
|
218
|
+
#: The artifact's CMD: what a sandbox started with no command of its own runs.
|
|
219
|
+
_KEEP_ALIVE_COMMAND = ("sleep", "infinity")
|
|
209
220
|
|
|
210
221
|
|
|
211
222
|
def _modal_sdk() -> Any:
|
|
@@ -498,7 +509,19 @@ class Builder(ManagedBuilder):
|
|
|
498
509
|
for command in files_step(request.environment, variant=self.variant):
|
|
499
510
|
image = image.run_commands(command)
|
|
500
511
|
image = _post_install(image, spec.commands.post_install, declared, step_secrets)
|
|
501
|
-
|
|
512
|
+
# The base's own CMD is `start-jupyter.sh`, and Modal keeps
|
|
513
|
+
# it under a new ENTRYPOINT where Docker would reset it: a
|
|
514
|
+
# sandbox started with no command ran a Jupyter server as its
|
|
515
|
+
# main process, which exits within a minute and takes the
|
|
516
|
+
# sandbox with it (found live on 2026-09-18, the restarted
|
|
517
|
+
# sandbox of a smoke test dying mid-tier). What holds the
|
|
518
|
+
# container is `sleep`; Jupyter is started by exec, when
|
|
519
|
+
# asked (`ModalSandbox.prepare_jupyter_server`).
|
|
520
|
+
image = (
|
|
521
|
+
image.workdir(_CONTENT_DIR)
|
|
522
|
+
.entrypoint([_ENTRYPOINT_PATH])
|
|
523
|
+
.cmd(list(_KEEP_ALIVE_COMMAND))
|
|
524
|
+
)
|
|
502
525
|
|
|
503
526
|
logged: list[str] = []
|
|
504
527
|
buffer = io.StringIO()
|
|
@@ -83,6 +83,7 @@ if TYPE_CHECKING:
|
|
|
83
83
|
__all__ = [
|
|
84
84
|
"APT_PIN_PREFIX",
|
|
85
85
|
"APT_SNAPSHOT_PREFIX",
|
|
86
|
+
"BUILDKIT_PROXY_ENV",
|
|
86
87
|
"CONSTRAINTS_PATH",
|
|
87
88
|
"COVERAGE_PREFIX",
|
|
88
89
|
"DOCKERFILE_COVERAGE",
|
|
@@ -98,6 +99,9 @@ __all__ = [
|
|
|
98
99
|
"apt_pins",
|
|
99
100
|
"apt_pins_in",
|
|
100
101
|
"apt_snapshot_in",
|
|
102
|
+
"buildkit_proxy",
|
|
103
|
+
"buildkit_proxy_options",
|
|
104
|
+
"egress_refused_hosts",
|
|
101
105
|
"lock_document",
|
|
102
106
|
"locked_versions",
|
|
103
107
|
"merge_requirements",
|
|
@@ -145,6 +149,114 @@ DOCKERFILE_COVERAGE = (
|
|
|
145
149
|
APT_SNAPSHOT_PREFIX = "# datalayer-apt-snapshot: "
|
|
146
150
|
_SNAPSHOT_ID = re.compile(r"^\d{8}T\d{6}Z$")
|
|
147
151
|
|
|
152
|
+
#: Where a build's own steps reach the network through, when the build pool
|
|
153
|
+
#: gives them nowhere else to go (E1-06): an HTTP proxy that allows only the
|
|
154
|
+
#: package indexes, the snapshot mirrors and the registries. The address is
|
|
155
|
+
#: the one `buildkitd` itself sees, since a step runs in its network.
|
|
156
|
+
BUILDKIT_PROXY_ENV = "DATALAYER_BUILDKIT_PROXY"
|
|
157
|
+
_PROXY_URL = re.compile(r"^http://[A-Za-z0-9.\-]+:\d{1,5}$")
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def buildkit_proxy(proxy: str | None = None) -> str:
|
|
161
|
+
"""The proxy a build's steps go through: ``proxy``, or the environment's.
|
|
162
|
+
|
|
163
|
+
Empty is no proxy, which is what a `buildkitd` with open egress needs
|
|
164
|
+
(`plane local`'s own). Anything that is not ``http://host:port`` is
|
|
165
|
+
refused rather than handed to every package manager of every build.
|
|
166
|
+
"""
|
|
167
|
+
value = (os.environ.get(BUILDKIT_PROXY_ENV, "") if proxy is None else proxy).strip()
|
|
168
|
+
if value and not _PROXY_URL.match(value):
|
|
169
|
+
raise ValueError(f"{BUILDKIT_PROXY_ENV} must be http://host:port, not {value!r}")
|
|
170
|
+
return value
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def buildkit_proxy_options(proxy: str) -> list[str]:
|
|
174
|
+
"""The ``buildctl`` options that send a build's steps through ``proxy``.
|
|
175
|
+
|
|
176
|
+
The Dockerfile frontend predefines these build args: a ``RUN`` step sees
|
|
177
|
+
them without an ``ARG``, they never reach the image's config or history,
|
|
178
|
+
and they do not change a cache key. Both spellings, since ``apt`` and
|
|
179
|
+
``curl`` read only the lower-case one for plain HTTP and ``uv``, ``pip``
|
|
180
|
+
and ``micromamba`` read either.
|
|
181
|
+
"""
|
|
182
|
+
if not proxy:
|
|
183
|
+
return []
|
|
184
|
+
options: list[str] = []
|
|
185
|
+
for name in ("HTTP_PROXY", "HTTPS_PROXY", "http_proxy", "https_proxy"):
|
|
186
|
+
options += ["--opt", f"build-arg:{name}={proxy}"]
|
|
187
|
+
for name in ("NO_PROXY", "no_proxy"):
|
|
188
|
+
options += ["--opt", f"build-arg:{name}=127.0.0.1,localhost"]
|
|
189
|
+
return options
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
#: What each tool writes when the build pool's egress proxy refuses it a
|
|
193
|
+
#: tunnel (E2-19). Read from the tools themselves, through the chart's own
|
|
194
|
+
#: Squid refusing every host, on 2026-09-19: pip, uv 0.12, micromamba 2.3,
|
|
195
|
+
#: git, curl 8 without `-f`, wget, and a Go client — `buildkitd`'s own pulls.
|
|
196
|
+
#: Each is a refused CONNECT and nothing else: a host that answered 403 over
|
|
197
|
+
#: its own TLS says so differently. `curl -f` ("The requested URL returned
|
|
198
|
+
#: error: 403"), `wget -q` (nothing) and `apt` over plain HTTP ("403
|
|
199
|
+
#: Forbidden [IP: proxy]") cannot be told from the host's own 403, and are
|
|
200
|
+
#: left to the log.
|
|
201
|
+
_EGRESS_REFUSED = re.compile(
|
|
202
|
+
r"Tunnel connection failed: 403" # pip, requests, urllib3
|
|
203
|
+
r"|tunnel error: unsuccessful" # uv
|
|
204
|
+
r"|CONNECT tunnel failed, response 403" # curl, git, micromamba
|
|
205
|
+
r"|Proxy tunneling failed: Forbidden" # wget
|
|
206
|
+
r'|"https?://[^"\s]+": Forbidden' # Go: buildkitd, containerd
|
|
207
|
+
)
|
|
208
|
+
#: A host a line names: urllib3's `host='…'`, or the host of a URL.
|
|
209
|
+
_NAMED_HOST = re.compile(r"host='(?P<pool>[A-Za-z0-9.\-]+)'|https?://(?P<url>[A-Za-z0-9.\-]+)")
|
|
210
|
+
#: `buildctl`'s plain progress: `#12 0.874 <what the step wrote>`. Steps run
|
|
211
|
+
#: side by side, so a line is read against the lines of its own step.
|
|
212
|
+
_BUILDKIT_LINE = re.compile(r"^#(?P<step>\d+) (?:\d+\.\d+ )?(?P<text>.*)$")
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def egress_refused_hosts(log: str, *, proxy: str = "", limit: int = 10) -> list[str]:
|
|
216
|
+
"""The hosts the build pool's egress proxy refused, as a build's log shows them (E2-19).
|
|
217
|
+
|
|
218
|
+
A refusal is found by what the tool writes (`_EGRESS_REFUSED`), and its
|
|
219
|
+
host is the one the same line names — pip's `host='files.pythonhosted.org'`,
|
|
220
|
+
git's URL — or else the last one its step named before it: uv and
|
|
221
|
+
micromamba write the URL a line or four above the refusal, wget and a
|
|
222
|
+
silent `curl` only in the `RUN` line. The proxy's own address is never a
|
|
223
|
+
host it refused. In the order they were first refused, at most ``limit``.
|
|
224
|
+
"""
|
|
225
|
+
own = {"127.0.0.1", "localhost"}
|
|
226
|
+
if proxy:
|
|
227
|
+
own.add(proxy.split("://", 1)[-1].rsplit(":", 1)[0])
|
|
228
|
+
hosts: list[str] = []
|
|
229
|
+
last: dict[str, str] = {}
|
|
230
|
+
for raw in log.splitlines():
|
|
231
|
+
line = _BUILDKIT_LINE.match(raw)
|
|
232
|
+
step, text = (line.group("step"), line.group("text")) if line else ("", raw)
|
|
233
|
+
named = [
|
|
234
|
+
host.lower().rstrip(".")
|
|
235
|
+
for match in _NAMED_HOST.finditer(text)
|
|
236
|
+
for host in (match.group("pool") or match.group("url"),)
|
|
237
|
+
if host and host.lower().rstrip(".") not in own
|
|
238
|
+
]
|
|
239
|
+
if _EGRESS_REFUSED.search(text):
|
|
240
|
+
host = named[0] if named else last.get(step, "")
|
|
241
|
+
if host and host not in hosts:
|
|
242
|
+
hosts.append(host)
|
|
243
|
+
if len(hosts) >= limit:
|
|
244
|
+
break
|
|
245
|
+
if named:
|
|
246
|
+
last[step] = named[-1]
|
|
247
|
+
return hosts
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
def egress_findings(hosts: Sequence[str]) -> list[dict[str, str]]:
|
|
251
|
+
"""The refused hosts as a failure's findings: what a page lists, not the log."""
|
|
252
|
+
return [{"kind": "egress_refused", "subject": host} for host in hosts]
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
def egress_hosts_text(hosts: Sequence[str]) -> str:
|
|
256
|
+
quoted = [f"`{host}`" for host in hosts]
|
|
257
|
+
return quoted[0] if len(quoted) == 1 else ", ".join(quoted[:-1]) + " and " + quoted[-1]
|
|
258
|
+
|
|
259
|
+
|
|
148
260
|
#: How a protected pin is recorded in the lock.
|
|
149
261
|
PROTECTED_PIN_PREFIX = "# datalayer-protected: "
|
|
150
262
|
|
|
@@ -478,6 +590,19 @@ def parse_resolver_failure(
|
|
|
478
590
|
},
|
|
479
591
|
)
|
|
480
592
|
|
|
593
|
+
# An index the build pool may not reach is not an outage: resolving again
|
|
594
|
+
# is refused again, so it is said with the host rather than retried.
|
|
595
|
+
refused = egress_refused_hosts(output)
|
|
596
|
+
if refused and "No solution found" not in text:
|
|
597
|
+
return EnvironmentsError(
|
|
598
|
+
PACKAGE_NOT_FOUND,
|
|
599
|
+
f"The build pool's egress proxy refused {egress_hosts_text(refused)}: a version "
|
|
600
|
+
"resolves only against the indexes the build pool allows. Use one of them, or "
|
|
601
|
+
"ask for the host to be allowed",
|
|
602
|
+
detail={**detail, "refused_hosts": refused, "findings": egress_findings(refused)},
|
|
603
|
+
retryable=False,
|
|
604
|
+
)
|
|
605
|
+
|
|
481
606
|
pair = _conflicting_pair(mentions) if "No solution found" in text else None
|
|
482
607
|
if pair:
|
|
483
608
|
return EnvironmentsError(
|
|
@@ -623,8 +748,11 @@ class BuildkitResolveRunner:
|
|
|
623
748
|
tlscacert: str | None = None,
|
|
624
749
|
apt_snapshot: str = "",
|
|
625
750
|
timeout: float = 900.0,
|
|
751
|
+
proxy: str | None = None,
|
|
626
752
|
) -> None:
|
|
627
753
|
self._buildctl = (shutil.which("buildctl") or "") if buildctl is None else buildctl
|
|
754
|
+
#: The build pool's egress proxy (E1-06), or `DATALAYER_BUILDKIT_PROXY`.
|
|
755
|
+
self._proxy = buildkit_proxy(proxy)
|
|
628
756
|
#: The build pool's `buildkitd` takes mTLS connections only
|
|
629
757
|
#: (PLAN_ENV.md E1-06); a plain-socket one, such as `plane local`'s
|
|
630
758
|
#: own ephemeral daemon, needs none of these three. All or nothing,
|
|
@@ -761,6 +889,7 @@ class BuildkitResolveRunner:
|
|
|
761
889
|
f"dockerfile={root}",
|
|
762
890
|
"--output",
|
|
763
891
|
f"type=local,dest={out}",
|
|
892
|
+
*buildkit_proxy_options(self._proxy),
|
|
764
893
|
]
|
|
765
894
|
say(f"Solving the lock in {request.base_reference}")
|
|
766
895
|
try:
|
{code_sandboxes-1.9.35 → code_sandboxes-1.9.37}/code_sandboxes/environments/resolve_conda.py
RENAMED
|
@@ -68,6 +68,11 @@ from .resolve import (
|
|
|
68
68
|
WHEELHOUSE_PATH,
|
|
69
69
|
MergedRequirements,
|
|
70
70
|
ProtectedPin,
|
|
71
|
+
buildkit_proxy,
|
|
72
|
+
buildkit_proxy_options,
|
|
73
|
+
egress_findings,
|
|
74
|
+
egress_hosts_text,
|
|
75
|
+
egress_refused_hosts,
|
|
71
76
|
merge_requirements,
|
|
72
77
|
)
|
|
73
78
|
|
|
@@ -527,6 +532,18 @@ def parse_conda_failure(output: str) -> EnvironmentsError:
|
|
|
527
532
|
f"`{name}` is not in any channel this environment may read",
|
|
528
533
|
detail={**detail, "package": name},
|
|
529
534
|
)
|
|
535
|
+
# A channel the build pool may not reach: solving again is refused again,
|
|
536
|
+
# so it is said with the host rather than retried (E2-19).
|
|
537
|
+
refused = egress_refused_hosts(output)
|
|
538
|
+
if refused:
|
|
539
|
+
return EnvironmentsError(
|
|
540
|
+
PACKAGE_NOT_FOUND,
|
|
541
|
+
f"The build pool's egress proxy refused {egress_hosts_text(refused)}: a version "
|
|
542
|
+
"solves only against the channels the build pool allows. Use one of them, or "
|
|
543
|
+
"ask for the host to be allowed",
|
|
544
|
+
detail={**detail, "refused_hosts": refused, "findings": egress_findings(refused)},
|
|
545
|
+
retryable=False,
|
|
546
|
+
)
|
|
530
547
|
lowered = text.lower()
|
|
531
548
|
if (
|
|
532
549
|
"could not solve" in lowered
|
|
@@ -684,8 +701,11 @@ class BuildkitCondaResolveRunner:
|
|
|
684
701
|
tlskey: str | None = None,
|
|
685
702
|
tlscacert: str | None = None,
|
|
686
703
|
timeout: float = 1200.0,
|
|
704
|
+
proxy: str | None = None,
|
|
687
705
|
) -> None:
|
|
688
706
|
self._buildctl = (shutil.which("buildctl") or "") if buildctl is None else buildctl
|
|
707
|
+
#: The build pool's egress proxy (E1-06), or `DATALAYER_BUILDKIT_PROXY`.
|
|
708
|
+
self._proxy = buildkit_proxy(proxy)
|
|
689
709
|
self._tlscert = tlscert or ""
|
|
690
710
|
self._tlskey = tlskey or ""
|
|
691
711
|
self._tlscacert = tlscacert or ""
|
|
@@ -778,6 +798,7 @@ class BuildkitCondaResolveRunner:
|
|
|
778
798
|
f"dockerfile={root}",
|
|
779
799
|
"--output",
|
|
780
800
|
f"type=local,dest={out}",
|
|
801
|
+
*buildkit_proxy_options(self._proxy),
|
|
781
802
|
]
|
|
782
803
|
say(f"Solving the conda lock in {request.base_reference}")
|
|
783
804
|
try:
|
|
@@ -441,7 +441,16 @@ class ModalSandbox(Sandbox):
|
|
|
441
441
|
for mount_path, volume_id in self._volume_mounts.requested.items()
|
|
442
442
|
}
|
|
443
443
|
|
|
444
|
-
|
|
444
|
+
# An Environments artifact's main process only holds the container:
|
|
445
|
+
# everything this class runs in it is an exec, Jupyter included
|
|
446
|
+
# (`prepare_jupyter_server`). Named here rather than left to the
|
|
447
|
+
# image, since an artifact built before code-sandboxes 1.9.36 carries
|
|
448
|
+
# its base's `start-jupyter.sh` as its CMD, which Modal runs under the
|
|
449
|
+
# entrypoint; that server exits within a minute and ends the sandbox
|
|
450
|
+
# (found live on 2026-09-18: a smoke test's restarted sandbox died
|
|
451
|
+
# between checks 8 and 9).
|
|
452
|
+
command = ("sleep", "infinity") if self._image_id else ()
|
|
453
|
+
self._sandbox = modal.Sandbox.create(*command, **create_kwargs)
|
|
445
454
|
self._volume_mounts.created()
|
|
446
455
|
self._start_driver()
|
|
447
456
|
|
|
@@ -37,7 +37,7 @@ A document is refused with `DL_ENV_SPEC_INVALID` when a field is wrong, and with
|
|
|
37
37
|
| `commands.postInstall` | none | At most 32 non-empty commands, run after the packages are installed. |
|
|
38
38
|
| `buildSecrets` | none | `id` is a Datalayer secret id, `dlsec_...`; `mountAs` is `env` or `file`; `name` is the variable or file name. Ids and names are unique. Secrets are injected into the build step that needs them and never written into the artifact. |
|
|
39
39
|
| `resources.sizeClass` | `small` | `small`, `medium`, `large`, `gpu-small` or `gpu-large`. A GPU class needs an accelerator and a CUDA base; an accelerator needs a GPU class. Datalayer runs no GPU nodes yet, so a GPU class is built for Modal and Daytona, which bring their own GPUs; E2B has none. |
|
|
40
|
-
| `resources.accelerator` | `none` | `none`, or `type`, `count` and `cuda`. `type` is the provider's own name for the GPU (Daytona: `H100`, `H200`, `RTX-PRO-6000`, `RTX-4090`, `RTX-5090`), and a GPU a variant does not offer is refused for it at `validate`. `cuda` is the base's toolkit: `datalayer/python-cuda:2026.09` carries 12.8, and another version is refused. |
|
|
40
|
+
| `resources.accelerator` | `none` | `none`, or `type`, `count` and `cuda`. `type` is the provider's own name for the GPU (Modal: `T4`, `L4`, `A10G`, `L40S`, `A100`, `A100-40GB`, `A100-80GB`, `H100`, `H200`, `B200`; Daytona: `H100`, `H200`, `RTX-PRO-6000`, `RTX-4090`, `RTX-5090`), and a GPU a variant does not offer is refused for it at `validate`. `cuda` is the base's toolkit: `datalayer/python-cuda:2026.09` carries 12.8, and another version is refused. |
|
|
41
41
|
| `resources.hints` | none | `cpu`, `memoryGi`, `diskGi`: positive numbers, within the size class. |
|
|
42
42
|
| `compatibility.variants.required` | `[datalayer]` | At least one of `datalayer`, `e2b`, `daytona`, `modal`. |
|
|
43
43
|
| `compatibility.variants.optional` | none | The same variants, none of them also required. |
|
|
@@ -77,9 +77,11 @@ with Sandbox.create(
|
|
|
77
77
|
An [Environment](/environments) built for Modal is an **image id**,
|
|
78
78
|
`im-…` — pulled `from_aws_ecr` off the approved Datalayer base, with your
|
|
79
79
|
lock installed by `uv pip sync --require-hashes` on top. A published name
|
|
80
|
-
is worth having for operability, but a launch always pins the id:
|
|
81
|
-
build
|
|
82
|
-
|
|
80
|
+
is worth having for operability, but a launch always pins the id: a name
|
|
81
|
+
moves when the same build is published again, and the id is the only
|
|
82
|
+
reference that names one build's image. Modal answers an identical image
|
|
83
|
+
definition with the image it already has, so two builds of the same lock
|
|
84
|
+
can share one id.
|
|
83
85
|
|
|
84
86
|
**Bring your own account:** a build runs in the environment owner's own
|
|
85
87
|
Modal workspace, from the same `MODAL_TOKEN_ID`/`MODAL_TOKEN_SECRET` pair
|
|
@@ -96,8 +98,22 @@ with no image id — general Modal sandbox usage here is unaffected).
|
|
|
96
98
|
Confirmed live: a launched sandbox's identity check now passes, where it
|
|
97
99
|
used to report `uid: 0`.
|
|
98
100
|
|
|
99
|
-
**
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
101
|
+
**The sandbox is held by `sleep infinity`, not the base's Jupyter.**
|
|
102
|
+
Modal keeps the base image's CMD, `start-jupyter.sh`, under the builder's
|
|
103
|
+
`ENTRYPOINT`, where Docker would reset it, so a sandbox started with no
|
|
104
|
+
command ran a Jupyter server as its main process. That server exits
|
|
105
|
+
within a minute and the sandbox ends with it: "Modal Sandbox is shutting
|
|
106
|
+
down", a few commands in. Since 1.9.36 the artifact's CMD is
|
|
107
|
+
`sleep infinity`, and `ModalSandbox` names `sleep infinity` when it
|
|
108
|
+
launches an artifact, which covers images built by earlier releases too.
|
|
109
|
+
Jupyter is started by exec when it is asked for
|
|
110
|
+
(`prepare_jupyter_server`).
|
|
111
|
+
|
|
112
|
+
**GPU versions.** On Modal a GPU is a launch option, not part of the
|
|
113
|
+
image: a GPU version's image builds like any other on the CUDA base, and
|
|
114
|
+
its sandboxes start on the GPU the version names. The build's smoke test
|
|
115
|
+
does that (`gpu="L4"`, or `"H100:2"` for two) and adds the contract's
|
|
116
|
+
check 11: the GPUs asked for are visible, and the image's CUDA is the
|
|
117
|
+
version's. A GPU Modal does not offer — it offers `T4`, `L4`, `A10G`,
|
|
118
|
+
`L40S`, `A100`, `A100-40GB`, `A100-80GB`, `H100`, `H200`, `B200` — is
|
|
119
|
+
refused at `validate`, before anything is built.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#1 [internal] load build definition from Dockerfile
|
|
2
|
+
#1 transferring dockerfile: 80B done
|
|
3
|
+
#1 DONE 0.0s
|
|
4
|
+
|
|
5
|
+
#2 [internal] load metadata for ghcr.io/astral-sh/uv:0.12.11
|
|
6
|
+
#2 ERROR: failed to do request: Head "https://ghcr.io/v2/astral-sh/uv/manifests/0.12.11": Forbidden
|
|
7
|
+
------
|
|
8
|
+
> [internal] load metadata for ghcr.io/astral-sh/uv:0.12.11:
|
|
9
|
+
------
|
|
10
|
+
Dockerfile:1
|
|
11
|
+
--------------------
|
|
12
|
+
1 | >>> FROM ghcr.io/astral-sh/uv:0.12.11
|
|
13
|
+
2 | RUN true
|
|
14
|
+
3 |
|
|
15
|
+
--------------------
|
|
16
|
+
error: failed to solve: ghcr.io/astral-sh/uv:0.12.11: failed to resolve source metadata for ghcr.io/astral-sh/uv:0.12.11: failed to do request: Head "https://ghcr.io/v2/astral-sh/uv/manifests/0.12.11": Forbidden
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#1 [internal] load build definition from Dockerfile
|
|
2
|
+
#1 transferring dockerfile: 325B done
|
|
3
|
+
#1 DONE 0.0s
|
|
4
|
+
|
|
5
|
+
#2 [internal] load metadata for docker.io/library/buildpack-deps:bookworm-scm
|
|
6
|
+
#2 DONE 0.2s
|
|
7
|
+
|
|
8
|
+
#3 [internal] load .dockerignore
|
|
9
|
+
#3 transferring context: 2B done
|
|
10
|
+
#3 DONE 0.0s
|
|
11
|
+
|
|
12
|
+
#4 [1/4] FROM docker.io/library/buildpack-deps:bookworm-scm@sha256:bb8654d03bd8341e702f1ae30adca91a11f4164da2d37dbe7a0bf49e4901bd03
|
|
13
|
+
#4 CACHED
|
|
14
|
+
|
|
15
|
+
#5 [2/4] RUN git clone -q https://github.com/psf/requests.git /tmp/r || true
|
|
16
|
+
#5 0.063 fatal: unable to access 'https://github.com/psf/requests.git/': CONNECT tunnel failed, response 403
|
|
17
|
+
#5 DONE 0.1s
|
|
18
|
+
|
|
19
|
+
#6 [3/4] RUN curl -fsSL https://raw.githubusercontent.com/psf/requests/main/README.md -o /dev/null || true
|
|
20
|
+
#6 0.065 curl: (22) The requested URL returned error: 403
|
|
21
|
+
#6 DONE 0.1s
|
|
22
|
+
|
|
23
|
+
#7 [4/4] RUN wget https://github.com/psf/requests/archive/refs/tags/v2.32.3.tar.gz -O /dev/null
|
|
24
|
+
#7 0.060 --2026-09-19 08:44:09-- https://github.com/psf/requests/archive/refs/tags/v2.32.3.tar.gz
|
|
25
|
+
#7 0.066 Connecting to 172.18.0.2:3128... connected.
|
|
26
|
+
#7 0.067 Proxy tunneling failed: ForbiddenUnable to establish SSL connection.
|
|
27
|
+
#7 ERROR: process "/bin/sh -c wget https://github.com/psf/requests/archive/refs/tags/v2.32.3.tar.gz -O /dev/null" did not complete successfully: exit code: 4
|
|
28
|
+
------
|
|
29
|
+
> [4/4] RUN wget https://github.com/psf/requests/archive/refs/tags/v2.32.3.tar.gz -O /dev/null:
|
|
30
|
+
0.060 --2026-09-19 08:44:09-- https://github.com/psf/requests/archive/refs/tags/v2.32.3.tar.gz
|
|
31
|
+
0.066 Connecting to 172.18.0.2:3128... connected.
|
|
32
|
+
0.067 Proxy tunneling failed: ForbiddenUnable to establish SSL connection.
|
|
33
|
+
------
|
|
34
|
+
Dockerfile:4
|
|
35
|
+
--------------------
|
|
36
|
+
2 | RUN git clone -q https://github.com/psf/requests.git /tmp/r || true
|
|
37
|
+
3 | RUN curl -fsSL https://raw.githubusercontent.com/psf/requests/main/README.md -o /dev/null || true
|
|
38
|
+
4 | >>> RUN wget https://github.com/psf/requests/archive/refs/tags/v2.32.3.tar.gz -O /dev/null
|
|
39
|
+
5 |
|
|
40
|
+
--------------------
|
|
41
|
+
error: failed to solve: process "/bin/sh -c wget https://github.com/psf/requests/archive/refs/tags/v2.32.3.tar.gz -O /dev/null" did not complete successfully: exit code: 4
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
#1 [internal] load build definition from Dockerfile
|
|
2
|
+
#1 transferring dockerfile: 192B done
|
|
3
|
+
#1 DONE 0.0s
|
|
4
|
+
|
|
5
|
+
#2 [internal] load metadata for docker.io/library/python:3.12-slim
|
|
6
|
+
#2 DONE 0.2s
|
|
7
|
+
|
|
8
|
+
#3 [internal] load .dockerignore
|
|
9
|
+
#3 transferring context: 2B done
|
|
10
|
+
#3 DONE 0.0s
|
|
11
|
+
|
|
12
|
+
#4 [1/3] FROM docker.io/library/python:3.12-slim@sha256:2f17fc044b579bab302c2e8054d3a686e2cb9a83de48e70534b94cd8ebbe06a9
|
|
13
|
+
#4 CACHED
|
|
14
|
+
|
|
15
|
+
#5 [2/3] RUN pip install --no-cache-dir --index-url https://pypi.example-private.io/simple requests
|
|
16
|
+
#5 0.887 Looking in indexes: https://pypi.example-private.io/simple
|
|
17
|
+
#5 0.890 WARNING: Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden'))': /simple/requests/
|
|
18
|
+
#5 1.391 WARNING: Retrying (Retry(total=3, connect=None, read=None, redirect=None, status=None)) after connection broken by 'ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden'))': /simple/requests/
|
|
19
|
+
#5 2.393 WARNING: Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden'))': /simple/requests/
|
|
20
|
+
#5 4.395 WARNING: Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden'))': /simple/requests/
|
|
21
|
+
#5 8.397 WARNING: Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden'))': /simple/requests/
|
|
22
|
+
#5 8.401 ERROR: Could not find a version that satisfies the requirement requests (from versions: none)
|
|
23
|
+
#5 8.413 ERROR: No matching distribution found for requests
|
|
24
|
+
#5 ERROR: process "/bin/sh -c pip install --no-cache-dir --index-url https://pypi.example-private.io/simple requests" did not complete successfully: exit code: 1
|
|
25
|
+
------
|
|
26
|
+
> [2/3] RUN pip install --no-cache-dir --index-url https://pypi.example-private.io/simple requests:
|
|
27
|
+
0.887 Looking in indexes: https://pypi.example-private.io/simple
|
|
28
|
+
0.890 WARNING: Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden'))': /simple/requests/
|
|
29
|
+
1.391 WARNING: Retrying (Retry(total=3, connect=None, read=None, redirect=None, status=None)) after connection broken by 'ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden'))': /simple/requests/
|
|
30
|
+
2.393 WARNING: Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden'))': /simple/requests/
|
|
31
|
+
4.395 WARNING: Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden'))': /simple/requests/
|
|
32
|
+
8.397 WARNING: Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden'))': /simple/requests/
|
|
33
|
+
8.401 ERROR: Could not find a version that satisfies the requirement requests (from versions: none)
|
|
34
|
+
8.413 ERROR: No matching distribution found for requests
|
|
35
|
+
------
|
|
36
|
+
Dockerfile:2
|
|
37
|
+
--------------------
|
|
38
|
+
1 | FROM python:3.12-slim
|
|
39
|
+
2 | >>> RUN pip install --no-cache-dir --index-url https://pypi.example-private.io/simple requests
|
|
40
|
+
3 | RUN pip install --no-cache-dir requests
|
|
41
|
+
4 |
|
|
42
|
+
--------------------
|
|
43
|
+
error: failed to solve: process "/bin/sh -c pip install --no-cache-dir --index-url https://pypi.example-private.io/simple requests" did not complete successfully: exit code: 1
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#1 [internal] load build definition from Dockerfile
|
|
2
|
+
#1 transferring dockerfile: 193B done
|
|
3
|
+
#1 DONE 0.0s
|
|
4
|
+
|
|
5
|
+
#2 [internal] load metadata for docker.io/library/python:3.12-slim
|
|
6
|
+
#2 DONE 0.2s
|
|
7
|
+
|
|
8
|
+
#3 [internal] load .dockerignore
|
|
9
|
+
#3 transferring context: 2B done
|
|
10
|
+
#3 DONE 0.0s
|
|
11
|
+
|
|
12
|
+
#4 [1/3] FROM docker.io/library/python:3.12-slim@sha256:2f17fc044b579bab302c2e8054d3a686e2cb9a83de48e70534b94cd8ebbe06a9
|
|
13
|
+
#4 DONE 0.0s
|
|
14
|
+
|
|
15
|
+
#5 [internal] load build context
|
|
16
|
+
#5 transferring context: 26B done
|
|
17
|
+
#5 DONE 0.0s
|
|
18
|
+
|
|
19
|
+
#6 [2/3] COPY uv /usr/local/bin/uv
|
|
20
|
+
#6 CACHED
|
|
21
|
+
|
|
22
|
+
#7 [3/3] RUN uv pip install --system "requests @ https://github.com/psf/requests/archive/refs/tags/v2.32.3.tar.gz"
|
|
23
|
+
#7 0.175 Using Python 3.12.14 environment at: /usr/local
|
|
24
|
+
#7 9.090 × Failed to download and build `requests @
|
|
25
|
+
#7 9.090 │ https://github.com/psf/requests/archive/refs/tags/v2.32.3.tar.gz`
|
|
26
|
+
#7 9.090 ├─▶ Request failed after 3 retries in 8.9s
|
|
27
|
+
#7 9.090 ├─▶ Failed to fetch:
|
|
28
|
+
#7 9.090 │ `https://github.com/psf/requests/archive/refs/tags/v2.32.3.tar.gz`
|
|
29
|
+
#7 9.090 ├─▶ error sending request for url
|
|
30
|
+
#7 9.090 │ (https://github.com/psf/requests/archive/refs/tags/v2.32.3.tar.gz)
|
|
31
|
+
#7 9.090 ├─▶ client error (Connect)
|
|
32
|
+
#7 9.090 ╰─▶ tunnel error: unsuccessful
|
|
33
|
+
#7 ERROR: process "/bin/sh -c uv pip install --system \"requests @ https://github.com/psf/requests/archive/refs/tags/v2.32.3.tar.gz\"" did not complete successfully: exit code: 1
|
|
34
|
+
------
|
|
35
|
+
> [3/3] RUN uv pip install --system "requests @ https://github.com/psf/requests/archive/refs/tags/v2.32.3.tar.gz":
|
|
36
|
+
0.175 Using Python 3.12.14 environment at: /usr/local
|
|
37
|
+
9.090 × Failed to download and build `requests @
|
|
38
|
+
9.090 │ https://github.com/psf/requests/archive/refs/tags/v2.32.3.tar.gz`
|
|
39
|
+
9.090 ├─▶ Request failed after 3 retries in 8.9s
|
|
40
|
+
9.090 ├─▶ Failed to fetch:
|
|
41
|
+
9.090 │ `https://github.com/psf/requests/archive/refs/tags/v2.32.3.tar.gz`
|
|
42
|
+
9.090 ├─▶ error sending request for url
|
|
43
|
+
9.090 │ (https://github.com/psf/requests/archive/refs/tags/v2.32.3.tar.gz)
|
|
44
|
+
9.090 ├─▶ client error (Connect)
|
|
45
|
+
9.090 ╰─▶ tunnel error: unsuccessful
|
|
46
|
+
------
|
|
47
|
+
Dockerfile:3
|
|
48
|
+
--------------------
|
|
49
|
+
1 | FROM python:3.12-slim
|
|
50
|
+
2 | COPY uv /usr/local/bin/uv
|
|
51
|
+
3 | >>> RUN uv pip install --system "requests @ https://github.com/psf/requests/archive/refs/tags/v2.32.3.tar.gz"
|
|
52
|
+
4 |
|
|
53
|
+
--------------------
|
|
54
|
+
error: failed to solve: process "/bin/sh -c uv pip install --system \"requests @ https://github.com/psf/requests/archive/refs/tags/v2.32.3.tar.gz\"" did not complete successfully: exit code: 1
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
warning libmamba Download error (56) Failure when receiving data from the peer [https://conda.anaconda.org/conda-forge/noarch/repodata.json.zst]
|
|
2
|
+
CONNECT tunnel failed, response 403
|
|
3
|
+
warning libmamba Retrying in 2 seconds
|
|
4
|
+
warning libmamba Download error (56) Failure when receiving data from the peer [https://conda.anaconda.org/conda-forge/linux-64/repodata.json.zst]
|
|
5
|
+
CONNECT tunnel failed, response 403
|
|
6
|
+
warning libmamba Retrying in 2 seconds
|
|
7
|
+
warning libmamba Download error (56) Failure when receiving data from the peer [https://conda.anaconda.org/conda-forge/noarch/repodata.json.zst]
|
|
8
|
+
CONNECT tunnel failed, response 403
|
|
9
|
+
warning libmamba Retrying in 2 seconds
|
|
10
|
+
warning libmamba Download error (56) Failure when receiving data from the peer [https://conda.anaconda.org/conda-forge/linux-64/repodata.json.zst]
|
|
11
|
+
CONNECT tunnel failed, response 403
|
|
12
|
+
warning libmamba Retrying in 2 seconds
|
|
13
|
+
warning libmamba Download error (56) Failure when receiving data from the peer [https://conda.anaconda.org/conda-forge/noarch/repodata.json.zst]
|
|
14
|
+
CONNECT tunnel failed, response 403
|
|
15
|
+
warning libmamba Retrying in 2 seconds
|
|
16
|
+
warning libmamba Download error (56) Failure when receiving data from the peer [https://conda.anaconda.org/conda-forge/linux-64/repodata.json.zst]
|
|
17
|
+
CONNECT tunnel failed, response 403
|
|
18
|
+
warning libmamba Retrying in 2 seconds
|
|
19
|
+
warning libmamba Download error (56) Failure when receiving data from the peer [https://conda.anaconda.org/conda-forge/noarch/repodata.json.zst]
|
|
20
|
+
CONNECT tunnel failed, response 403
|
|
21
|
+
warning libmamba Retrying in 2 seconds
|
|
22
|
+
critical libmamba Multiple errors occurred:
|
|
23
|
+
Download error (56) Failure when receiving data from the peer [https://conda.anaconda.org/conda-forge/noarch/repodata.json.zst]
|
|
24
|
+
CONNECT tunnel failed, response 403
|
|
25
|
+
Subdir conda-forge/noarch not loaded!
|
|
26
|
+
If you run into this error repeatedly, your package cache may be corrupted.
|
|
27
|
+
Please try running `mamba clean -a` to remove this cache before retrying the operation.
|
|
28
|
+
|
|
29
|
+
If you still are having issues, please report the error on `mamba-org/mamba`'s issue tracker:
|
|
30
|
+
https://github.com/mamba-org/mamba/issues/new?assignees=&labels=&projects=&template=bug.yml
|