modal 1.5.6.dev9__tar.gz → 1.5.6.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 (236) hide show
  1. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/PKG-INFO +1 -1
  2. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/client.pyi +2 -2
  3. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/sandbox.py +152 -22
  4. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/sandbox.pyi +263 -0
  5. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal.egg-info/PKG-INFO +1 -1
  6. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal_version/__init__.py +1 -1
  7. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/LICENSE +0 -0
  8. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/README.md +0 -0
  9. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/__init__.py +0 -0
  10. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/__main__.py +0 -0
  11. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_billing.py +0 -0
  12. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_clustered_functions.py +0 -0
  13. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_clustered_functions.pyi +0 -0
  14. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_container_entrypoint.py +0 -0
  15. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_environments.py +0 -0
  16. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_function_variants.py +0 -0
  17. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_functions.py +0 -0
  18. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_grpc_client.py +0 -0
  19. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_image.py +0 -0
  20. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_ipython.py +0 -0
  21. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_load_context.py +0 -0
  22. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_location.py +0 -0
  23. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_logs.py +0 -0
  24. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_logs_manager.py +0 -0
  25. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_logs_manager.pyi +0 -0
  26. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_object.py +0 -0
  27. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_output/__init__.py +0 -0
  28. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_output/manager.py +0 -0
  29. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_output/pty.py +0 -0
  30. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_output/rich.py +0 -0
  31. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_output/status.py +0 -0
  32. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_partial_function.py +0 -0
  33. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_resolver.py +0 -0
  34. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_resources.py +0 -0
  35. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_runtime/__init__.py +0 -0
  36. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_runtime/asgi.py +0 -0
  37. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_runtime/container_io_manager.py +0 -0
  38. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_runtime/container_io_manager.pyi +0 -0
  39. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_runtime/execution_context.py +0 -0
  40. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_runtime/execution_context.pyi +0 -0
  41. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_runtime/gpu_memory_snapshot.py +0 -0
  42. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_runtime/task_lifecycle_manager.py +0 -0
  43. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_runtime/task_lifecycle_manager.pyi +0 -0
  44. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_runtime/telemetry.py +0 -0
  45. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_runtime/user_code_event_loop.py +0 -0
  46. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_runtime/user_code_imports.py +0 -0
  47. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_serialization.py +0 -0
  48. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_server.py +0 -0
  49. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_supports_logs.py +0 -0
  50. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_traceback.py +0 -0
  51. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_tunnel.py +0 -0
  52. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_tunnel.pyi +0 -0
  53. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_type_manager.py +0 -0
  54. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_utils/__init__.py +0 -0
  55. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_utils/app_utils.py +0 -0
  56. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_utils/async_utils.py +0 -0
  57. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_utils/auth_token_manager.py +0 -0
  58. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_utils/blob_utils.py +0 -0
  59. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_utils/browser_utils.py +0 -0
  60. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_utils/bytes_io_segment_payload.py +0 -0
  61. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_utils/curl_utils.py +0 -0
  62. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_utils/deprecation.py +0 -0
  63. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_utils/display_utils.py +0 -0
  64. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_utils/docker_utils.py +0 -0
  65. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_utils/function_utils.py +0 -0
  66. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_utils/git_utils.py +0 -0
  67. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_utils/grpc_testing.py +0 -0
  68. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_utils/grpc_utils.py +0 -0
  69. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_utils/hash_utils.py +0 -0
  70. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_utils/http_utils.py +0 -0
  71. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_utils/jwt_utils.py +0 -0
  72. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_utils/logger.py +0 -0
  73. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_utils/mount_utils.py +0 -0
  74. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_utils/name_utils.py +0 -0
  75. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_utils/package_utils.py +0 -0
  76. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_utils/pattern_utils.py +0 -0
  77. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_utils/proxy_support.py +0 -0
  78. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_utils/rand_pb_testing.py +0 -0
  79. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_utils/sandbox_fs_utils.py +0 -0
  80. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_utils/shell_utils.py +0 -0
  81. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_utils/task_command_router_client.py +0 -0
  82. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_utils/time_utils.py +0 -0
  83. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_vendor/__init__.py +0 -0
  84. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_vendor/a2wsgi_wsgi.py +0 -0
  85. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_vendor/cloudpickle.py +0 -0
  86. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_vendor/tblib.py +0 -0
  87. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_vendor/version.py +0 -0
  88. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_watcher.py +0 -0
  89. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/_workspace.py +0 -0
  90. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/app.py +0 -0
  91. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/app.pyi +0 -0
  92. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/billing.py +0 -0
  93. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/billing.pyi +0 -0
  94. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/builder/2023.12.312.txt +0 -0
  95. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/builder/2023.12.txt +0 -0
  96. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/builder/2024.04.txt +0 -0
  97. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/builder/2024.10.txt +0 -0
  98. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/builder/2025.06.txt +0 -0
  99. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/builder/PREVIEW.txt +0 -0
  100. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/builder/README.md +0 -0
  101. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/builder/base-images.json +0 -0
  102. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/call_graph.py +0 -0
  103. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/cli/__init__.py +0 -0
  104. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/cli/_download.py +0 -0
  105. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/cli/_help.py +0 -0
  106. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/cli/_traceback.py +0 -0
  107. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/cli/app.py +0 -0
  108. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/cli/billing.py +0 -0
  109. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/cli/bootstrap.py +0 -0
  110. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/cli/changelog.py +0 -0
  111. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/cli/cluster.py +0 -0
  112. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/cli/config.py +0 -0
  113. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/cli/container.py +0 -0
  114. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/cli/curl.py +0 -0
  115. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/cli/dashboard.py +0 -0
  116. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/cli/dict.py +0 -0
  117. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/cli/endpoint.py +0 -0
  118. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/cli/entry_point.py +0 -0
  119. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/cli/environment.py +0 -0
  120. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/cli/image.py +0 -0
  121. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/cli/import_refs.py +0 -0
  122. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/cli/launch.py +0 -0
  123. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/cli/logo.py +0 -0
  124. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/cli/network_file_system.py +0 -0
  125. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/cli/profile.py +0 -0
  126. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/cli/programs/__init__.py +0 -0
  127. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/cli/programs/run_jupyter.py +0 -0
  128. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/cli/programs/vscode.py +0 -0
  129. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/cli/queues.py +0 -0
  130. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/cli/run.py +0 -0
  131. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/cli/secret.py +0 -0
  132. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/cli/selector.py +0 -0
  133. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/cli/shell.py +0 -0
  134. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/cli/skills.py +0 -0
  135. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/cli/token.py +0 -0
  136. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/cli/utils.py +0 -0
  137. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/cli/volume.py +0 -0
  138. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/cli/workspace.py +0 -0
  139. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/client.py +0 -0
  140. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/cloud_bucket_mount.py +0 -0
  141. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/cloud_bucket_mount.pyi +0 -0
  142. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/cls.py +0 -0
  143. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/cls.pyi +0 -0
  144. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/config.py +0 -0
  145. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/container_process.py +0 -0
  146. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/container_process.pyi +0 -0
  147. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/dict.py +0 -0
  148. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/dict.pyi +0 -0
  149. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/environments.py +0 -0
  150. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/environments.pyi +0 -0
  151. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/exception.py +0 -0
  152. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/experimental/__init__.py +0 -0
  153. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/experimental/flash.py +0 -0
  154. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/experimental/flash.pyi +0 -0
  155. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/experimental/ipython.py +0 -0
  156. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/file_io.py +0 -0
  157. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/file_io.pyi +0 -0
  158. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/file_pattern_matcher.py +0 -0
  159. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/functions.py +0 -0
  160. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/functions.pyi +0 -0
  161. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/image.py +0 -0
  162. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/image.pyi +0 -0
  163. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/io_streams.py +0 -0
  164. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/io_streams.pyi +0 -0
  165. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/mount.py +0 -0
  166. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/mount.pyi +0 -0
  167. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/network_file_system.py +0 -0
  168. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/network_file_system.pyi +0 -0
  169. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/object.py +0 -0
  170. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/object.pyi +0 -0
  171. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/output.py +0 -0
  172. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/parallel_map.py +0 -0
  173. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/parallel_map.pyi +0 -0
  174. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/partial_function.py +0 -0
  175. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/partial_function.pyi +0 -0
  176. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/proxy.py +0 -0
  177. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/proxy.pyi +0 -0
  178. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/py.typed +0 -0
  179. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/queue.py +0 -0
  180. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/queue.pyi +0 -0
  181. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/retries.py +0 -0
  182. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/runner.py +0 -0
  183. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/runner.pyi +0 -0
  184. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/running_app.py +0 -0
  185. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/sandbox_fs.py +0 -0
  186. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/sandbox_fs.pyi +0 -0
  187. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/schedule.py +0 -0
  188. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/scheduler_placement.py +0 -0
  189. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/secret.py +0 -0
  190. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/secret.pyi +0 -0
  191. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/server.py +0 -0
  192. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/server.pyi +0 -0
  193. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/serving.py +0 -0
  194. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/serving.pyi +0 -0
  195. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/skills/modal/SKILL.md +0 -0
  196. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/snapshot.py +0 -0
  197. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/snapshot.pyi +0 -0
  198. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/stream_type.py +0 -0
  199. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/token_flow.py +0 -0
  200. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/token_flow.pyi +0 -0
  201. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/types.py +0 -0
  202. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/volume.py +0 -0
  203. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/volume.pyi +0 -0
  204. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/workspace.py +0 -0
  205. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal/workspace.pyi +0 -0
  206. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal.egg-info/SOURCES.txt +0 -0
  207. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal.egg-info/dependency_links.txt +0 -0
  208. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal.egg-info/entry_points.txt +0 -0
  209. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal.egg-info/requires.txt +0 -0
  210. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal.egg-info/top_level.txt +0 -0
  211. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal_docs/__init__.py +0 -0
  212. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal_docs/gen_cli_docs.py +0 -0
  213. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal_docs/gen_cli_docs_main.py +0 -0
  214. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal_docs/gen_reference_docs.py +0 -0
  215. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal_docs/gen_reference_docs_main.py +0 -0
  216. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal_docs/mdmd/__init__.py +0 -0
  217. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal_docs/mdmd/mdmd.py +0 -0
  218. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal_docs/mdmd/signatures.py +0 -0
  219. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal_docs/mdmd/types.py +0 -0
  220. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal_docs/reference_intro.md +0 -0
  221. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal_proto/__init__.py +0 -0
  222. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal_proto/api_grpc.py +0 -0
  223. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal_proto/api_pb2.py +0 -0
  224. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal_proto/api_pb2.pyi +0 -0
  225. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal_proto/api_pb2_grpc.py +0 -0
  226. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal_proto/api_pb2_grpc.pyi +0 -0
  227. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal_proto/modal_api_grpc.py +0 -0
  228. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal_proto/py.typed +0 -0
  229. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal_proto/task_command_router_grpc.py +0 -0
  230. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal_proto/task_command_router_pb2.py +0 -0
  231. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal_proto/task_command_router_pb2.pyi +0 -0
  232. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal_proto/task_command_router_pb2_grpc.py +0 -0
  233. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal_proto/task_command_router_pb2_grpc.pyi +0 -0
  234. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/modal_version/__main__.py +0 -0
  235. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/pyproject.toml +0 -0
  236. {modal-1.5.6.dev9 → modal-1.5.6.dev10}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.5.6.dev9
3
+ Version: 1.5.6.dev10
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License-Expression: Apache-2.0
@@ -77,7 +77,7 @@ class _Client:
77
77
  server_url: str,
78
78
  client_type: int,
79
79
  credentials: typing.Optional[tuple[str, str]],
80
- version: str = "1.5.6.dev9",
80
+ version: str = "1.5.6.dev10",
81
81
  *,
82
82
  oauth_credentials: typing.Optional[_OAuthCredentials] = None,
83
83
  ):
@@ -277,7 +277,7 @@ class Client:
277
277
  server_url: str,
278
278
  client_type: int,
279
279
  credentials: typing.Optional[tuple[str, str]],
280
- version: str = "1.5.6.dev9",
280
+ version: str = "1.5.6.dev10",
281
281
  *,
282
282
  oauth_credentials: typing.Optional[_OAuthCredentials] = None,
283
283
  ):
@@ -196,6 +196,30 @@ def _validate_experimental_encryption_key(key: bytes | None) -> bytes | None:
196
196
  return key
197
197
 
198
198
 
199
+ def _image_id_for_mount(image: _Image, method_name: str) -> str:
200
+ if not isinstance(image, _Image):
201
+ raise TypeError(f"{method_name}(image=...) expects an Image object, got {image!r}")
202
+
203
+ if image._mount_layers:
204
+ raise InvalidError(
205
+ f"{method_name}() only supports pre-built images. When using `add_local*` methods, "
206
+ "specify `copy=True` and call `.build()` before passing the image to `mount_image()`:\n\nE.g.\n"
207
+ 'img = modal.Image.debian_slim().add_local_file("foo", "/foo", copy=True).build(app)\n'
208
+ f"{method_name}(path, img)"
209
+ )
210
+ if image._is_empty:
211
+ return ""
212
+ if image._object_id:
213
+ return image._object_id
214
+ raise InvalidError(
215
+ f"{method_name}() currently only supports Images that are either:\n"
216
+ "- prebuilt using `image.build()`\n"
217
+ "- referenced by id, e.g. `Image.from_id()`\n"
218
+ "- filesystem/directory snapshots e.g. created by `.snapshot_directory()` "
219
+ "or `.snapshot_filesystem()`\n"
220
+ )
221
+
222
+
199
223
  if TYPE_CHECKING:
200
224
  import modal.app
201
225
 
@@ -1651,28 +1675,7 @@ class _Sandbox(_Object, type_prefix="sb"):
1651
1675
  sandbox_session_2.filesystem.list_files("/user_project")
1652
1676
  ```
1653
1677
  """
1654
- if not isinstance(image, _Image):
1655
- raise TypeError(f"Sandbox.mount_image(image=...) expects an Image object, got {image!r}")
1656
-
1657
- if image._mount_layers:
1658
- raise InvalidError(
1659
- "Sandbox.mount_image() only supports pre-built images. When using `add_local*` methods, "
1660
- "specify `copy=True` and call `.build()` before passing the image to `mount_image()`:\n\nE.g.\n"
1661
- 'img = modal.Image.debian_slim().add_local_file("foo", "/foo", copy=True).build(app)\n'
1662
- "sandbox.mount_image(path, img)"
1663
- )
1664
- if image._is_empty:
1665
- image_id = ""
1666
- elif image._object_id:
1667
- image_id = image._object_id
1668
- else:
1669
- raise InvalidError(
1670
- "Sandbox.mount_image() currently only supports Images that are either:\n"
1671
- "- prebuilt using `image.build()`\n"
1672
- "- referenced by id, e.g. `Image.from_id()`\n"
1673
- "- filesystem/directory snapshots e.g. created by `.snapshot_directory()` "
1674
- "or `.snapshot_filesystem()`\n"
1675
- )
1678
+ image_id = _image_id_for_mount(image, "Sandbox.mount_image")
1676
1679
 
1677
1680
  task_id = await self._get_task_id()
1678
1681
  command_router_client = await self._get_command_router_client(task_id)
@@ -2867,6 +2870,133 @@ class _SidecarContainer:
2867
2870
  self._filesystem = _SandboxFilesystem(self)
2868
2871
  return self._filesystem
2869
2872
 
2873
+ async def mount_image(
2874
+ self,
2875
+ path: PurePosixPath | str,
2876
+ image: _Image,
2877
+ *,
2878
+ _experimental_encryption_key: bytes | None = None,
2879
+ ) -> None:
2880
+ """Mount an Image at a specified path in this Sidecar container.
2881
+
2882
+ `path` should be a directory that is **not** the root path (`/`). If the path doesn't exist,
2883
+ it will be created. If it exists and contains data, the previous directory will be replaced
2884
+ by the mount.
2885
+
2886
+ The `image` argument supports any Image that has an object ID, including:
2887
+ - Images built using `image.build()`
2888
+ - Images referenced by ID, e.g. `Image.from_id(...)`
2889
+ - Filesystem/directory snapshots, e.g. created by `.snapshot_directory()` or `.snapshot_filesystem()`
2890
+ - Empty images created with `Image.from_scratch()`
2891
+
2892
+ Args:
2893
+ path: Absolute mount point directory inside the Sidecar container (not `/`).
2894
+ image: Image to mount at `path` (must be built, referenced by ID, or snapshot-based as described above).
2895
+
2896
+ Examples:
2897
+ ```py notest
2898
+ sidecar_1.mount_image("/workspace", modal.Image.from_scratch())
2899
+ workspace_snapshot = sidecar_1.snapshot_directory("/workspace")
2900
+
2901
+ # You can later mount this snapshot in another Sidecar:
2902
+ sidecar_2.mount_image("/workspace", workspace_snapshot)
2903
+ sidecar_2.filesystem.list_files("/workspace")
2904
+ ```
2905
+ """
2906
+ image_id = _image_id_for_mount(image, "SidecarContainer.mount_image")
2907
+
2908
+ posix_path = PurePosixPath(path)
2909
+ if not posix_path.is_absolute():
2910
+ raise InvalidError(f"Mount path must be absolute; got: {posix_path}")
2911
+
2912
+ task_id, command_router_client = await self._get_command_router()
2913
+ await command_router_client.mount_image(
2914
+ sr_pb2.TaskMountDirectoryRequest(
2915
+ task_id=task_id,
2916
+ path=posix_path.as_posix().encode("utf8"),
2917
+ image_id=image_id,
2918
+ customer_supplied_encryption_key=_validate_experimental_encryption_key(_experimental_encryption_key),
2919
+ container_id=self._container_id,
2920
+ )
2921
+ )
2922
+
2923
+ async def unmount_image(self, path: PurePosixPath | str) -> None:
2924
+ """Unmount a previously mounted Image from this Sidecar container.
2925
+
2926
+ `path` must be the exact mount point that was passed to `.mount_image()`.
2927
+ After unmounting, the underlying Sidecar filesystem at that path becomes
2928
+ visible again.
2929
+
2930
+ Args:
2931
+ path: Absolute mount point directory to unmount.
2932
+
2933
+ """
2934
+ posix_path = PurePosixPath(path)
2935
+ if not posix_path.is_absolute():
2936
+ raise InvalidError(f"Unmount path must be absolute; got: {posix_path}")
2937
+
2938
+ task_id, command_router_client = await self._get_command_router()
2939
+ await command_router_client.unmount_image(
2940
+ sr_pb2.TaskUnmountDirectoryRequest(
2941
+ task_id=task_id,
2942
+ path=posix_path.as_posix().encode("utf8"),
2943
+ container_id=self._container_id,
2944
+ )
2945
+ )
2946
+
2947
+ async def snapshot_directory(
2948
+ self,
2949
+ path: PurePosixPath | str,
2950
+ *,
2951
+ timeout: int = 55,
2952
+ ttl: int | None = 30 * 24 * 3600,
2953
+ _experimental_encryption_key: bytes | None = None,
2954
+ ) -> _Image:
2955
+ """Snapshot a directory in this Sidecar container, creating a new Image with its content.
2956
+
2957
+ `timeout` If the snapshot does not return within that window, the call is cancelled
2958
+ and `modal.exception.TimeoutError` is raised.
2959
+
2960
+ `ttl` The resulting Image is retained for `ttl` seconds (default: 30 days).
2961
+ Pass `ttl=None` to retain the Image indefinitely.
2962
+
2963
+ The returned Image can be used anywhere an Image is accepted, including
2964
+ as a mount or as the base filesystem for another container.
2965
+
2966
+ Args:
2967
+ path: Absolute path of the directory inside the Sidecar container to snapshot.
2968
+
2969
+ Returns:
2970
+ An `Image` containing the directory contents.
2971
+
2972
+ Examples:
2973
+ ```py notest
2974
+ workspace_snapshot = sidecar_1.snapshot_directory("/workspace")
2975
+
2976
+ # You can later mount this snapshot in another Sidecar:
2977
+ sidecar_2.mount_image("/workspace", workspace_snapshot)
2978
+ sidecar_2.filesystem.list_files("/workspace")
2979
+ ```
2980
+ """
2981
+ wire_ttl_seconds = _ttl_to_wire_ttl(ttl)
2982
+ posix_path = PurePosixPath(path)
2983
+ if not posix_path.is_absolute():
2984
+ raise InvalidError(f"Snapshot path must be absolute; got: {posix_path}")
2985
+
2986
+ task_id, command_router_client = await self._get_command_router()
2987
+ response = await command_router_client.snapshot_directory(
2988
+ sr_pb2.TaskSnapshotDirectoryRequest(
2989
+ task_id=task_id,
2990
+ path=posix_path.as_posix().encode("utf8"),
2991
+ snapshot_id=str(uuid.uuid4()),
2992
+ ttl_seconds=wire_ttl_seconds,
2993
+ customer_supplied_encryption_key=_validate_experimental_encryption_key(_experimental_encryption_key),
2994
+ container_id=self._container_id,
2995
+ ),
2996
+ timeout=float(timeout),
2997
+ )
2998
+ return _Image._new_hydrated(response.image_id, self._sandbox._client, None)
2999
+
2870
3000
  async def wait(self, raise_on_termination: bool = True) -> None:
2871
3001
  if self._result is not None and self._result.status != api_pb2.GenericResult.GENERIC_STATUS_UNSPECIFIED:
2872
3002
  if self._result.status == api_pb2.GenericResult.GENERIC_STATUS_TERMINATED and raise_on_termination:
@@ -50,6 +50,7 @@ def _ttl_to_wire_ttl(ttl: typing.Optional[int]) -> int:
50
50
  ...
51
51
 
52
52
  def _validate_experimental_encryption_key(key: typing.Optional[bytes]) -> typing.Optional[bytes]: ...
53
+ def _image_id_for_mount(image: modal._image._Image, method_name: str) -> str: ...
53
54
 
54
55
  class SandboxVersion(enum.Enum):
55
56
  V1 = 1
@@ -1171,6 +1172,89 @@ class _SidecarContainer:
1171
1172
  """Namespace for Sandbox filesystem APIs."""
1172
1173
  ...
1173
1174
 
1175
+ async def mount_image(
1176
+ self,
1177
+ path: typing.Union[pathlib.PurePosixPath, str],
1178
+ image: modal._image._Image,
1179
+ *,
1180
+ _experimental_encryption_key: typing.Optional[bytes] = None,
1181
+ ) -> None:
1182
+ """Mount an Image at a specified path in this Sidecar container.
1183
+
1184
+ `path` should be a directory that is **not** the root path (`/`). If the path doesn't exist,
1185
+ it will be created. If it exists and contains data, the previous directory will be replaced
1186
+ by the mount.
1187
+
1188
+ The `image` argument supports any Image that has an object ID, including:
1189
+ - Images built using `image.build()`
1190
+ - Images referenced by ID, e.g. `Image.from_id(...)`
1191
+ - Filesystem/directory snapshots, e.g. created by `.snapshot_directory()` or `.snapshot_filesystem()`
1192
+ - Empty images created with `Image.from_scratch()`
1193
+
1194
+ Args:
1195
+ path: Absolute mount point directory inside the Sidecar container (not `/`).
1196
+ image: Image to mount at `path` (must be built, referenced by ID, or snapshot-based as described above).
1197
+
1198
+ Examples:
1199
+ ```py notest
1200
+ sidecar_1.mount_image("/workspace", modal.Image.from_scratch())
1201
+ workspace_snapshot = sidecar_1.snapshot_directory("/workspace")
1202
+
1203
+ # You can later mount this snapshot in another Sidecar:
1204
+ sidecar_2.mount_image("/workspace", workspace_snapshot)
1205
+ sidecar_2.filesystem.list_files("/workspace")
1206
+ ```
1207
+ """
1208
+ ...
1209
+
1210
+ async def unmount_image(self, path: typing.Union[pathlib.PurePosixPath, str]) -> None:
1211
+ """Unmount a previously mounted Image from this Sidecar container.
1212
+
1213
+ `path` must be the exact mount point that was passed to `.mount_image()`.
1214
+ After unmounting, the underlying Sidecar filesystem at that path becomes
1215
+ visible again.
1216
+
1217
+ Args:
1218
+ path: Absolute mount point directory to unmount.
1219
+ """
1220
+ ...
1221
+
1222
+ async def snapshot_directory(
1223
+ self,
1224
+ path: typing.Union[pathlib.PurePosixPath, str],
1225
+ *,
1226
+ timeout: int = 55,
1227
+ ttl: typing.Optional[int] = 2592000,
1228
+ _experimental_encryption_key: typing.Optional[bytes] = None,
1229
+ ) -> modal._image._Image:
1230
+ """Snapshot a directory in this Sidecar container, creating a new Image with its content.
1231
+
1232
+ `timeout` If the snapshot does not return within that window, the call is cancelled
1233
+ and `modal.exception.TimeoutError` is raised.
1234
+
1235
+ `ttl` The resulting Image is retained for `ttl` seconds (default: 30 days).
1236
+ Pass `ttl=None` to retain the Image indefinitely.
1237
+
1238
+ The returned Image can be used anywhere an Image is accepted, including
1239
+ as a mount or as the base filesystem for another container.
1240
+
1241
+ Args:
1242
+ path: Absolute path of the directory inside the Sidecar container to snapshot.
1243
+
1244
+ Returns:
1245
+ An `Image` containing the directory contents.
1246
+
1247
+ Examples:
1248
+ ```py notest
1249
+ workspace_snapshot = sidecar_1.snapshot_directory("/workspace")
1250
+
1251
+ # You can later mount this snapshot in another Sidecar:
1252
+ sidecar_2.mount_image("/workspace", workspace_snapshot)
1253
+ sidecar_2.filesystem.list_files("/workspace")
1254
+ ```
1255
+ """
1256
+ ...
1257
+
1174
1258
  async def wait(self, raise_on_termination: bool = True) -> None: ...
1175
1259
  async def poll(self) -> typing.Optional[int]: ...
1176
1260
  @typing.overload
@@ -1420,6 +1504,185 @@ class SidecarContainer:
1420
1504
  """Namespace for Sandbox filesystem APIs."""
1421
1505
  ...
1422
1506
 
1507
+ class __mount_image_spec(typing_extensions.Protocol):
1508
+ def __call__(
1509
+ self,
1510
+ /,
1511
+ path: typing.Union[pathlib.PurePosixPath, str],
1512
+ image: modal.image.Image,
1513
+ *,
1514
+ _experimental_encryption_key: typing.Optional[bytes] = None,
1515
+ ) -> None:
1516
+ """Mount an Image at a specified path in this Sidecar container.
1517
+
1518
+ `path` should be a directory that is **not** the root path (`/`). If the path doesn't exist,
1519
+ it will be created. If it exists and contains data, the previous directory will be replaced
1520
+ by the mount.
1521
+
1522
+ The `image` argument supports any Image that has an object ID, including:
1523
+ - Images built using `image.build()`
1524
+ - Images referenced by ID, e.g. `Image.from_id(...)`
1525
+ - Filesystem/directory snapshots, e.g. created by `.snapshot_directory()` or `.snapshot_filesystem()`
1526
+ - Empty images created with `Image.from_scratch()`
1527
+
1528
+ Args:
1529
+ path: Absolute mount point directory inside the Sidecar container (not `/`).
1530
+ image: Image to mount at `path` (must be built, referenced by ID, or snapshot-based as described above).
1531
+
1532
+ Examples:
1533
+ ```py notest
1534
+ sidecar_1.mount_image("/workspace", modal.Image.from_scratch())
1535
+ workspace_snapshot = sidecar_1.snapshot_directory("/workspace")
1536
+
1537
+ # You can later mount this snapshot in another Sidecar:
1538
+ sidecar_2.mount_image("/workspace", workspace_snapshot)
1539
+ sidecar_2.filesystem.list_files("/workspace")
1540
+ ```
1541
+ """
1542
+ ...
1543
+
1544
+ async def aio(
1545
+ self,
1546
+ /,
1547
+ path: typing.Union[pathlib.PurePosixPath, str],
1548
+ image: modal.image.Image,
1549
+ *,
1550
+ _experimental_encryption_key: typing.Optional[bytes] = None,
1551
+ ) -> None:
1552
+ """Mount an Image at a specified path in this Sidecar container.
1553
+
1554
+ `path` should be a directory that is **not** the root path (`/`). If the path doesn't exist,
1555
+ it will be created. If it exists and contains data, the previous directory will be replaced
1556
+ by the mount.
1557
+
1558
+ The `image` argument supports any Image that has an object ID, including:
1559
+ - Images built using `image.build()`
1560
+ - Images referenced by ID, e.g. `Image.from_id(...)`
1561
+ - Filesystem/directory snapshots, e.g. created by `.snapshot_directory()` or `.snapshot_filesystem()`
1562
+ - Empty images created with `Image.from_scratch()`
1563
+
1564
+ Args:
1565
+ path: Absolute mount point directory inside the Sidecar container (not `/`).
1566
+ image: Image to mount at `path` (must be built, referenced by ID, or snapshot-based as described above).
1567
+
1568
+ Examples:
1569
+ ```py notest
1570
+ sidecar_1.mount_image("/workspace", modal.Image.from_scratch())
1571
+ workspace_snapshot = sidecar_1.snapshot_directory("/workspace")
1572
+
1573
+ # You can later mount this snapshot in another Sidecar:
1574
+ sidecar_2.mount_image("/workspace", workspace_snapshot)
1575
+ sidecar_2.filesystem.list_files("/workspace")
1576
+ ```
1577
+ """
1578
+ ...
1579
+
1580
+ mount_image: __mount_image_spec
1581
+
1582
+ class __unmount_image_spec(typing_extensions.Protocol):
1583
+ def __call__(self, /, path: typing.Union[pathlib.PurePosixPath, str]) -> None:
1584
+ """Unmount a previously mounted Image from this Sidecar container.
1585
+
1586
+ `path` must be the exact mount point that was passed to `.mount_image()`.
1587
+ After unmounting, the underlying Sidecar filesystem at that path becomes
1588
+ visible again.
1589
+
1590
+ Args:
1591
+ path: Absolute mount point directory to unmount.
1592
+ """
1593
+ ...
1594
+
1595
+ async def aio(self, /, path: typing.Union[pathlib.PurePosixPath, str]) -> None:
1596
+ """Unmount a previously mounted Image from this Sidecar container.
1597
+
1598
+ `path` must be the exact mount point that was passed to `.mount_image()`.
1599
+ After unmounting, the underlying Sidecar filesystem at that path becomes
1600
+ visible again.
1601
+
1602
+ Args:
1603
+ path: Absolute mount point directory to unmount.
1604
+ """
1605
+ ...
1606
+
1607
+ unmount_image: __unmount_image_spec
1608
+
1609
+ class __snapshot_directory_spec(typing_extensions.Protocol):
1610
+ def __call__(
1611
+ self,
1612
+ /,
1613
+ path: typing.Union[pathlib.PurePosixPath, str],
1614
+ *,
1615
+ timeout: int = 55,
1616
+ ttl: typing.Optional[int] = 2592000,
1617
+ _experimental_encryption_key: typing.Optional[bytes] = None,
1618
+ ) -> modal.image.Image:
1619
+ """Snapshot a directory in this Sidecar container, creating a new Image with its content.
1620
+
1621
+ `timeout` If the snapshot does not return within that window, the call is cancelled
1622
+ and `modal.exception.TimeoutError` is raised.
1623
+
1624
+ `ttl` The resulting Image is retained for `ttl` seconds (default: 30 days).
1625
+ Pass `ttl=None` to retain the Image indefinitely.
1626
+
1627
+ The returned Image can be used anywhere an Image is accepted, including
1628
+ as a mount or as the base filesystem for another container.
1629
+
1630
+ Args:
1631
+ path: Absolute path of the directory inside the Sidecar container to snapshot.
1632
+
1633
+ Returns:
1634
+ An `Image` containing the directory contents.
1635
+
1636
+ Examples:
1637
+ ```py notest
1638
+ workspace_snapshot = sidecar_1.snapshot_directory("/workspace")
1639
+
1640
+ # You can later mount this snapshot in another Sidecar:
1641
+ sidecar_2.mount_image("/workspace", workspace_snapshot)
1642
+ sidecar_2.filesystem.list_files("/workspace")
1643
+ ```
1644
+ """
1645
+ ...
1646
+
1647
+ async def aio(
1648
+ self,
1649
+ /,
1650
+ path: typing.Union[pathlib.PurePosixPath, str],
1651
+ *,
1652
+ timeout: int = 55,
1653
+ ttl: typing.Optional[int] = 2592000,
1654
+ _experimental_encryption_key: typing.Optional[bytes] = None,
1655
+ ) -> modal.image.Image:
1656
+ """Snapshot a directory in this Sidecar container, creating a new Image with its content.
1657
+
1658
+ `timeout` If the snapshot does not return within that window, the call is cancelled
1659
+ and `modal.exception.TimeoutError` is raised.
1660
+
1661
+ `ttl` The resulting Image is retained for `ttl` seconds (default: 30 days).
1662
+ Pass `ttl=None` to retain the Image indefinitely.
1663
+
1664
+ The returned Image can be used anywhere an Image is accepted, including
1665
+ as a mount or as the base filesystem for another container.
1666
+
1667
+ Args:
1668
+ path: Absolute path of the directory inside the Sidecar container to snapshot.
1669
+
1670
+ Returns:
1671
+ An `Image` containing the directory contents.
1672
+
1673
+ Examples:
1674
+ ```py notest
1675
+ workspace_snapshot = sidecar_1.snapshot_directory("/workspace")
1676
+
1677
+ # You can later mount this snapshot in another Sidecar:
1678
+ sidecar_2.mount_image("/workspace", workspace_snapshot)
1679
+ sidecar_2.filesystem.list_files("/workspace")
1680
+ ```
1681
+ """
1682
+ ...
1683
+
1684
+ snapshot_directory: __snapshot_directory_spec
1685
+
1423
1686
  class __wait_spec(typing_extensions.Protocol):
1424
1687
  def __call__(self, /, raise_on_termination: bool = True) -> None: ...
1425
1688
  async def aio(self, /, raise_on_termination: bool = True) -> None: ...
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.5.6.dev9
3
+ Version: 1.5.6.dev10
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License-Expression: Apache-2.0
@@ -1,4 +1,4 @@
1
1
  # Copyright Modal Labs 2026
2
2
  """Supplies the current version of the modal client library."""
3
3
 
4
- __version__ = "1.5.6.dev9"
4
+ __version__ = "1.5.6.dev10"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes