code-sandboxes 1.9.2__tar.gz → 1.9.3__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.
Files changed (262) hide show
  1. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/CHANGELOG.md +11 -0
  2. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/PKG-INFO +1 -1
  3. code_sandboxes-1.9.3/build.log +5 -0
  4. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/__version__.py +1 -1
  5. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/environments/adapters/datalayer.py +13 -10
  6. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/environments/spec.py +24 -0
  7. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_environment_datalayer_builder.py +24 -12
  8. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_environment_spec.py +29 -1
  9. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/.github/workflows/build.yml +0 -0
  10. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/.github/workflows/environments-live.yml +0 -0
  11. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/.github/workflows/py-code-style.yml +0 -0
  12. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/.github/workflows/py-tests.yml +0 -0
  13. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/.github/workflows/py-typing.yml +0 -0
  14. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/.github/workflows/reusable-python.yml +0 -0
  15. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/.gitignore +0 -0
  16. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/.licenserc.yaml +0 -0
  17. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/.pre-commit-config.yaml +0 -0
  18. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/.vscode/settings.json +0 -0
  19. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/Dockerfile +0 -0
  20. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/LICENSE +0 -0
  21. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/Makefile +0 -0
  22. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/README.md +0 -0
  23. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/__init__.py +0 -0
  24. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/base.py +0 -0
  25. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/bridge_mount.py +0 -0
  26. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/builds.py +0 -0
  27. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/cli.py +0 -0
  28. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/client.py +0 -0
  29. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/cloudflare_sandbox.py +0 -0
  30. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/commands.py +0 -0
  31. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/console.py +0 -0
  32. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/contents.py +0 -0
  33. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/coreweave_sandbox.py +0 -0
  34. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/datalayer_sandbox.py +0 -0
  35. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/daytona_sandbox.py +0 -0
  36. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/docker_sandbox.py +0 -0
  37. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/e2b_sandbox.py +0 -0
  38. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/environments/__init__.py +0 -0
  39. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/environments/__main__.py +0 -0
  40. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/environments/accounts.py +0 -0
  41. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/environments/adapters/__init__.py +0 -0
  42. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/environments/adapters/daytona.py +0 -0
  43. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/environments/adapters/e2b.py +0 -0
  44. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/environments/adapters/managed.py +0 -0
  45. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/environments/adapters/modal.py +0 -0
  46. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/environments/attest.py +0 -0
  47. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/environments/bases.py +0 -0
  48. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/environments/breaker.py +0 -0
  49. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/environments/build_secrets.py +0 -0
  50. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/environments/builders.py +0 -0
  51. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/environments/canonical.py +0 -0
  52. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/environments/conformance.py +0 -0
  53. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/environments/constraints/sandbox-contract-v1.txt +0 -0
  54. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/environments/constraints/wheelhouse/README.md +0 -0
  55. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/environments/constraints/wheelhouse/jupyter_server-2.21.0+datalayer.1-py3-none-any.whl +0 -0
  56. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/environments/contract.py +0 -0
  57. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/environments/doctor/__init__.py +0 -0
  58. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/environments/doctor/build.py +0 -0
  59. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/environments/doctor/datalayer_sandbox.py +0 -0
  60. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/environments/doctor/report.schema.json +0 -0
  61. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/environments/errors.py +0 -0
  62. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/environments/files.py +0 -0
  63. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/environments/image_import.py +0 -0
  64. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/environments/lifecycle.py +0 -0
  65. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/environments/policy.py +0 -0
  66. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/environments/redact.py +0 -0
  67. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/environments/resolve.py +0 -0
  68. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/environments/schema.py +0 -0
  69. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/eval_sandbox.py +0 -0
  70. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/exceptions.py +0 -0
  71. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/filesystem.py +0 -0
  72. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/google_colab.py +0 -0
  73. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/google_colab_sandbox.py +0 -0
  74. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/interfaces.py +0 -0
  75. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/jupyter_ingress.py +0 -0
  76. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/jupyter_server_sandbox.py +0 -0
  77. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/kaggle.py +0 -0
  78. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/kaggle_execute.py +0 -0
  79. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/kaggle_live.py +0 -0
  80. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/kaggle_sandbox.py +0 -0
  81. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/lifecycle.py +0 -0
  82. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/manage.py +0 -0
  83. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/modal_sandbox.py +0 -0
  84. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/models.py +0 -0
  85. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/monty_sandbox.py +0 -0
  86. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/provider_ingress.py +0 -0
  87. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/code_sandboxes/providers.py +0 -0
  88. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docker/Dockerfile +0 -0
  89. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/.gitignore +0 -0
  90. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/LICENSE +0 -0
  91. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/Makefile +0 -0
  92. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/README.md +0 -0
  93. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/babel.config.js +0 -0
  94. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/docs/api-reference/_category_.yml +0 -0
  95. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/docs/api-reference/index.mdx +0 -0
  96. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/docs/cli/_category_.yml +0 -0
  97. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/docs/cli/index.mdx +0 -0
  98. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/docs/contribute/_category_.yml +0 -0
  99. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/docs/contribute/index.mdx +0 -0
  100. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/docs/environments/_category_.yml +0 -0
  101. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/docs/environments/contract.mdx +0 -0
  102. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/docs/environments/index.mdx +0 -0
  103. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/docs/environments/specification.mdx +0 -0
  104. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/docs/environments/spike-2026-09.mdx +0 -0
  105. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/docs/examples/_category_.yml +0 -0
  106. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/docs/examples/index.mdx +0 -0
  107. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/docs/guide/_category_.yml +0 -0
  108. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/docs/guide/index.mdx +0 -0
  109. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/docs/index.mdx +0 -0
  110. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/docs/install/_category_.yml +0 -0
  111. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/docs/install/index.mdx +0 -0
  112. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/docs/provider-ingress.mdx +0 -0
  113. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/docs/providers/_category_.yml +0 -0
  114. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/docs/providers/cloudflare.mdx +0 -0
  115. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/docs/providers/coreweave.mdx +0 -0
  116. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/docs/providers/datalayer.mdx +0 -0
  117. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/docs/providers/daytona.mdx +0 -0
  118. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/docs/providers/docker.mdx +0 -0
  119. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/docs/providers/e2b.mdx +0 -0
  120. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/docs/providers/eval.mdx +0 -0
  121. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/docs/providers/google-colab.mdx +0 -0
  122. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/docs/providers/index.mdx +0 -0
  123. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/docs/providers/jupyter-server.mdx +0 -0
  124. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/docs/providers/kaggle.mdx +0 -0
  125. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/docs/providers/modal.mdx +0 -0
  126. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/docs/providers/monty.mdx +0 -0
  127. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/docusaurus.config.js +0 -0
  128. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/package.json +0 -0
  129. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/sidebars.js +0 -0
  130. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/src/components/HomepageRow1.js +0 -0
  131. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/src/components/HomepageRow1.module.css +0 -0
  132. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/src/components/HomepageRow2.js +0 -0
  133. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/src/components/HomepageRow2.module.css +0 -0
  134. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/src/components/HomepageRow3.js +0 -0
  135. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/src/components/HomepageRow3.module.css +0 -0
  136. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/src/css/custom.css +0 -0
  137. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/src/pages/index.module.css +0 -0
  138. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/src/pages/markdown-page.md +0 -0
  139. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/src/theme/CustomDocItem.tsx +0 -0
  140. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/src/theme/IconsTitle.tsx +0 -0
  141. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/static/img/bricks.svg +0 -0
  142. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/static/img/building-construction.svg +0 -0
  143. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/static/img/cloud-sun.svg +0 -0
  144. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/static/img/cloud.svg +0 -0
  145. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/static/img/collaboration.svg +0 -0
  146. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/static/img/copy-left.svg +0 -0
  147. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/static/img/datalayer/logo.png +0 -0
  148. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/static/img/datalayer/logo.svg +0 -0
  149. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/static/img/datalayer/personas/business.svg +0 -0
  150. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/static/img/datalayer/personas/data-scientist.svg +0 -0
  151. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/static/img/datalayer/personas/devops.svg +0 -0
  152. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/static/img/datalayer/project/project-line.svg +0 -0
  153. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/static/img/favicon.ico +0 -0
  154. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/static/img/jupyter.svg +0 -0
  155. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/static/img/open-source.svg +0 -0
  156. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/static/img/react-js.svg +0 -0
  157. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/static/img/react-js2.svg +0 -0
  158. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/static/img/ringed-planet.svg +0 -0
  159. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/static/img/robot.svg +0 -0
  160. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/static/img/rocket.svg +0 -0
  161. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/static/img/shield.svg +0 -0
  162. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/static/img/sparkles.svg +0 -0
  163. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/static/img/streamlit.gif +0 -0
  164. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/static/img/super-hero.svg +0 -0
  165. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/static/img/target.svg +0 -0
  166. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/docs/static/img/thumbs-up.svg +0 -0
  167. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/examples/README.md +0 -0
  168. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/examples/exec/Makefile +0 -0
  169. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/examples/exec/cloudflare_sandbox_example.py +0 -0
  170. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/examples/exec/coreweave_sandbox_example.py +0 -0
  171. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/examples/exec/datalayer_sandbox_example.py +0 -0
  172. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/examples/exec/daytona_sandbox_example.py +0 -0
  173. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/examples/exec/docker_sandbox_example.py +0 -0
  174. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/examples/exec/e2b_sandbox_example.py +0 -0
  175. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/examples/exec/eval_sandbox_example.py +0 -0
  176. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/examples/exec/google_colab_sandbox_example.py +0 -0
  177. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/examples/exec/jupyter_server_sandbox_example.py +0 -0
  178. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/examples/exec/kaggle_sandbox_example.py +0 -0
  179. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/examples/exec/modal_sandbox_example.py +0 -0
  180. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/examples/exec/monty_sandbox_example.py +0 -0
  181. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/examples/repl/Makefile +0 -0
  182. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/examples/repl/cloudflare_sandbox_example.py +0 -0
  183. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/examples/repl/coreweave_sandbox_example.py +0 -0
  184. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/examples/repl/datalayer_sandbox_example.py +0 -0
  185. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/examples/repl/daytona_sandbox_example.py +0 -0
  186. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/examples/repl/docker_sandbox_example.py +0 -0
  187. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/examples/repl/e2b_sandbox_example.py +0 -0
  188. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/examples/repl/eval_sandbox_example.py +0 -0
  189. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/examples/repl/google_colab_sandbox_example.py +0 -0
  190. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/examples/repl/jupyter_server_sandbox_example.py +0 -0
  191. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/examples/repl/kaggle_sandbox_example.py +0 -0
  192. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/examples/repl/modal_sandbox_example.py +0 -0
  193. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/examples/repl/monty_sandbox_example.py +0 -0
  194. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/pyproject.toml +0 -0
  195. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/schemas/environment-v1alpha1.json +0 -0
  196. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/__init__.py +0 -0
  197. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/conftest.py +0 -0
  198. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_a_datalayer_sandbox_can_be_interrupted.py +0 -0
  199. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_bridge_mount.py +0 -0
  200. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_builds.py +0 -0
  201. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_cli_exec.py +0 -0
  202. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_cli_repl.py +0 -0
  203. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_client.py +0 -0
  204. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_client_contents.py +0 -0
  205. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_client_files.py +0 -0
  206. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_client_outcome_error_output.py +0 -0
  207. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_cloudflare.py +0 -0
  208. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_commands_envelope.py +0 -0
  209. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_console.py +0 -0
  210. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_contents_contract.py +0 -0
  211. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_contents_live_matrix.py +0 -0
  212. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_coreweave.py +0 -0
  213. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_datalayer_sandbox.py +0 -0
  214. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_daytona.py +0 -0
  215. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_e2b.py +0 -0
  216. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_environment_accounts.py +0 -0
  217. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_environment_attest.py +0 -0
  218. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_environment_bases.py +0 -0
  219. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_environment_breaker.py +0 -0
  220. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_environment_build_secrets.py +0 -0
  221. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_environment_builders.py +0 -0
  222. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_environment_canonical.py +0 -0
  223. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_environment_conformance.py +0 -0
  224. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_environment_constraints.py +0 -0
  225. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_environment_contract.py +0 -0
  226. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_environment_cross_variant_report.py +0 -0
  227. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_environment_daytona_builder.py +0 -0
  228. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_environment_doctor.py +0 -0
  229. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_environment_e2b_builder.py +0 -0
  230. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_environment_errors.py +0 -0
  231. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_environment_image_import.py +0 -0
  232. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_environment_lifecycle.py +0 -0
  233. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_environment_live_matrix.py +0 -0
  234. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_environment_managed_builders.py +0 -0
  235. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_environment_modal_builder.py +0 -0
  236. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_environment_redact.py +0 -0
  237. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_environment_resolve.py +0 -0
  238. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_eval.py +0 -0
  239. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_every_variant_has_a_real_interrupt.py +0 -0
  240. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_factory.py +0 -0
  241. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_google_colab.py +0 -0
  242. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_integration.py +0 -0
  243. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_jupyter_ingress.py +0 -0
  244. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_jupyter_server.py +0 -0
  245. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_jupyter_server_streaming.py +0 -0
  246. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_kaggle.py +0 -0
  247. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_kaggle_execute.py +0 -0
  248. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_kaggle_live.py +0 -0
  249. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_kaggle_session.py +0 -0
  250. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_kernel_client_compatibility.py +0 -0
  251. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_lifecycle_vocabulary.py +0 -0
  252. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_manage.py +0 -0
  253. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_manage_datalayer.py +0 -0
  254. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_modal_google_colab_sandbox.py +0 -0
  255. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_modal_session.py +0 -0
  256. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_models.py +0 -0
  257. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_output_line_fidelity.py +0 -0
  258. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_provider_catalog_names.py +0 -0
  259. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_provider_ingress.py +0 -0
  260. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_providers.py +0 -0
  261. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_sandboxes.py +0 -0
  262. {code_sandboxes-1.9.2 → code_sandboxes-1.9.3}/tests/test_the_kill_relaunch_drill.py +0 -0
@@ -8,6 +8,17 @@
8
8
 
9
9
  ## Unreleased
10
10
 
11
+ ## 1.9.3
12
+
13
+ - **A build secret is mounted only on the `postInstall` commands that name it**
14
+ (`environments.spec.command_names_secret`, `environments.adapters.datalayer`;
15
+ PLAN_ENV.md E3-05). Every declared secret used to be mounted on every
16
+ `postInstall` `RUN`. A command now gets a secret's mount only when the
17
+ secret's name is in it as a whole word (`$NAME`, `${NAME}`, `--key-env NAME`,
18
+ `/run/secrets/NAME`). A declared secret that no command names is a
19
+ `DL_ENV_SPEC_INVALID` finding on `spec.buildSecrets[i]`, rather than a build
20
+ that runs with it empty.
21
+
11
22
  ## 1.9.2
12
23
 
13
24
  - **A real ECR repository name is lowercase; a real owner uid is not**
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: code_sandboxes
3
- Version: 1.9.2
3
+ Version: 1.9.3
4
4
  Project-URL: Home, https://github.com/datalayer/code-sandboxes
5
5
  Author-email: Datalayer <info@datalayer.io>
6
6
  License: BSD 3-Clause License
@@ -0,0 +1,5 @@
1
+ * Creating isolated environment: venv+pip...
2
+ * Installing packages in isolated environment:
3
+ - hatchling~=1.21
4
+ * Getting build dependencies for sdist...
5
+ * Building sdist...
@@ -3,4 +3,4 @@
3
3
 
4
4
  """Code Sandboxes."""
5
5
 
6
- __version__ = "1.9.2"
6
+ __version__ = "1.9.3"
@@ -69,7 +69,7 @@ from ..errors import (
69
69
  )
70
70
  from ..files import files_step
71
71
  from ..resolve import WHEELHOUSE_IMAGE_PATH, WHEELHOUSE_PATH, apt_pins_in, locked_versions
72
- from ..spec import BuildSecret, Environment
72
+ from ..spec import BuildSecret, Environment, command_names_secret
73
73
 
74
74
  __all__ = [
75
75
  "ECR_ENVIRONMENT_PREFIX",
@@ -347,15 +347,14 @@ class Builder:
347
347
  "/opt/datalayer/lock.txt",
348
348
  ]
349
349
  )
350
- # A build secret is mounted on the postInstall step and nowhere else
351
- # (§4.1, D-11): never an `ARG` or `ENV`, which bakes a value into the
352
- # image's history, and never the package-install or files steps,
353
- # which no secret is declared for. `--mount=type=secret` is a
354
- # BuildKit mount: the value is available to the one `RUN`'s shell and
355
- # never written to a layer.
350
+ # A build secret is mounted on the postInstall commands that name it
351
+ # and nowhere else (§4.1, D-11): never an `ARG` or `ENV`, which bakes a
352
+ # value into the image's history, never the package-install or files
353
+ # steps, and never a postInstall command that does not read it.
354
+ # `--mount=type=secret` is a BuildKit mount: the value is available to
355
+ # the one `RUN`'s shell and never written to a layer.
356
356
  wanted = set(request.build_secret_ids)
357
357
  secrets = [secret for secret in spec.build_secrets if secret.id in wanted]
358
- secret_mounts = " ".join(_secret_mount(secret) for secret in secrets)
359
358
  baked = files_step(request.environment, variant=self.variant)
360
359
  if baked:
361
360
  lines.append("USER 1000:100")
@@ -365,11 +364,15 @@ class Builder:
365
364
  if spec.commands.post_install:
366
365
  lines.append("USER 1000:100")
367
366
  lines.append("WORKDIR /home/datalayer/content")
368
- prefix = "RUN --network=none " + (f"{secret_mounts} " if secret_mounts else "")
369
367
  for command in spec.commands.post_install:
370
368
  # No network: a command that fetches something makes an
371
369
  # artifact whose contents depend on the day it was built.
372
- lines.append(f"{prefix}{command}")
370
+ mounts = "".join(
371
+ f"{_secret_mount(secret)} "
372
+ for secret in secrets
373
+ if command_names_secret(command, secret)
374
+ )
375
+ lines.append(f"RUN --network=none {mounts}{command}")
373
376
  lines.extend(
374
377
  [
375
378
  "USER 1000:100",
@@ -83,6 +83,7 @@ __all__ = [
83
83
  "VariantSet",
84
84
  "VersionStatus",
85
85
  "assert_publishable",
86
+ "command_names_secret",
86
87
  "parse_environment",
87
88
  "parse_requirements_txt",
88
89
  "publication_findings",
@@ -200,6 +201,18 @@ class BuildSecret(_Model):
200
201
  name: str = Field(pattern=r"^[A-Za-z0-9_.-]+$")
201
202
 
202
203
 
204
+ def command_names_secret(command: str, secret: BuildSecret) -> bool:
205
+ """Whether one ``postInstall`` command names ``secret``, so its step gets the mount (E3-05).
206
+
207
+ A command names a secret when the secret's name is in it as a whole word:
208
+ ``$PIP_TOKEN``, ``${PIP_TOKEN}``, ``--key-env PIP_TOKEN`` or
209
+ ``/run/secrets/netrc``. A secret is mounted on exactly the steps that name
210
+ it (§4.1), so a command that reads none holds none.
211
+ """
212
+ word = rf"(?<![A-Za-z0-9_.-]){re.escape(secret.name)}(?![A-Za-z0-9_.-])"
213
+ return re.search(word, command) is not None
214
+
215
+
203
216
  class Accelerator(_Model):
204
217
  type: str
205
218
  count: int = Field(default=1, ge=1)
@@ -640,6 +653,17 @@ def spec_findings(
640
653
  values = [getattr(secret, attribute) for secret in spec.build_secrets]
641
654
  if len(values) != len(set(values)):
642
655
  findings.append(SpecFinding("spec.buildSecrets", f"a secret {label} is listed twice"))
656
+ for index, secret in enumerate(spec.build_secrets):
657
+ # A secret no command names would be mounted nowhere: the build would
658
+ # run with it empty and fail far from the cause.
659
+ if not any(command_names_secret(command, secret) for command in spec.commands.post_install):
660
+ findings.append(
661
+ SpecFinding(
662
+ f"spec.buildSecrets[{index}]",
663
+ f"`{secret.name}` is named by no `postInstall` command, and a secret "
664
+ "is mounted only on the commands that name it",
665
+ )
666
+ )
643
667
 
644
668
  resources = spec.resources
645
669
  if resources.size_class not in SIZE_CLASSES:
@@ -95,6 +95,18 @@ class FakeEcr:
95
95
  return error
96
96
 
97
97
 
98
+ #: One build secret, named by one of two `postInstall` commands (E3-05).
99
+ A_SECRET = {
100
+ "buildSecrets": [{"id": "dlsec_01J9BUILDSECRET0000000000", "name": "PIP_TOKEN"}],
101
+ "commands": {
102
+ "postInstall": [
103
+ "python -c 'import geopandas'",
104
+ "python unpack_tiles.py --key-env PIP_TOKEN",
105
+ ]
106
+ },
107
+ }
108
+
109
+
98
110
  def a_request(**changes) -> BuildRequest:
99
111
  """The section 4.1 example as a build of version 3, attempt `bld-1`."""
100
112
  spec = {
@@ -236,21 +248,20 @@ class TestTheDockerfileItGenerates:
236
248
  # Never the loose list: that is the whole point of resolving once.
237
249
  assert "geopandas==1.1.1" not in dockerfile
238
250
 
239
- def test_a_build_secret_is_mounted_for_the_postinstall_step_alone(self) -> None:
240
- """Mounted on the `postInstall` `RUN` alone — never an `ARG`/`ENV`,
241
- which bakes a value into the image's history, and never the
242
- package-install or files steps, which name no secret (§4.1, D-11)."""
243
- request = a_request(
244
- spec={"buildSecrets": [{"id": "dlsec_01J9BUILDSECRET0000000000", "name": "PIP_TOKEN"}]},
245
- build_secret_ids=("dlsec_01J9BUILDSECRET0000000000",),
246
- )
251
+ def test_a_build_secret_is_mounted_for_the_command_that_names_it_alone(self) -> None:
252
+ """Mounted on the `postInstall` `RUN` that names it alone — never an
253
+ `ARG`/`ENV`, which bakes a value into the image's history, never the
254
+ package-install or files steps, and never a `postInstall` command
255
+ that does not read it (§4.1, D-11)."""
256
+ request = a_request(spec=A_SECRET, build_secret_ids=("dlsec_01J9BUILDSECRET0000000000",))
247
257
  dockerfile = a_builder().dockerfile(request)
248
258
  lines = dockerfile.splitlines()
249
259
  mount_lines = [line for line in lines if "--mount=type=secret" in line]
250
260
  assert mount_lines == [
251
261
  "RUN --network=none --mount=type=secret,id=dlsec_01J9BUILDSECRET0000000000,"
252
- "env=PIP_TOKEN python -c 'import geopandas'"
262
+ "env=PIP_TOKEN python unpack_tiles.py --key-env PIP_TOKEN"
253
263
  ]
264
+ assert "RUN --network=none python -c 'import geopandas'" in lines
254
265
  # Nowhere else in the Dockerfile: no `ARG`/`ENV` line, and no other
255
266
  # `RUN` mentions the id or the value's own name.
256
267
  assert not any(line.startswith(("ARG", "ENV")) and "PIP_TOKEN" in line for line in lines)
@@ -265,7 +276,8 @@ class TestTheDockerfileItGenerates:
265
276
  "name": "netrc",
266
277
  "mountAs": "file",
267
278
  }
268
- ]
279
+ ],
280
+ "commands": {"postInstall": ["python unpack_tiles.py --netrc /run/secrets/netrc"]},
269
281
  },
270
282
  build_secret_ids=("dlsec_01J9BUILDSECRET0000000000",),
271
283
  )
@@ -480,7 +492,7 @@ class TestBuildingAndPushing:
480
492
  return result
481
493
 
482
494
  request = a_request(
483
- spec={"buildSecrets": [{"id": "dlsec_01J9BUILDSECRET0000000000", "name": "PIP_TOKEN"}]},
495
+ spec=A_SECRET,
484
496
  build_secret_ids=("dlsec_01J9BUILDSECRET0000000000",),
485
497
  )
486
498
  buildctl = RecordingBuildctl()
@@ -501,7 +513,7 @@ class TestBuildingAndPushing:
501
513
  raise EnvironmentsError(BUILD_SECRET_UNAVAILABLE, "IAM is unreachable")
502
514
 
503
515
  request = a_request(
504
- spec={"buildSecrets": [{"id": "dlsec_01J9BUILDSECRET0000000000", "name": "PIP_TOKEN"}]},
516
+ spec=A_SECRET,
505
517
  build_secret_ids=("dlsec_01J9BUILDSECRET0000000000",),
506
518
  )
507
519
  buildctl = Buildctl()
@@ -23,8 +23,10 @@ from code_sandboxes.environments.errors import EnvironmentsError
23
23
  from code_sandboxes.environments.schema import main as schema_main
24
24
  from code_sandboxes.environments.schema import schema_text
25
25
  from code_sandboxes.environments.spec import (
26
+ BuildSecret,
26
27
  Environment,
27
28
  assert_publishable,
29
+ command_names_secret,
28
30
  parse_environment,
29
31
  publication_findings,
30
32
  spec_digest,
@@ -72,10 +74,11 @@ spec:
72
74
  commands:
73
75
  postInstall:
74
76
  - "python -c 'import geopandas'"
77
+ - "python unpack_tiles.py --key-env TILES_LICENSE_KEY"
75
78
  buildSecrets:
76
79
  - id: dlsec_01J8ZK
77
80
  mountAs: env
78
- name: PIP_EXTRA_INDEX_TOKEN
81
+ name: TILES_LICENSE_KEY
79
82
  resources:
80
83
  accelerator: none
81
84
  hints:
@@ -195,6 +198,13 @@ UNSUPPORTED = "DL_ENV_CAPABILITY_UNSUPPORTED"
195
198
  ("spec.language.version", "3.9", "spec.language.version", INVALID),
196
199
  ("spec.build.source", "dockerfile", "spec.build.source", UNSUPPORTED),
197
200
  ("spec.packages.python.manager", "conda", "spec.packages.python.manager", UNSUPPORTED),
201
+ # E3-05: a secret no postInstall command names would be mounted nowhere.
202
+ (
203
+ "spec.commands.postInstall",
204
+ ["python -c 'import geopandas'"],
205
+ "spec.buildSecrets[0]",
206
+ INVALID,
207
+ ),
198
208
  (
199
209
  "spec.packages.python.dependencies.0",
200
210
  "geopandas>=>1",
@@ -526,6 +536,24 @@ def test_a_spec_is_digested_the_same_from_the_environment_or_the_spec() -> None:
526
536
  assert spec_digest(environment) == spec_digest(environment.spec)
527
537
 
528
538
 
539
+ @pytest.mark.parametrize(
540
+ ("command", "named"),
541
+ [
542
+ ("python unpack_tiles.py --key-env TOKEN", True),
543
+ ('curl -H "Authorization: $TOKEN" x', True),
544
+ ("echo ${TOKEN}", True),
545
+ ("cat /run/secrets/TOKEN", True),
546
+ ("echo $TOKEN_FILE", False),
547
+ ("echo $MY_TOKEN", False),
548
+ ("python -c 'import geopandas'", False),
549
+ ],
550
+ )
551
+ def test_a_command_names_a_secret_by_its_whole_name(command: str, named: bool) -> None:
552
+ """E3-05: the Datalayer builder mounts a secret on the commands that name it."""
553
+ secret = BuildSecret(id="dlsec_01J8ZK", name="TOKEN")
554
+ assert command_names_secret(command, secret) is named
555
+
556
+
529
557
  class TestPublicationFindings:
530
558
  """D-12: a version with any build secret can never be published to the Library."""
531
559
 
File without changes
File without changes
File without changes