modal 1.2.5.dev7__tar.gz → 1.2.5.dev8__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 (202) hide show
  1. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/PKG-INFO +1 -1
  2. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_runtime/user_code_imports.py +95 -77
  3. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/client.pyi +2 -2
  4. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal.egg-info/PKG-INFO +1 -1
  5. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal_version/__init__.py +1 -1
  6. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/LICENSE +0 -0
  7. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/README.md +0 -0
  8. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/__init__.py +0 -0
  9. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/__main__.py +0 -0
  10. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_billing.py +0 -0
  11. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_clustered_functions.py +0 -0
  12. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_clustered_functions.pyi +0 -0
  13. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_container_entrypoint.py +0 -0
  14. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_functions.py +0 -0
  15. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_grpc_client.py +0 -0
  16. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_ipython.py +0 -0
  17. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_load_context.py +0 -0
  18. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_location.py +0 -0
  19. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_object.py +0 -0
  20. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_output.py +0 -0
  21. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_partial_function.py +0 -0
  22. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_pty.py +0 -0
  23. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_resolver.py +0 -0
  24. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_resources.py +0 -0
  25. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_runtime/__init__.py +0 -0
  26. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_runtime/asgi.py +0 -0
  27. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_runtime/container_io_manager.py +0 -0
  28. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_runtime/container_io_manager.pyi +0 -0
  29. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_runtime/execution_context.py +0 -0
  30. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_runtime/execution_context.pyi +0 -0
  31. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_runtime/gpu_memory_snapshot.py +0 -0
  32. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_runtime/telemetry.py +0 -0
  33. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_runtime/user_code_event_loop.py +0 -0
  34. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_serialization.py +0 -0
  35. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_traceback.py +0 -0
  36. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_tunnel.py +0 -0
  37. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_tunnel.pyi +0 -0
  38. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_type_manager.py +0 -0
  39. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_utils/__init__.py +0 -0
  40. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_utils/app_utils.py +0 -0
  41. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_utils/async_utils.py +0 -0
  42. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_utils/auth_token_manager.py +0 -0
  43. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_utils/blob_utils.py +0 -0
  44. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_utils/bytes_io_segment_payload.py +0 -0
  45. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_utils/deprecation.py +0 -0
  46. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_utils/docker_utils.py +0 -0
  47. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_utils/function_utils.py +0 -0
  48. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_utils/git_utils.py +0 -0
  49. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_utils/grpc_testing.py +0 -0
  50. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_utils/grpc_utils.py +0 -0
  51. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_utils/hash_utils.py +0 -0
  52. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_utils/http_utils.py +0 -0
  53. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_utils/jwt_utils.py +0 -0
  54. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_utils/logger.py +0 -0
  55. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_utils/mount_utils.py +0 -0
  56. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_utils/name_utils.py +0 -0
  57. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_utils/package_utils.py +0 -0
  58. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_utils/pattern_utils.py +0 -0
  59. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_utils/rand_pb_testing.py +0 -0
  60. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_utils/shell_utils.py +0 -0
  61. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_utils/task_command_router_client.py +0 -0
  62. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_utils/time_utils.py +0 -0
  63. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_vendor/__init__.py +0 -0
  64. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_vendor/a2wsgi_wsgi.py +0 -0
  65. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_vendor/cloudpickle.py +0 -0
  66. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_vendor/tblib.py +0 -0
  67. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/_watcher.py +0 -0
  68. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/app.py +0 -0
  69. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/app.pyi +0 -0
  70. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/billing.py +0 -0
  71. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/builder/2023.12.312.txt +0 -0
  72. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/builder/2023.12.txt +0 -0
  73. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/builder/2024.04.txt +0 -0
  74. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/builder/2024.10.txt +0 -0
  75. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/builder/2025.06.txt +0 -0
  76. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/builder/PREVIEW.txt +0 -0
  77. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/builder/README.md +0 -0
  78. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/builder/base-images.json +0 -0
  79. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/call_graph.py +0 -0
  80. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/cli/__init__.py +0 -0
  81. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/cli/_download.py +0 -0
  82. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/cli/_traceback.py +0 -0
  83. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/cli/app.py +0 -0
  84. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/cli/cluster.py +0 -0
  85. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/cli/config.py +0 -0
  86. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/cli/container.py +0 -0
  87. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/cli/dict.py +0 -0
  88. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/cli/entry_point.py +0 -0
  89. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/cli/environment.py +0 -0
  90. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/cli/import_refs.py +0 -0
  91. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/cli/launch.py +0 -0
  92. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/cli/network_file_system.py +0 -0
  93. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/cli/profile.py +0 -0
  94. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/cli/programs/__init__.py +0 -0
  95. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/cli/programs/launch_instance_ssh.py +0 -0
  96. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/cli/programs/run_jupyter.py +0 -0
  97. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/cli/programs/run_marimo.py +0 -0
  98. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/cli/programs/vscode.py +0 -0
  99. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/cli/queues.py +0 -0
  100. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/cli/run.py +0 -0
  101. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/cli/secret.py +0 -0
  102. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/cli/shell.py +0 -0
  103. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/cli/token.py +0 -0
  104. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/cli/utils.py +0 -0
  105. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/cli/volume.py +0 -0
  106. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/client.py +0 -0
  107. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/cloud_bucket_mount.py +0 -0
  108. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/cloud_bucket_mount.pyi +0 -0
  109. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/cls.py +0 -0
  110. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/cls.pyi +0 -0
  111. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/config.py +0 -0
  112. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/container_process.py +0 -0
  113. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/container_process.pyi +0 -0
  114. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/dict.py +0 -0
  115. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/dict.pyi +0 -0
  116. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/environments.py +0 -0
  117. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/environments.pyi +0 -0
  118. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/exception.py +0 -0
  119. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/experimental/__init__.py +0 -0
  120. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/experimental/flash.py +0 -0
  121. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/experimental/flash.pyi +0 -0
  122. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/experimental/ipython.py +0 -0
  123. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/file_io.py +0 -0
  124. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/file_io.pyi +0 -0
  125. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/file_pattern_matcher.py +0 -0
  126. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/functions.py +0 -0
  127. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/functions.pyi +0 -0
  128. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/gpu.py +0 -0
  129. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/image.py +0 -0
  130. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/image.pyi +0 -0
  131. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/io_streams.py +0 -0
  132. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/io_streams.pyi +0 -0
  133. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/mount.py +0 -0
  134. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/mount.pyi +0 -0
  135. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/network_file_system.py +0 -0
  136. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/network_file_system.pyi +0 -0
  137. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/object.py +0 -0
  138. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/object.pyi +0 -0
  139. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/output.py +0 -0
  140. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/parallel_map.py +0 -0
  141. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/parallel_map.pyi +0 -0
  142. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/partial_function.py +0 -0
  143. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/partial_function.pyi +0 -0
  144. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/proxy.py +0 -0
  145. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/proxy.pyi +0 -0
  146. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/py.typed +0 -0
  147. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/queue.py +0 -0
  148. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/queue.pyi +0 -0
  149. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/retries.py +0 -0
  150. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/runner.py +0 -0
  151. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/runner.pyi +0 -0
  152. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/running_app.py +0 -0
  153. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/sandbox.py +0 -0
  154. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/sandbox.pyi +0 -0
  155. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/schedule.py +0 -0
  156. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/scheduler_placement.py +0 -0
  157. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/secret.py +0 -0
  158. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/secret.pyi +0 -0
  159. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/serving.py +0 -0
  160. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/serving.pyi +0 -0
  161. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/snapshot.py +0 -0
  162. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/snapshot.pyi +0 -0
  163. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/stream_type.py +0 -0
  164. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/token_flow.py +0 -0
  165. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/token_flow.pyi +0 -0
  166. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/volume.py +0 -0
  167. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal/volume.pyi +0 -0
  168. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal.egg-info/SOURCES.txt +0 -0
  169. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal.egg-info/dependency_links.txt +0 -0
  170. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal.egg-info/entry_points.txt +0 -0
  171. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal.egg-info/requires.txt +0 -0
  172. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal.egg-info/top_level.txt +0 -0
  173. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal_docs/__init__.py +0 -0
  174. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal_docs/gen_cli_docs.py +0 -0
  175. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal_docs/gen_reference_docs.py +0 -0
  176. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal_docs/mdmd/__init__.py +0 -0
  177. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal_docs/mdmd/mdmd.py +0 -0
  178. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal_docs/mdmd/signatures.py +0 -0
  179. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal_proto/__init__.py +0 -0
  180. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal_proto/api.proto +0 -0
  181. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal_proto/api_grpc.py +0 -0
  182. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal_proto/api_pb2.py +0 -0
  183. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal_proto/api_pb2.pyi +0 -0
  184. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal_proto/api_pb2_grpc.py +0 -0
  185. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal_proto/api_pb2_grpc.pyi +0 -0
  186. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal_proto/modal_api_grpc.py +0 -0
  187. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal_proto/py.typed +0 -0
  188. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal_proto/sandbox_router.proto +0 -0
  189. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal_proto/sandbox_router_grpc.py +0 -0
  190. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal_proto/sandbox_router_pb2.py +0 -0
  191. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal_proto/sandbox_router_pb2.pyi +0 -0
  192. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal_proto/sandbox_router_pb2_grpc.py +0 -0
  193. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal_proto/sandbox_router_pb2_grpc.pyi +0 -0
  194. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal_proto/task_command_router.proto +0 -0
  195. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal_proto/task_command_router_grpc.py +0 -0
  196. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal_proto/task_command_router_pb2.py +0 -0
  197. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal_proto/task_command_router_pb2.pyi +0 -0
  198. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal_proto/task_command_router_pb2_grpc.py +0 -0
  199. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal_proto/task_command_router_pb2_grpc.pyi +0 -0
  200. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/modal_version/__main__.py +0 -0
  201. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/pyproject.toml +0 -0
  202. {modal-1.2.5.dev7 → modal-1.2.5.dev8}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.2.5.dev7
3
+ Version: 1.2.5.dev8
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -64,12 +64,10 @@ def call_lifecycle_functions(
64
64
 
65
65
 
66
66
  @contextmanager
67
- def _run_service_lifecycle(
67
+ def lifecycle_asgi(
68
68
  event_loop: UserCodeEventLoop,
69
69
  container_io_manager: "modal._runtime.container_io_manager.ContainerIOManager",
70
- function_def: api_pb2.Function,
71
70
  finalized_functions: dict[str, FinalizedFunction],
72
- exit_callback: Optional[Callable[[], None]],
73
71
  ) -> Generator[None, None, None]:
74
72
  lifespan_background_tasks = []
75
73
  try:
@@ -82,38 +80,34 @@ def _run_service_lifecycle(
82
80
  event_loop.run(finalized_function.lifespan_manager.lifespan_startup())
83
81
  yield
84
82
  finally:
85
- # Run exit handlers. From this point onward, ignore all SIGINT signals that come from
86
- # graceful shutdowns originating on the worker, as well as stray SIGUSR1 signals that
87
- # may have been sent to cancel inputs.
88
- int_handler = signal.signal(signal.SIGINT, signal.SIG_IGN)
89
- usr1_handler = signal.signal(signal.SIGUSR1, signal.SIG_IGN)
90
83
  try:
91
- try:
92
- # run lifespan shutdown for asgi apps
93
- for finalized_function in finalized_functions.values():
94
- if finalized_function.lifespan_manager:
95
- with container_io_manager.handle_user_exception():
96
- event_loop.run(finalized_function.lifespan_manager.lifespan_shutdown())
97
- finally:
98
- # no need to keep the lifespan asgi call around - we send it no more messages
99
- for task in lifespan_background_tasks:
100
- task.cancel()
101
-
102
- # Identify "exit" methods and run them.
103
- # want to make sure this is called even if the lifespan manager fails
104
- if exit_callback:
105
- exit_callback()
106
-
107
- # Finally, commit on exit to catch uncommitted volume changes and surface background
108
- # commit errors.
109
- container_io_manager.volume_commit(
110
- [v.volume_id for v in function_def.volume_mounts if v.allow_background_commits]
111
- )
84
+ # run lifespan shutdown for asgi apps
85
+ for finalized_function in finalized_functions.values():
86
+ if finalized_function.lifespan_manager:
87
+ with container_io_manager.handle_user_exception():
88
+ event_loop.run(finalized_function.lifespan_manager.lifespan_shutdown())
112
89
  finally:
113
- # Restore the original signal handler, needed for container_test hygiene since the
114
- # test runs `main()` multiple times in the same process.
115
- signal.signal(signal.SIGINT, int_handler)
116
- signal.signal(signal.SIGUSR1, usr1_handler)
90
+ # no need to keep the lifespan asgi call around - we send it no more messages
91
+ for task in lifespan_background_tasks:
92
+ task.cancel()
93
+
94
+
95
+ def disable_signals():
96
+ int_handler = signal.signal(signal.SIGINT, signal.SIG_IGN)
97
+ usr1_handler = signal.signal(signal.SIGUSR1, signal.SIG_IGN)
98
+ return int_handler, usr1_handler
99
+
100
+
101
+ def try_enable_signals(int_handler, usr1_handler):
102
+ if int_handler is not None and usr1_handler is not None:
103
+ signal.signal(signal.SIGINT, int_handler)
104
+ signal.signal(signal.SIGUSR1, usr1_handler)
105
+
106
+
107
+ def volume_commit(
108
+ container_io_manager: "modal._runtime.container_io_manager.ContainerIOManager", function_def: api_pb2.Function
109
+ ):
110
+ container_io_manager.volume_commit([v.volume_id for v in function_def.volume_mounts if v.allow_background_commits])
117
111
 
118
112
 
119
113
  class Service(metaclass=ABCMeta):
@@ -127,14 +121,30 @@ class Service(metaclass=ABCMeta):
127
121
  user_cls_instance: Any
128
122
  app: "modal.app._App"
129
123
  service_deps: Optional[Sequence["modal._object._Object"]]
124
+ function_def: api_pb2.Function
130
125
 
131
126
  @abstractmethod
132
127
  def get_finalized_functions(
133
128
  self, fun_def: api_pb2.Function, container_io_manager: "modal._runtime.container_io_manager.ContainerIOManager"
134
129
  ) -> dict[str, "FinalizedFunction"]: ...
135
130
 
131
+ @abstractmethod
136
132
  @contextmanager
133
+ def lifecycle_presnapshot(
134
+ self,
135
+ event_loop: UserCodeEventLoop,
136
+ container_io_manager: "modal._runtime.container_io_manager.ContainerIOManager",
137
+ ) -> Generator[None, None, None]: ...
138
+
137
139
  @abstractmethod
140
+ @contextmanager
141
+ def lifecycle_postsnapshot(
142
+ self,
143
+ event_loop: UserCodeEventLoop,
144
+ container_io_manager: "modal._runtime.container_io_manager.ContainerIOManager",
145
+ ) -> Generator[None, None, None]: ...
146
+
147
+ @contextmanager
138
148
  def execution_context(
139
149
  self,
140
150
  event_loop: UserCodeEventLoop,
@@ -150,6 +160,34 @@ class Service(metaclass=ABCMeta):
150
160
  6. Yield finalized_functions for execution
151
161
  7. Handles cleanup (lifespan shutdown, 'exit' methods)
152
162
  """
163
+ int_handler, usr1_handler = None, None
164
+ try:
165
+ # 1. Pre-snapshot Enter
166
+ with self.lifecycle_presnapshot(event_loop, container_io_manager):
167
+ # 2. Snapshot -- If this container is being used to create a checkpoint, checkpoint the container after
168
+ # global imports and initialization. Checkpointed containers run from this point onwards.
169
+ maybe_snapshot(container_io_manager, self.function_def)
170
+ # 3. Breakpoint wrapper
171
+ create_breakpoint_wrapper(container_io_manager)
172
+ # 4. Post-snapshot Enter
173
+ with self.lifecycle_postsnapshot(event_loop, container_io_manager):
174
+ # Get Functions
175
+ with container_io_manager.handle_user_exception():
176
+ finalized_functions = self.get_finalized_functions(self.function_def, container_io_manager)
177
+ # 5. Start ASGI lifespan
178
+ with lifecycle_asgi(event_loop, container_io_manager, finalized_functions):
179
+ # 6. Yield Finalized Functions
180
+ try:
181
+ yield finalized_functions
182
+ finally:
183
+ int_handler, usr1_handler = disable_signals()
184
+ finally:
185
+ # 9. Volume commit - runs OUTSIDE all lifecycle managers so exit handlers
186
+ # have a chance to write to disk before we commit volumes
187
+ try:
188
+ volume_commit(container_io_manager, self.function_def)
189
+ finally:
190
+ try_enable_signals(int_handler, usr1_handler)
153
191
 
154
192
 
155
193
  def construct_webhook_callable(
@@ -265,27 +303,22 @@ class ImportedFunction(Service):
265
303
  }
266
304
 
267
305
  @contextmanager
268
- def execution_context(
306
+ def lifecycle_presnapshot(
269
307
  self,
270
308
  event_loop: UserCodeEventLoop,
271
309
  container_io_manager: "modal._runtime.container_io_manager.ContainerIOManager",
272
- ) -> Generator[dict[str, "FinalizedFunction"], None, None]:
273
- # If this container is being used to create a checkpoint, checkpoint the container after
274
- # global imports and initialization. Checkpointed containers run from this point onwards.
275
- maybe_snapshot(container_io_manager, self.function_def)
276
- create_breakpoint_wrapper(container_io_manager)
277
-
278
- with container_io_manager.handle_user_exception():
279
- finalized_functions = self.get_finalized_functions(self.function_def, container_io_manager)
310
+ ):
311
+ # This is a no-op for imported functions since @enter methods are not supported
312
+ yield
280
313
 
281
- with _run_service_lifecycle(
282
- event_loop,
283
- container_io_manager,
284
- self.function_def,
285
- finalized_functions,
286
- None,
287
- ):
288
- yield finalized_functions
314
+ @contextmanager
315
+ def lifecycle_postsnapshot(
316
+ self,
317
+ event_loop: UserCodeEventLoop,
318
+ container_io_manager: "modal._runtime.container_io_manager.ContainerIOManager",
319
+ ):
320
+ # This is a no-op for imported functions since @enter methods are not supported
321
+ yield
289
322
 
290
323
 
291
324
  @dataclass
@@ -340,53 +373,38 @@ class ImportedClass(Service):
340
373
  return finalized_functions
341
374
 
342
375
  @contextmanager
343
- def execution_context(
376
+ def lifecycle_presnapshot(
344
377
  self,
345
378
  event_loop: UserCodeEventLoop,
346
379
  container_io_manager: "modal._runtime.container_io_manager.ContainerIOManager",
347
- ) -> Generator[dict[str, "FinalizedFunction"], None, None]:
348
- # 1. Pre-snapshot Enter
380
+ ):
349
381
  # Identify all "enter" methods that need to run before we snapshot.
350
382
  if not self.function_def.is_auto_snapshot:
351
383
  pre_snapshot_methods = _find_callables_for_obj(
352
384
  self.user_cls_instance, _PartialFunctionFlags.ENTER_PRE_SNAPSHOT
353
385
  )
354
386
  call_lifecycle_functions(event_loop, container_io_manager, list(pre_snapshot_methods.values()))
387
+ yield
355
388
 
356
- # 2. Snapshot
357
- # If this container is being used to create a checkpoint, checkpoint the container after
358
- # global imports and initialization. Checkpointed containers run from this point onwards.
359
- maybe_snapshot(container_io_manager, self.function_def)
360
-
361
- # 3. Breakpoint wrapper
362
- create_breakpoint_wrapper(container_io_manager)
363
-
364
- # 4. Post-snapshot Enter
389
+ @contextmanager
390
+ def lifecycle_postsnapshot(
391
+ self,
392
+ event_loop: UserCodeEventLoop,
393
+ container_io_manager: "modal._runtime.container_io_manager.ContainerIOManager",
394
+ ):
365
395
  # Identify the "enter" methods to run after resuming from a snapshot.
366
396
  if not self.function_def.is_auto_snapshot:
367
397
  post_snapshot_methods = _find_callables_for_obj(
368
398
  self.user_cls_instance, _PartialFunctionFlags.ENTER_POST_SNAPSHOT
369
399
  )
370
400
  call_lifecycle_functions(event_loop, container_io_manager, list(post_snapshot_methods.values()))
371
-
372
- # 5. Get Functions & Start Lifespan
373
- with container_io_manager.handle_user_exception():
374
- finalized_functions = self.get_finalized_functions(self.function_def, container_io_manager)
375
-
376
- def exit_callback():
401
+ try:
402
+ yield
403
+ finally:
377
404
  if not self.function_def.is_auto_snapshot:
378
405
  exit_methods = _find_callables_for_obj(self.user_cls_instance, _PartialFunctionFlags.EXIT)
379
406
  call_lifecycle_functions(event_loop, container_io_manager, list(exit_methods.values()))
380
407
 
381
- with _run_service_lifecycle(
382
- event_loop,
383
- container_io_manager,
384
- self.function_def,
385
- finalized_functions,
386
- exit_callback,
387
- ):
388
- yield finalized_functions
389
-
390
408
 
391
409
  def get_user_class_instance(_cls: modal.cls._Cls, args: tuple[Any, ...], kwargs: dict[str, Any]) -> typing.Any:
392
410
  """Returns instance of the underlying class to be used as the `self`
@@ -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.5.dev7",
35
+ version: str = "1.2.5.dev8",
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.5.dev7",
166
+ version: str = "1.2.5.dev8",
167
167
  ):
168
168
  """mdmd:hidden
169
169
  The Modal client object is not intended to be instantiated directly by users.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.2.5.dev7
3
+ Version: 1.2.5.dev8
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.5.dev7"
4
+ __version__ = "1.2.5.dev8"
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
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