modAL 1.2.7.dev9__tar.gz → 1.2.7.dev10__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 (194) hide show
  1. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/PKG-INFO +1 -1
  2. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_container_entrypoint.py +0 -1
  3. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_utils/grpc_utils.py +0 -2
  4. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_utils/package_utils.py +0 -1
  5. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_utils/task_command_router_client.py +14 -0
  6. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/client.pyi +2 -2
  7. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/image.py +1 -0
  8. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/sandbox.py +44 -0
  9. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/sandbox.pyi +39 -0
  10. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal.egg-info/PKG-INFO +1 -1
  11. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal_version/__init__.py +1 -1
  12. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/LICENSE +0 -0
  13. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/README.md +0 -0
  14. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/__init__.py +0 -0
  15. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/__main__.py +0 -0
  16. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_billing.py +0 -0
  17. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_clustered_functions.py +0 -0
  18. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_clustered_functions.pyi +0 -0
  19. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_functions.py +0 -0
  20. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_grpc_client.py +0 -0
  21. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_ipython.py +0 -0
  22. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_load_context.py +0 -0
  23. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_location.py +0 -0
  24. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_object.py +0 -0
  25. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_output.py +0 -0
  26. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_partial_function.py +0 -0
  27. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_pty.py +0 -0
  28. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_resolver.py +0 -0
  29. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_resources.py +0 -0
  30. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_runtime/__init__.py +0 -0
  31. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_runtime/asgi.py +0 -0
  32. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_runtime/container_io_manager.py +0 -0
  33. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_runtime/container_io_manager.pyi +0 -0
  34. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_runtime/execution_context.py +0 -0
  35. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_runtime/execution_context.pyi +0 -0
  36. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_runtime/gpu_memory_snapshot.py +0 -0
  37. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_runtime/telemetry.py +0 -0
  38. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_runtime/user_code_event_loop.py +0 -0
  39. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_runtime/user_code_imports.py +0 -0
  40. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_serialization.py +0 -0
  41. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_traceback.py +0 -0
  42. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_tunnel.py +0 -0
  43. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_tunnel.pyi +0 -0
  44. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_type_manager.py +0 -0
  45. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_utils/__init__.py +0 -0
  46. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_utils/app_utils.py +0 -0
  47. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_utils/async_utils.py +0 -0
  48. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_utils/auth_token_manager.py +0 -0
  49. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_utils/blob_utils.py +0 -0
  50. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_utils/bytes_io_segment_payload.py +0 -0
  51. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_utils/deprecation.py +0 -0
  52. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_utils/docker_utils.py +0 -0
  53. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_utils/function_utils.py +0 -0
  54. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_utils/git_utils.py +0 -0
  55. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_utils/grpc_testing.py +0 -0
  56. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_utils/hash_utils.py +0 -0
  57. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_utils/http_utils.py +0 -0
  58. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_utils/jwt_utils.py +0 -0
  59. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_utils/logger.py +0 -0
  60. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_utils/mount_utils.py +0 -0
  61. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_utils/name_utils.py +0 -0
  62. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_utils/pattern_utils.py +0 -0
  63. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_utils/rand_pb_testing.py +0 -0
  64. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_utils/shell_utils.py +0 -0
  65. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_utils/time_utils.py +0 -0
  66. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_vendor/__init__.py +0 -0
  67. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_vendor/a2wsgi_wsgi.py +0 -0
  68. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_vendor/cloudpickle.py +0 -0
  69. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_vendor/tblib.py +0 -0
  70. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/_watcher.py +0 -0
  71. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/app.py +0 -0
  72. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/app.pyi +0 -0
  73. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/billing.py +0 -0
  74. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/builder/2023.12.312.txt +0 -0
  75. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/builder/2023.12.txt +0 -0
  76. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/builder/2024.04.txt +0 -0
  77. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/builder/2024.10.txt +0 -0
  78. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/builder/2025.06.txt +0 -0
  79. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/builder/PREVIEW.txt +0 -0
  80. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/builder/README.md +0 -0
  81. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/builder/base-images.json +0 -0
  82. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/call_graph.py +0 -0
  83. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/cli/__init__.py +0 -0
  84. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/cli/_download.py +0 -0
  85. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/cli/_traceback.py +0 -0
  86. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/cli/app.py +0 -0
  87. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/cli/cluster.py +0 -0
  88. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/cli/config.py +0 -0
  89. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/cli/container.py +0 -0
  90. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/cli/dict.py +0 -0
  91. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/cli/entry_point.py +0 -0
  92. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/cli/environment.py +0 -0
  93. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/cli/import_refs.py +0 -0
  94. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/cli/launch.py +0 -0
  95. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/cli/network_file_system.py +0 -0
  96. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/cli/profile.py +0 -0
  97. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/cli/programs/__init__.py +0 -0
  98. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/cli/programs/run_jupyter.py +0 -0
  99. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/cli/programs/vscode.py +0 -0
  100. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/cli/queues.py +0 -0
  101. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/cli/run.py +0 -0
  102. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/cli/secret.py +0 -0
  103. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/cli/shell.py +0 -0
  104. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/cli/token.py +0 -0
  105. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/cli/utils.py +0 -0
  106. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/cli/volume.py +0 -0
  107. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/client.py +0 -0
  108. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/cloud_bucket_mount.py +0 -0
  109. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/cloud_bucket_mount.pyi +0 -0
  110. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/cls.py +0 -0
  111. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/cls.pyi +0 -0
  112. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/config.py +0 -0
  113. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/container_process.py +0 -0
  114. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/container_process.pyi +0 -0
  115. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/dict.py +0 -0
  116. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/dict.pyi +0 -0
  117. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/environments.py +0 -0
  118. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/environments.pyi +0 -0
  119. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/exception.py +0 -0
  120. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/experimental/__init__.py +0 -0
  121. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/experimental/flash.py +0 -0
  122. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/experimental/flash.pyi +0 -0
  123. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/experimental/ipython.py +0 -0
  124. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/file_io.py +0 -0
  125. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/file_io.pyi +0 -0
  126. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/file_pattern_matcher.py +0 -0
  127. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/functions.py +0 -0
  128. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/functions.pyi +0 -0
  129. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/gpu.py +0 -0
  130. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/image.pyi +0 -0
  131. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/io_streams.py +0 -0
  132. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/io_streams.pyi +0 -0
  133. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/mount.py +0 -0
  134. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/mount.pyi +0 -0
  135. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/network_file_system.py +0 -0
  136. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/network_file_system.pyi +0 -0
  137. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/object.py +0 -0
  138. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/object.pyi +0 -0
  139. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/output.py +0 -0
  140. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/parallel_map.py +0 -0
  141. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/parallel_map.pyi +0 -0
  142. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/partial_function.py +0 -0
  143. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/partial_function.pyi +0 -0
  144. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/proxy.py +0 -0
  145. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/proxy.pyi +0 -0
  146. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/py.typed +0 -0
  147. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/queue.py +0 -0
  148. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/queue.pyi +0 -0
  149. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/retries.py +0 -0
  150. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/runner.py +0 -0
  151. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/runner.pyi +0 -0
  152. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/running_app.py +0 -0
  153. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/schedule.py +0 -0
  154. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/scheduler_placement.py +0 -0
  155. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/secret.py +0 -0
  156. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/secret.pyi +0 -0
  157. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/serving.py +0 -0
  158. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/serving.pyi +0 -0
  159. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/snapshot.py +0 -0
  160. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/snapshot.pyi +0 -0
  161. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/stream_type.py +0 -0
  162. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/token_flow.py +0 -0
  163. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/token_flow.pyi +0 -0
  164. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/volume.py +0 -0
  165. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal/volume.pyi +0 -0
  166. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal.egg-info/SOURCES.txt +0 -0
  167. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal.egg-info/dependency_links.txt +0 -0
  168. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal.egg-info/entry_points.txt +0 -0
  169. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal.egg-info/requires.txt +0 -0
  170. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal.egg-info/top_level.txt +0 -0
  171. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal_docs/__init__.py +0 -0
  172. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal_docs/gen_cli_docs.py +0 -0
  173. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal_docs/gen_reference_docs.py +0 -0
  174. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal_docs/mdmd/__init__.py +0 -0
  175. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal_docs/mdmd/mdmd.py +0 -0
  176. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal_docs/mdmd/signatures.py +0 -0
  177. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal_proto/__init__.py +0 -0
  178. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal_proto/api.proto +0 -0
  179. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal_proto/api_grpc.py +0 -0
  180. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal_proto/api_pb2.py +0 -0
  181. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal_proto/api_pb2.pyi +0 -0
  182. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal_proto/api_pb2_grpc.py +0 -0
  183. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal_proto/api_pb2_grpc.pyi +0 -0
  184. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal_proto/modal_api_grpc.py +0 -0
  185. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal_proto/py.typed +0 -0
  186. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal_proto/task_command_router.proto +0 -0
  187. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal_proto/task_command_router_grpc.py +0 -0
  188. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal_proto/task_command_router_pb2.py +0 -0
  189. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal_proto/task_command_router_pb2.pyi +0 -0
  190. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal_proto/task_command_router_pb2_grpc.py +0 -0
  191. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal_proto/task_command_router_pb2_grpc.pyi +0 -0
  192. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/modal_version/__main__.py +0 -0
  193. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/pyproject.toml +0 -0
  194. {modal-1.2.7.dev9 → modal-1.2.7.dev10}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.2.7.dev9
3
+ Version: 1.2.7.dev10
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -43,7 +43,6 @@ from ._runtime.container_io_manager import (
43
43
  )
44
44
 
45
45
  if TYPE_CHECKING:
46
- import modal._object
47
46
  import modal._runtime.container_io_manager
48
47
  import modal._runtime.user_code_imports
49
48
 
@@ -16,8 +16,6 @@ from typing import Any, Optional, Sequence, TypeVar
16
16
  import grpclib.client
17
17
  import grpclib.config
18
18
  import grpclib.events
19
- import grpclib.protocol
20
- import grpclib.stream
21
19
  from google.protobuf.message import Message
22
20
  from google.protobuf.symbol_database import SymbolDatabase
23
21
  from grpclib import GRPCError, Status
@@ -1,5 +1,4 @@
1
1
  # Copyright Modal Labs 2022
2
- import importlib
3
2
  import importlib.util
4
3
  import typing
5
4
  from importlib.metadata import PackageNotFoundError, files
@@ -521,3 +521,17 @@ class TaskCommandRouterClient:
521
521
  await sleep_and_update_delay_and_num_retries_remaining(e)
522
522
  else:
523
523
  raise ConnectionError(str(e))
524
+
525
+ async def mount_image(self, request: sr_pb2.TaskMountDirectoryRequest):
526
+ with grpc_error_converter():
527
+ return await call_with_retries_on_transient_errors(
528
+ lambda: self._call_with_auth_retry(self._stub.TaskMountDirectory, request)
529
+ )
530
+
531
+ async def snapshot_directory(
532
+ self, request: sr_pb2.TaskSnapshotDirectoryRequest
533
+ ) -> sr_pb2.TaskSnapshotDirectoryResponse:
534
+ with grpc_error_converter():
535
+ return await call_with_retries_on_transient_errors(
536
+ lambda: self._call_with_auth_retry(self._stub.TaskSnapshotDirectory, request)
537
+ )
@@ -32,7 +32,7 @@ class _Client:
32
32
  server_url: str,
33
33
  client_type: int,
34
34
  credentials: typing.Optional[tuple[str, str]],
35
- version: str = "1.2.7.dev9",
35
+ version: str = "1.2.7.dev10",
36
36
  ):
37
37
  """mdmd:hidden
38
38
  The Modal client object is not intended to be instantiated directly by users.
@@ -163,7 +163,7 @@ class Client:
163
163
  server_url: str,
164
164
  client_type: int,
165
165
  credentials: typing.Optional[tuple[str, str]],
166
- version: str = "1.2.7.dev9",
166
+ version: str = "1.2.7.dev10",
167
167
  ):
168
168
  """mdmd:hidden
169
169
  The Modal client object is not intended to be instantiated directly by users.
@@ -874,6 +874,7 @@ class _Image(_Object, type_prefix="im"):
874
874
 
875
875
  rep = f"Image.from_id({image_id!r})"
876
876
  obj = _Image._from_loader(_load, rep, load_context_overrides=LoadContext(client=client))
877
+ obj._object_id = image_id
877
878
 
878
879
  return obj
879
880
 
@@ -6,6 +6,7 @@ import time
6
6
  import uuid
7
7
  from collections.abc import AsyncGenerator, Collection, Sequence
8
8
  from dataclasses import dataclass
9
+ from pathlib import PurePosixPath
9
10
  from typing import TYPE_CHECKING, Any, AsyncIterator, Literal, Optional, Union, overload
10
11
 
11
12
  from ._pty import get_pty_info
@@ -600,6 +601,49 @@ class _Sandbox(_Object, type_prefix="sb"):
600
601
 
601
602
  return image
602
603
 
604
+ async def _experimental_mount_image(self, path: Union[PurePosixPath, str], image: Optional[_Image]):
605
+ """Mount an Image at a path in the Sandbox filesystem."""
606
+
607
+ image_id = None
608
+
609
+ if image:
610
+ if not image._object_id:
611
+ # FIXME
612
+ raise InvalidError("Image has not been built.")
613
+ image_id = image._object_id
614
+ else:
615
+ image_id = "" # empty string indicates mount an empty dir
616
+
617
+ task_id = await self._get_task_id()
618
+ if (command_router_client := await self._get_command_router_client(task_id)) is None:
619
+ raise InvalidError("Mounting directories requires direct Sandbox control - please contact Modal support.")
620
+
621
+ posix_path = PurePosixPath(path)
622
+ if not posix_path.is_absolute():
623
+ raise InvalidError(f"Mount path must be absolute; got: {posix_path}")
624
+ path_bytes = posix_path.as_posix().encode("utf8")
625
+
626
+ req = sr_pb2.TaskMountDirectoryRequest(task_id=task_id, path=path_bytes, image_id=image_id)
627
+ await command_router_client.mount_image(req)
628
+
629
+ async def _experimental_snapshot_directory(self, path: Union[PurePosixPath, str]) -> _Image:
630
+ """Snapshot local changes to a previously mounted Image, creating a new Image."""
631
+
632
+ task_id = await self._get_task_id()
633
+ if (command_router_client := await self._get_command_router_client(task_id)) is None:
634
+ raise InvalidError(
635
+ "Snapshotting directories requires direct Sandbox control - please contact Modal support."
636
+ )
637
+
638
+ posix_path = PurePosixPath(path)
639
+ if not posix_path.is_absolute():
640
+ raise InvalidError(f"Snapshot path must be absolute; got: {posix_path}")
641
+ path_bytes = posix_path.as_posix().encode("utf8")
642
+
643
+ req = sr_pb2.TaskSnapshotDirectoryRequest(task_id=task_id, path=path_bytes)
644
+ res = await command_router_client.snapshot_directory(req)
645
+ return _Image._new_hydrated(res.image_id, self._client, None)
646
+
603
647
  # Live handle methods
604
648
 
605
649
  async def wait(self, raise_on_termination: bool = True):
@@ -22,6 +22,7 @@ import modal.stream_type
22
22
  import modal.volume
23
23
  import modal_proto.api_pb2
24
24
  import os
25
+ import pathlib
25
26
  import typing
26
27
  import typing_extensions
27
28
 
@@ -254,6 +255,18 @@ class _Sandbox(modal._object._Object):
254
255
  """
255
256
  ...
256
257
 
258
+ async def _experimental_mount_image(
259
+ self, path: typing.Union[pathlib.PurePosixPath, str], image: typing.Optional[modal.image._Image]
260
+ ):
261
+ """Mount an Image at a path in the Sandbox filesystem."""
262
+ ...
263
+
264
+ async def _experimental_snapshot_directory(
265
+ self, path: typing.Union[pathlib.PurePosixPath, str]
266
+ ) -> modal.image._Image:
267
+ """Snapshot local changes to a previously mounted Image, creating a new Image."""
268
+ ...
269
+
257
270
  async def wait(self, raise_on_termination: bool = True):
258
271
  """Wait for the Sandbox to finish running."""
259
272
  ...
@@ -820,6 +833,32 @@ class Sandbox(modal.object.Object):
820
833
 
821
834
  snapshot_filesystem: __snapshot_filesystem_spec[typing_extensions.Self]
822
835
 
836
+ class ___experimental_mount_image_spec(typing_extensions.Protocol[SUPERSELF]):
837
+ def __call__(
838
+ self, /, path: typing.Union[pathlib.PurePosixPath, str], image: typing.Optional[modal.image.Image]
839
+ ):
840
+ """Mount an Image at a path in the Sandbox filesystem."""
841
+ ...
842
+
843
+ async def aio(
844
+ self, /, path: typing.Union[pathlib.PurePosixPath, str], image: typing.Optional[modal.image.Image]
845
+ ):
846
+ """Mount an Image at a path in the Sandbox filesystem."""
847
+ ...
848
+
849
+ _experimental_mount_image: ___experimental_mount_image_spec[typing_extensions.Self]
850
+
851
+ class ___experimental_snapshot_directory_spec(typing_extensions.Protocol[SUPERSELF]):
852
+ def __call__(self, /, path: typing.Union[pathlib.PurePosixPath, str]) -> modal.image.Image:
853
+ """Snapshot local changes to a previously mounted Image, creating a new Image."""
854
+ ...
855
+
856
+ async def aio(self, /, path: typing.Union[pathlib.PurePosixPath, str]) -> modal.image.Image:
857
+ """Snapshot local changes to a previously mounted Image, creating a new Image."""
858
+ ...
859
+
860
+ _experimental_snapshot_directory: ___experimental_snapshot_directory_spec[typing_extensions.Self]
861
+
823
862
  class __wait_spec(typing_extensions.Protocol[SUPERSELF]):
824
863
  def __call__(self, /, raise_on_termination: bool = True):
825
864
  """Wait for the Sandbox to finish running."""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.2.7.dev9
3
+ Version: 1.2.7.dev10
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -1,4 +1,4 @@
1
1
  # Copyright Modal Labs 2025
2
2
  """Supplies the current version of the modal client library."""
3
3
 
4
- __version__ = "1.2.7.dev9"
4
+ __version__ = "1.2.7.dev10"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes