code-sandboxes 1.9.37__tar.gz → 1.9.39__tar.gz

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