modal 1.5.6.dev2__tar.gz → 1.5.6.dev4__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.dev2 → modal-1.5.6.dev4}/PKG-INFO +1 -1
  2. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_runtime/gpu_memory_snapshot.py +3 -34
  3. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_runtime/task_lifecycle_manager.py +28 -16
  4. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_runtime/task_lifecycle_manager.pyi +5 -0
  5. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/client.pyi +2 -2
  6. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/config.py +2 -0
  7. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/functions.pyi +6 -6
  8. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/sandbox.py +35 -0
  9. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/sandbox.pyi +66 -0
  10. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal.egg-info/PKG-INFO +1 -1
  11. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal_proto/api_grpc.py +32 -0
  12. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal_proto/api_pb2.py +865 -805
  13. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal_proto/api_pb2.pyi +124 -1
  14. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal_proto/api_pb2_grpc.py +67 -1
  15. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal_proto/api_pb2_grpc.pyi +23 -3
  16. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal_proto/modal_api_grpc.py +2 -0
  17. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal_version/__init__.py +1 -1
  18. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/pyproject.toml +4 -8
  19. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/LICENSE +0 -0
  20. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/README.md +0 -0
  21. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/__init__.py +0 -0
  22. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/__main__.py +0 -0
  23. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_billing.py +0 -0
  24. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_clustered_functions.py +0 -0
  25. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_clustered_functions.pyi +0 -0
  26. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_container_entrypoint.py +0 -0
  27. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_environments.py +0 -0
  28. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_function_variants.py +0 -0
  29. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_functions.py +0 -0
  30. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_grpc_client.py +0 -0
  31. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_image.py +0 -0
  32. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_ipython.py +0 -0
  33. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_load_context.py +0 -0
  34. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_location.py +0 -0
  35. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_logs.py +0 -0
  36. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_logs_manager.py +0 -0
  37. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_logs_manager.pyi +0 -0
  38. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_object.py +0 -0
  39. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_output/__init__.py +0 -0
  40. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_output/manager.py +0 -0
  41. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_output/pty.py +0 -0
  42. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_output/rich.py +0 -0
  43. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_output/status.py +0 -0
  44. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_partial_function.py +0 -0
  45. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_resolver.py +0 -0
  46. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_resources.py +0 -0
  47. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_runtime/__init__.py +0 -0
  48. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_runtime/asgi.py +0 -0
  49. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_runtime/container_io_manager.py +0 -0
  50. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_runtime/container_io_manager.pyi +0 -0
  51. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_runtime/execution_context.py +0 -0
  52. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_runtime/execution_context.pyi +0 -0
  53. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_runtime/telemetry.py +0 -0
  54. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_runtime/user_code_event_loop.py +0 -0
  55. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_runtime/user_code_imports.py +0 -0
  56. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_serialization.py +0 -0
  57. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_server.py +0 -0
  58. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_supports_logs.py +0 -0
  59. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_traceback.py +0 -0
  60. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_tunnel.py +0 -0
  61. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_tunnel.pyi +0 -0
  62. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_type_manager.py +0 -0
  63. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_utils/__init__.py +0 -0
  64. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_utils/app_utils.py +0 -0
  65. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_utils/async_utils.py +0 -0
  66. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_utils/auth_token_manager.py +0 -0
  67. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_utils/blob_utils.py +0 -0
  68. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_utils/browser_utils.py +0 -0
  69. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_utils/bytes_io_segment_payload.py +0 -0
  70. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_utils/curl_utils.py +0 -0
  71. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_utils/deprecation.py +0 -0
  72. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_utils/display_utils.py +0 -0
  73. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_utils/docker_utils.py +0 -0
  74. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_utils/function_utils.py +0 -0
  75. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_utils/git_utils.py +0 -0
  76. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_utils/grpc_testing.py +0 -0
  77. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_utils/grpc_utils.py +0 -0
  78. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_utils/hash_utils.py +0 -0
  79. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_utils/http_utils.py +0 -0
  80. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_utils/jwt_utils.py +0 -0
  81. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_utils/logger.py +0 -0
  82. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_utils/mount_utils.py +0 -0
  83. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_utils/name_utils.py +0 -0
  84. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_utils/package_utils.py +0 -0
  85. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_utils/pattern_utils.py +0 -0
  86. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_utils/proxy_support.py +0 -0
  87. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_utils/rand_pb_testing.py +0 -0
  88. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_utils/sandbox_fs_utils.py +0 -0
  89. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_utils/shell_utils.py +0 -0
  90. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_utils/task_command_router_client.py +0 -0
  91. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_utils/time_utils.py +0 -0
  92. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_vendor/__init__.py +0 -0
  93. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_vendor/a2wsgi_wsgi.py +0 -0
  94. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_vendor/cloudpickle.py +0 -0
  95. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_vendor/tblib.py +0 -0
  96. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_vendor/version.py +0 -0
  97. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_watcher.py +0 -0
  98. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/_workspace.py +0 -0
  99. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/app.py +0 -0
  100. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/app.pyi +0 -0
  101. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/billing.py +0 -0
  102. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/billing.pyi +0 -0
  103. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/builder/2023.12.312.txt +0 -0
  104. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/builder/2023.12.txt +0 -0
  105. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/builder/2024.04.txt +0 -0
  106. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/builder/2024.10.txt +0 -0
  107. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/builder/2025.06.txt +0 -0
  108. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/builder/PREVIEW.txt +0 -0
  109. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/builder/README.md +0 -0
  110. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/builder/base-images.json +0 -0
  111. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/call_graph.py +0 -0
  112. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/cli/__init__.py +0 -0
  113. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/cli/_download.py +0 -0
  114. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/cli/_help.py +0 -0
  115. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/cli/_traceback.py +0 -0
  116. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/cli/app.py +0 -0
  117. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/cli/billing.py +0 -0
  118. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/cli/bootstrap.py +0 -0
  119. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/cli/changelog.py +0 -0
  120. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/cli/cluster.py +0 -0
  121. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/cli/config.py +0 -0
  122. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/cli/container.py +0 -0
  123. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/cli/curl.py +0 -0
  124. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/cli/dashboard.py +0 -0
  125. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/cli/dict.py +0 -0
  126. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/cli/endpoint.py +0 -0
  127. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/cli/entry_point.py +0 -0
  128. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/cli/environment.py +0 -0
  129. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/cli/image.py +0 -0
  130. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/cli/import_refs.py +0 -0
  131. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/cli/launch.py +0 -0
  132. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/cli/logo.py +0 -0
  133. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/cli/network_file_system.py +0 -0
  134. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/cli/profile.py +0 -0
  135. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/cli/programs/__init__.py +0 -0
  136. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/cli/programs/run_jupyter.py +0 -0
  137. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/cli/programs/vscode.py +0 -0
  138. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/cli/queues.py +0 -0
  139. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/cli/run.py +0 -0
  140. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/cli/secret.py +0 -0
  141. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/cli/selector.py +0 -0
  142. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/cli/shell.py +0 -0
  143. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/cli/skills.py +0 -0
  144. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/cli/token.py +0 -0
  145. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/cli/utils.py +0 -0
  146. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/cli/volume.py +0 -0
  147. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/cli/workspace.py +0 -0
  148. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/client.py +0 -0
  149. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/cloud_bucket_mount.py +0 -0
  150. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/cloud_bucket_mount.pyi +0 -0
  151. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/cls.py +0 -0
  152. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/cls.pyi +0 -0
  153. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/container_process.py +0 -0
  154. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/container_process.pyi +0 -0
  155. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/dict.py +0 -0
  156. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/dict.pyi +0 -0
  157. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/environments.py +0 -0
  158. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/environments.pyi +0 -0
  159. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/exception.py +0 -0
  160. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/experimental/__init__.py +0 -0
  161. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/experimental/flash.py +0 -0
  162. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/experimental/flash.pyi +0 -0
  163. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/experimental/ipython.py +0 -0
  164. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/file_io.py +0 -0
  165. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/file_io.pyi +0 -0
  166. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/file_pattern_matcher.py +0 -0
  167. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/functions.py +0 -0
  168. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/image.py +0 -0
  169. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/image.pyi +0 -0
  170. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/io_streams.py +0 -0
  171. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/io_streams.pyi +0 -0
  172. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/mount.py +0 -0
  173. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/mount.pyi +0 -0
  174. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/network_file_system.py +0 -0
  175. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/network_file_system.pyi +0 -0
  176. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/object.py +0 -0
  177. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/object.pyi +0 -0
  178. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/output.py +0 -0
  179. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/parallel_map.py +0 -0
  180. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/parallel_map.pyi +0 -0
  181. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/partial_function.py +0 -0
  182. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/partial_function.pyi +0 -0
  183. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/proxy.py +0 -0
  184. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/proxy.pyi +0 -0
  185. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/py.typed +0 -0
  186. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/queue.py +0 -0
  187. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/queue.pyi +0 -0
  188. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/retries.py +0 -0
  189. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/runner.py +0 -0
  190. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/runner.pyi +0 -0
  191. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/running_app.py +0 -0
  192. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/sandbox_fs.py +0 -0
  193. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/sandbox_fs.pyi +0 -0
  194. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/schedule.py +0 -0
  195. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/scheduler_placement.py +0 -0
  196. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/secret.py +0 -0
  197. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/secret.pyi +0 -0
  198. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/server.py +0 -0
  199. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/server.pyi +0 -0
  200. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/serving.py +0 -0
  201. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/serving.pyi +0 -0
  202. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/skills/modal/SKILL.md +0 -0
  203. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/snapshot.py +0 -0
  204. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/snapshot.pyi +0 -0
  205. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/stream_type.py +0 -0
  206. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/token_flow.py +0 -0
  207. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/token_flow.pyi +0 -0
  208. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/types.py +0 -0
  209. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/volume.py +0 -0
  210. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/volume.pyi +0 -0
  211. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/workspace.py +0 -0
  212. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal/workspace.pyi +0 -0
  213. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal.egg-info/SOURCES.txt +0 -0
  214. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal.egg-info/dependency_links.txt +0 -0
  215. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal.egg-info/entry_points.txt +0 -0
  216. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal.egg-info/requires.txt +0 -0
  217. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal.egg-info/top_level.txt +0 -0
  218. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal_docs/__init__.py +0 -0
  219. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal_docs/gen_cli_docs.py +0 -0
  220. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal_docs/gen_cli_docs_main.py +0 -0
  221. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal_docs/gen_reference_docs.py +0 -0
  222. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal_docs/gen_reference_docs_main.py +0 -0
  223. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal_docs/mdmd/__init__.py +0 -0
  224. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal_docs/mdmd/mdmd.py +0 -0
  225. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal_docs/mdmd/signatures.py +0 -0
  226. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal_docs/mdmd/types.py +0 -0
  227. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal_docs/reference_intro.md +0 -0
  228. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal_proto/__init__.py +0 -0
  229. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal_proto/py.typed +0 -0
  230. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal_proto/task_command_router_grpc.py +0 -0
  231. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal_proto/task_command_router_pb2.py +0 -0
  232. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal_proto/task_command_router_pb2.pyi +0 -0
  233. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal_proto/task_command_router_pb2_grpc.py +0 -0
  234. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal_proto/task_command_router_pb2_grpc.pyi +0 -0
  235. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/modal_version/__main__.py +0 -0
  236. {modal-1.5.6.dev2 → modal-1.5.6.dev4}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.5.6.dev2
3
+ Version: 1.5.6.dev4
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License-Expression: Apache-2.0
@@ -22,15 +22,9 @@ CUDA_CHECKPOINT_PATH: str = config.get("cuda_checkpoint_path")
22
22
  # stay in sync with `GPU_SNAPSHOT_RESTORE_FAILED_EXIT_CODE` in runner.rs.
23
23
  SNAPSHOT_RESTORE_FAILED_EXIT_CODE: int = 222
24
24
 
25
- # Maximum total duration for each individual `cuda-checkpoint` invocation.
26
- CUDA_CHECKPOINT_TIMEOUT: float = 3 * 60.0
27
-
28
25
  # Number of retries for each individual `cuda-checkpoint --toggle` invocation.
29
26
  CUDA_CHECKPOINT_TOGGLE_NUM_RETRIES: int = 3
30
27
 
31
- # Maximum total duration for an entire toggle operation.
32
- CUDA_CHECKPOINT_TOGGLE_TIMEOUT: float = CUDA_CHECKPOINT_TOGGLE_NUM_RETRIES * CUDA_CHECKPOINT_TIMEOUT
33
-
34
28
 
35
29
  class CudaCheckpointState(Enum):
36
30
  """State representation from the CUDA API [1].
@@ -63,14 +57,11 @@ class CudaCheckpointProcess:
63
57
  """
64
58
  logger.debug(f"PID: {self.pid} Toggling CUDA checkpoint state to {target_state.value}")
65
59
 
66
- start_time = time.monotonic()
67
60
  retry_count = 0
68
61
  max_retries = CUDA_CHECKPOINT_TOGGLE_NUM_RETRIES
69
62
 
70
63
  attempts = 0
71
- while self._should_continue_toggle(
72
- target_state, start_time, refresh=not (skip_first_refresh and attempts == 0)
73
- ):
64
+ while self._should_continue_toggle(target_state, refresh=not (skip_first_refresh and attempts == 0)):
74
65
  attempts += 1
75
66
  try:
76
67
  self._execute_toggle_command()
@@ -89,10 +80,8 @@ class CudaCheckpointProcess:
89
80
 
90
81
  logger.debug(f"PID: {self.pid} Target state {target_state.value} reached")
91
82
 
92
- def _should_continue_toggle(
93
- self, target_state: CudaCheckpointState, start_time: float, refresh: bool = True
94
- ) -> bool:
95
- """Check if toggle operation should continue based on current state and timeout."""
83
+ def _should_continue_toggle(self, target_state: CudaCheckpointState, refresh: bool = True) -> bool:
84
+ """Check if toggle operation should continue based on current state."""
96
85
  if refresh:
97
86
  self.refresh_state()
98
87
 
@@ -102,13 +91,6 @@ class CudaCheckpointProcess:
102
91
  if self.state == CudaCheckpointState.FAILED:
103
92
  raise CudaCheckpointException(f"PID: {self.pid} CUDA process state is {self.state}")
104
93
 
105
- elapsed = time.monotonic() - start_time
106
- if elapsed >= CUDA_CHECKPOINT_TOGGLE_TIMEOUT:
107
- raise CudaCheckpointException(
108
- f"PID: {self.pid} Timeout after {elapsed:.2f}s waiting for state {target_state.value}. "
109
- f"Current state: {self.state}"
110
- )
111
-
112
94
  return True
113
95
 
114
96
  def _execute_toggle_command(self) -> None:
@@ -119,17 +101,12 @@ class CudaCheckpointProcess:
119
101
  check=True,
120
102
  capture_output=True,
121
103
  text=True,
122
- timeout=CUDA_CHECKPOINT_TIMEOUT,
123
104
  )
124
105
  logger.debug(f"PID: {self.pid} Successfully toggled CUDA checkpoint state")
125
106
  except subprocess.CalledProcessError as e:
126
107
  error_msg = f"PID: {self.pid} Failed to toggle CUDA checkpoint state: {e.stderr}"
127
108
  logger.debug(error_msg)
128
109
  raise CudaCheckpointException(error_msg)
129
- except subprocess.TimeoutExpired:
130
- error_msg = f"PID: {self.pid} Toggle command timed out"
131
- logger.debug(error_msg)
132
- raise CudaCheckpointException(error_msg)
133
110
 
134
111
  def refresh_state(self) -> None:
135
112
  """Refreshes the current CUDA checkpoint state for this process."""
@@ -139,7 +116,6 @@ class CudaCheckpointProcess:
139
116
  check=True,
140
117
  capture_output=True,
141
118
  text=True,
142
- timeout=CUDA_CHECKPOINT_TIMEOUT,
143
119
  )
144
120
 
145
121
  state_str = result.stdout.strip().lower()
@@ -149,10 +125,6 @@ class CudaCheckpointProcess:
149
125
  error_msg = f"PID: {self.pid} Failed to get CUDA checkpoint state: {e.stderr}"
150
126
  logger.debug(error_msg)
151
127
  raise CudaCheckpointException(error_msg)
152
- except subprocess.TimeoutExpired:
153
- error_msg = f"PID: {self.pid} Get state command timed out"
154
- logger.debug(error_msg)
155
- raise CudaCheckpointException(error_msg)
156
128
 
157
129
 
158
130
  class CudaCheckpointSession:
@@ -208,7 +180,6 @@ class CudaCheckpointSession:
208
180
  [CUDA_CHECKPOINT_PATH, "--get-state", "--pid", str(pid)],
209
181
  capture_output=True,
210
182
  text=True,
211
- timeout=CUDA_CHECKPOINT_TIMEOUT,
212
183
  )
213
184
 
214
185
  # If the command succeeds (return code 0), this PID has a CUDA session
@@ -220,8 +191,6 @@ class CudaCheckpointSession:
220
191
  except subprocess.CalledProcessError:
221
192
  # Command failed, which is expected for PIDs without CUDA sessions
222
193
  pass
223
- except subprocess.TimeoutExpired:
224
- logger.debug(f"Timeout checking CUDA state for PID {pid}")
225
194
  except Exception as e:
226
195
  logger.debug(f"Error checking PID {pid}: {e}")
227
196
 
@@ -143,6 +143,12 @@ class _TaskLifecycleManager:
143
143
  else:
144
144
  logger.debug(f"modal.Volume background commit success for {volume_id}.")
145
145
 
146
+ @property
147
+ def _gpu_snapshot_enabled(self) -> bool:
148
+ return bool(
149
+ self.function_def._experimental_enable_gpu_snapshot and self.function_def.resources.gpu_config.gpu_type
150
+ )
151
+
146
152
  async def memory_restore(self) -> None:
147
153
  # Busy-wait for restore. `/__modal/restore-state.json` is created
148
154
  # by the worker process with updates to the container config.
@@ -177,18 +183,21 @@ class _TaskLifecycleManager:
177
183
  config.override_locally(key, value)
178
184
 
179
185
  # Restore GPU memory.
180
- if self.function_def._experimental_enable_gpu_snapshot and self.function_def.resources.gpu_config.gpu_type:
181
- logger.debug("GPU memory snapshot enabled. Attempting to restore GPU memory.")
182
-
183
- try:
184
- if self._cuda_checkpoint_session is None:
185
- raise gpu_memory_snapshot.CudaCheckpointException("CudaCheckpointSession not found")
186
- self._cuda_checkpoint_session.restore()
187
- except gpu_memory_snapshot.CudaCheckpointException as exc:
188
- logger.warning(f"GPU memory snapshot restore failed; retrying task without snapshot. Error: {exc}")
189
- sys.stderr.flush()
190
- # Exit with a sentinel code that the runtime will use to retry the task without a snapshot.
191
- os._exit(gpu_memory_snapshot.SNAPSHOT_RESTORE_FAILED_EXIT_CODE)
186
+ if self._gpu_snapshot_enabled:
187
+ if config.get("runtime_managed_cuda_checkpoint"):
188
+ logger.debug("GPU memory restore is managed by the container runtime.")
189
+ else:
190
+ logger.debug("GPU memory snapshot enabled. Attempting to restore GPU memory.")
191
+
192
+ try:
193
+ if self._cuda_checkpoint_session is None:
194
+ raise gpu_memory_snapshot.CudaCheckpointException("CudaCheckpointSession not found")
195
+ self._cuda_checkpoint_session.restore()
196
+ except gpu_memory_snapshot.CudaCheckpointException as exc:
197
+ logger.warning(f"GPU memory snapshot restore failed; retrying task without snapshot. Error: {exc}")
198
+ sys.stderr.flush()
199
+ # Exit with a sentinel code that the runtime will use to retry the task without a snapshot.
200
+ os._exit(gpu_memory_snapshot.SNAPSHOT_RESTORE_FAILED_EXIT_CODE)
192
201
 
193
202
  self._client = await _Client.from_env()
194
203
 
@@ -199,11 +208,14 @@ class _TaskLifecycleManager:
199
208
  else:
200
209
  raise ValueError("No checkpoint ID provided for memory snapshot")
201
210
 
202
- if self.function_def._experimental_enable_gpu_snapshot and self.function_def.resources.gpu_config.gpu_type:
203
- logger.debug("GPU memory snapshot enabled. Attempting to snapshot GPU memory.")
211
+ if self._gpu_snapshot_enabled:
212
+ if config.get("runtime_managed_cuda_checkpoint"):
213
+ logger.debug("GPU memory snapshot is managed by the container runtime.")
214
+ else:
215
+ logger.debug("GPU memory snapshot enabled. Attempting to snapshot GPU memory.")
204
216
 
205
- self._cuda_checkpoint_session = gpu_memory_snapshot.CudaCheckpointSession()
206
- self._cuda_checkpoint_session.checkpoint()
217
+ self._cuda_checkpoint_session = gpu_memory_snapshot.CudaCheckpointSession()
218
+ self._cuda_checkpoint_session.checkpoint()
207
219
 
208
220
  await self._client.stub.ContainerCheckpoint(
209
221
  api_pb2.ContainerCheckpointRequest(checkpoint_id=self.checkpoint_id)
@@ -54,6 +54,8 @@ class _TaskLifecycleManager:
54
54
  """
55
55
  ...
56
56
 
57
+ @property
58
+ def _gpu_snapshot_enabled(self) -> bool: ...
57
59
  async def memory_restore(self) -> None: ...
58
60
  async def memory_snapshot(self) -> None:
59
61
  """Message server indicating that function is ready to be checkpointed."""
@@ -111,6 +113,9 @@ class TaskLifecycleManager:
111
113
 
112
114
  volume_commit: __volume_commit_spec
113
115
 
116
+ @property
117
+ def _gpu_snapshot_enabled(self) -> bool: ...
118
+
114
119
  class __memory_restore_spec(typing_extensions.Protocol):
115
120
  def __call__(self, /) -> None: ...
116
121
  async def aio(self, /) -> None: ...
@@ -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.dev2",
80
+ version: str = "1.5.6.dev4",
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.dev2",
280
+ version: str = "1.5.6.dev4",
281
281
  *,
282
282
  oauth_credentials: typing.Optional[_OAuthCredentials] = None,
283
283
  ):
@@ -339,6 +339,8 @@ _SETTINGS = {
339
339
  "sandbox_v2": _Setting(None, transform=_to_boolean),
340
340
  "snapshot_debug": _Setting(False, transform=_to_boolean),
341
341
  "cuda_checkpoint_path": _Setting("/__modal/.bin/cuda-checkpoint"), # Used for snapshotting GPU memory.
342
+ # Used to indicate gVisor cuda-checkpoint automation.
343
+ "runtime_managed_cuda_checkpoint": _Setting(False, transform=_to_boolean),
342
344
  "build_validation": _Setting("error", transform=_check_value(["error", "warn", "ignore"])),
343
345
  # Payload format for function inputs/outputs: 'pickle' (default) or 'cbor'
344
346
  "payload_format": _Setting(
@@ -619,7 +619,7 @@ class Function(
619
619
 
620
620
  _call_generator: ___call_generator_spec
621
621
 
622
- class __remote_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER]):
622
+ class __remote_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
623
623
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER:
624
624
  """Calls the function remotely, executing it with the given arguments and returning the execution's result.
625
625
 
@@ -644,7 +644,7 @@ class Function(
644
644
  """
645
645
  ...
646
646
 
647
- remote: __remote_spec[modal._functions.P, modal._functions.ReturnType]
647
+ remote: __remote_spec[modal._functions.ReturnType, modal._functions.P]
648
648
 
649
649
  class __remote_gen_spec(typing_extensions.Protocol):
650
650
  def __call__(self, /, *args, **kwargs) -> typing.Generator[typing.Any, None, None]:
@@ -694,7 +694,7 @@ class Function(
694
694
  """
695
695
  ...
696
696
 
697
- class ___experimental_spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER]):
697
+ class ___experimental_spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
698
698
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]:
699
699
  """[Experimental] Calls the function with the given arguments, without waiting for the results.
700
700
 
@@ -727,7 +727,7 @@ class Function(
727
727
  """
728
728
  ...
729
729
 
730
- _experimental_spawn: ___experimental_spawn_spec[modal._functions.P, modal._functions.ReturnType]
730
+ _experimental_spawn: ___experimental_spawn_spec[modal._functions.ReturnType, modal._functions.P]
731
731
 
732
732
  class ___spawn_map_inner_spec(typing_extensions.Protocol[P_INNER]):
733
733
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> None: ...
@@ -735,7 +735,7 @@ class Function(
735
735
 
736
736
  _spawn_map_inner: ___spawn_map_inner_spec[modal._functions.P]
737
737
 
738
- class __spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER]):
738
+ class __spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
739
739
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]:
740
740
  """Calls the function with the given arguments, without waiting for the results.
741
741
 
@@ -768,7 +768,7 @@ class Function(
768
768
  """
769
769
  ...
770
770
 
771
- spawn: __spawn_spec[modal._functions.P, modal._functions.ReturnType]
771
+ spawn: __spawn_spec[modal._functions.ReturnType, modal._functions.P]
772
772
 
773
773
  def get_raw_f(self) -> collections.abc.Callable[..., typing.Any]:
774
774
  """Return the inner Python object wrapped by this Modal Function.
@@ -1577,6 +1577,15 @@ class _Sandbox(_Object, type_prefix="sb"):
1577
1577
  raise InvalidError("ttl is not supported with MODAL_USE_LEGACY_FILESYSTEM_SNAPSHOT")
1578
1578
  return await self._legacy_snapshot_filesystem(timeout)
1579
1579
 
1580
+ return await self._snapshot_filesystem(timeout, ttl=ttl)
1581
+
1582
+ async def _snapshot_filesystem(
1583
+ self,
1584
+ timeout: int,
1585
+ *,
1586
+ ttl: int | None,
1587
+ container_id: str = "",
1588
+ ) -> _Image:
1580
1589
  wire_ttl_seconds = _ttl_to_wire_ttl(ttl)
1581
1590
 
1582
1591
  task_id = await self._get_task_id()
@@ -1586,6 +1595,7 @@ class _Sandbox(_Object, type_prefix="sb"):
1586
1595
  task_id=task_id,
1587
1596
  snapshot_id=str(uuid.uuid4()),
1588
1597
  ttl_seconds=wire_ttl_seconds,
1598
+ container_id=container_id,
1589
1599
  )
1590
1600
  res = await command_router_client.snapshot_filesystem(req, timeout=float(timeout))
1591
1601
  return _Image._new_hydrated(res.image_id, self._client, None)
@@ -2755,6 +2765,31 @@ class _SidecarContainer:
2755
2765
  command_router_client = await self._sandbox._get_command_router_client(task_id)
2756
2766
  return task_id, command_router_client
2757
2767
 
2768
+ async def snapshot_filesystem(
2769
+ self,
2770
+ timeout: int = 55,
2771
+ *,
2772
+ ttl: int | None = 30 * 24 * 3600,
2773
+ ) -> _Image:
2774
+ """Snapshot this Sidecar container's filesystem.
2775
+
2776
+ Args:
2777
+ timeout:
2778
+ Maximum time in seconds to wait for the snapshot operation.
2779
+ ttl:
2780
+ The resulting Image is retained for `ttl` seconds (default: 30 days). Pass `ttl=None` to retain
2781
+ the image indefinitely.
2782
+
2783
+ Returns:
2784
+ An [`Image`](https://modal.com/docs/sdk/py/latest/Image) containing a snapshot of this Sidecar's
2785
+ filesystem.
2786
+ """
2787
+ return await self._sandbox._snapshot_filesystem(
2788
+ timeout,
2789
+ ttl=ttl,
2790
+ container_id=self._container_id,
2791
+ )
2792
+
2758
2793
  @typing.overload
2759
2794
  async def exec(
2760
2795
  self,
@@ -637,6 +637,9 @@ class _Sandbox(modal._object._Object):
637
637
  """
638
638
  ...
639
639
 
640
+ async def _snapshot_filesystem(
641
+ self, timeout: int, *, ttl: typing.Optional[int], container_id: str = ""
642
+ ) -> modal._image._Image: ...
640
643
  async def _legacy_snapshot_filesystem(self, timeout: int = 55) -> modal._image._Image: ...
641
644
  async def mount_image(
642
645
  self,
@@ -1111,6 +1114,24 @@ class _SidecarContainer:
1111
1114
  """Get task ID and command router client."""
1112
1115
  ...
1113
1116
 
1117
+ async def snapshot_filesystem(
1118
+ self, timeout: int = 55, *, ttl: typing.Optional[int] = 2592000
1119
+ ) -> modal._image._Image:
1120
+ """Snapshot this Sidecar container's filesystem.
1121
+
1122
+ Args:
1123
+ timeout:
1124
+ Maximum time in seconds to wait for the snapshot operation.
1125
+ ttl:
1126
+ The resulting Image is retained for `ttl` seconds (default: 30 days). Pass `ttl=None` to retain
1127
+ the image indefinitely.
1128
+
1129
+ Returns:
1130
+ An [`Image`](https://modal.com/docs/sdk/py/latest/Image) containing a snapshot of this Sidecar's
1131
+ filesystem.
1132
+ """
1133
+ ...
1134
+
1114
1135
  @typing.overload
1115
1136
  async def exec(
1116
1137
  self,
@@ -1289,6 +1310,41 @@ class SidecarContainer:
1289
1310
 
1290
1311
  _get_command_router: ___get_command_router_spec
1291
1312
 
1313
+ class __snapshot_filesystem_spec(typing_extensions.Protocol):
1314
+ def __call__(self, /, timeout: int = 55, *, ttl: typing.Optional[int] = 2592000) -> modal.image.Image:
1315
+ """Snapshot this Sidecar container's filesystem.
1316
+
1317
+ Args:
1318
+ timeout:
1319
+ Maximum time in seconds to wait for the snapshot operation.
1320
+ ttl:
1321
+ The resulting Image is retained for `ttl` seconds (default: 30 days). Pass `ttl=None` to retain
1322
+ the image indefinitely.
1323
+
1324
+ Returns:
1325
+ An [`Image`](https://modal.com/docs/sdk/py/latest/Image) containing a snapshot of this Sidecar's
1326
+ filesystem.
1327
+ """
1328
+ ...
1329
+
1330
+ async def aio(self, /, timeout: int = 55, *, ttl: typing.Optional[int] = 2592000) -> modal.image.Image:
1331
+ """Snapshot this Sidecar container's filesystem.
1332
+
1333
+ Args:
1334
+ timeout:
1335
+ Maximum time in seconds to wait for the snapshot operation.
1336
+ ttl:
1337
+ The resulting Image is retained for `ttl` seconds (default: 30 days). Pass `ttl=None` to retain
1338
+ the image indefinitely.
1339
+
1340
+ Returns:
1341
+ An [`Image`](https://modal.com/docs/sdk/py/latest/Image) containing a snapshot of this Sidecar's
1342
+ filesystem.
1343
+ """
1344
+ ...
1345
+
1346
+ snapshot_filesystem: __snapshot_filesystem_spec
1347
+
1292
1348
  class __exec_spec(typing_extensions.Protocol):
1293
1349
  @typing.overload
1294
1350
  def __call__(
@@ -2485,6 +2541,16 @@ class Sandbox(modal.object.Object):
2485
2541
 
2486
2542
  snapshot_filesystem: __snapshot_filesystem_spec
2487
2543
 
2544
+ class ___snapshot_filesystem_spec(typing_extensions.Protocol):
2545
+ def __call__(
2546
+ self, /, timeout: int, *, ttl: typing.Optional[int], container_id: str = ""
2547
+ ) -> modal.image.Image: ...
2548
+ async def aio(
2549
+ self, /, timeout: int, *, ttl: typing.Optional[int], container_id: str = ""
2550
+ ) -> modal.image.Image: ...
2551
+
2552
+ _snapshot_filesystem: ___snapshot_filesystem_spec
2553
+
2488
2554
  class ___legacy_snapshot_filesystem_spec(typing_extensions.Protocol):
2489
2555
  def __call__(self, /, timeout: int = 55) -> modal.image.Image: ...
2490
2556
  async def aio(self, /, timeout: int = 55) -> modal.image.Image: ...
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.5.6.dev2
3
+ Version: 1.5.6.dev4
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License-Expression: Apache-2.0
@@ -411,6 +411,10 @@ class ModalClientBase(abc.ABC):
411
411
  async def FunctionGet(self, stream: 'grpclib.server.Stream[modal_proto.api_pb2.FunctionGetRequest, modal_proto.api_pb2.FunctionGetResponse]') -> None:
412
412
  pass
413
413
 
414
+ @abc.abstractmethod
415
+ async def FunctionGetById(self, stream: 'grpclib.server.Stream[modal_proto.api_pb2.FunctionGetByIdRequest, modal_proto.api_pb2.FunctionGetByIdResponse]') -> None:
416
+ pass
417
+
414
418
  @abc.abstractmethod
415
419
  async def FunctionGetCallGraph(self, stream: 'grpclib.server.Stream[modal_proto.api_pb2.FunctionGetCallGraphRequest, modal_proto.api_pb2.FunctionGetCallGraphResponse]') -> None:
416
420
  pass
@@ -599,6 +603,10 @@ class ModalClientBase(abc.ABC):
599
603
  async def QueuePut(self, stream: 'grpclib.server.Stream[modal_proto.api_pb2.QueuePutRequest, google.protobuf.empty_pb2.Empty]') -> None:
600
604
  pass
601
605
 
606
+ @abc.abstractmethod
607
+ async def SandboxContainerCreateV2(self, stream: 'grpclib.server.Stream[modal_proto.api_pb2.SandboxContainerCreateV2Request, modal_proto.api_pb2.SandboxContainerCreateV2Response]') -> None:
608
+ pass
609
+
602
610
  @abc.abstractmethod
603
611
  async def SandboxCreate(self, stream: 'grpclib.server.Stream[modal_proto.api_pb2.SandboxCreateRequest, modal_proto.api_pb2.SandboxCreateResponse]') -> None:
604
612
  pass
@@ -1577,6 +1585,12 @@ class ModalClientBase(abc.ABC):
1577
1585
  modal_proto.api_pb2.FunctionGetRequest,
1578
1586
  modal_proto.api_pb2.FunctionGetResponse,
1579
1587
  ),
1588
+ '/modal.client.ModalClient/FunctionGetById': grpclib.const.Handler(
1589
+ self.FunctionGetById,
1590
+ grpclib.const.Cardinality.UNARY_UNARY,
1591
+ modal_proto.api_pb2.FunctionGetByIdRequest,
1592
+ modal_proto.api_pb2.FunctionGetByIdResponse,
1593
+ ),
1580
1594
  '/modal.client.ModalClient/FunctionGetCallGraph': grpclib.const.Handler(
1581
1595
  self.FunctionGetCallGraph,
1582
1596
  grpclib.const.Cardinality.UNARY_UNARY,
@@ -1859,6 +1873,12 @@ class ModalClientBase(abc.ABC):
1859
1873
  modal_proto.api_pb2.QueuePutRequest,
1860
1874
  google.protobuf.empty_pb2.Empty,
1861
1875
  ),
1876
+ '/modal.client.ModalClient/SandboxContainerCreateV2': grpclib.const.Handler(
1877
+ self.SandboxContainerCreateV2,
1878
+ grpclib.const.Cardinality.UNARY_UNARY,
1879
+ modal_proto.api_pb2.SandboxContainerCreateV2Request,
1880
+ modal_proto.api_pb2.SandboxContainerCreateV2Response,
1881
+ ),
1862
1882
  '/modal.client.ModalClient/SandboxCreate': grpclib.const.Handler(
1863
1883
  self.SandboxCreate,
1864
1884
  grpclib.const.Cardinality.UNARY_UNARY,
@@ -3035,6 +3055,12 @@ class ModalClientStub:
3035
3055
  modal_proto.api_pb2.FunctionGetRequest,
3036
3056
  modal_proto.api_pb2.FunctionGetResponse,
3037
3057
  )
3058
+ self.FunctionGetById = grpclib.client.UnaryUnaryMethod(
3059
+ channel,
3060
+ '/modal.client.ModalClient/FunctionGetById',
3061
+ modal_proto.api_pb2.FunctionGetByIdRequest,
3062
+ modal_proto.api_pb2.FunctionGetByIdResponse,
3063
+ )
3038
3064
  self.FunctionGetCallGraph = grpclib.client.UnaryUnaryMethod(
3039
3065
  channel,
3040
3066
  '/modal.client.ModalClient/FunctionGetCallGraph',
@@ -3317,6 +3343,12 @@ class ModalClientStub:
3317
3343
  modal_proto.api_pb2.QueuePutRequest,
3318
3344
  google.protobuf.empty_pb2.Empty,
3319
3345
  )
3346
+ self.SandboxContainerCreateV2 = grpclib.client.UnaryUnaryMethod(
3347
+ channel,
3348
+ '/modal.client.ModalClient/SandboxContainerCreateV2',
3349
+ modal_proto.api_pb2.SandboxContainerCreateV2Request,
3350
+ modal_proto.api_pb2.SandboxContainerCreateV2Response,
3351
+ )
3320
3352
  self.SandboxCreate = grpclib.client.UnaryUnaryMethod(
3321
3353
  channel,
3322
3354
  '/modal.client.ModalClient/SandboxCreate',