modal 1.2.2.dev24__tar.gz → 1.2.2.dev30__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 (199) hide show
  1. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/PKG-INFO +1 -1
  2. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_grpc_client.py +25 -2
  3. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_utils/function_utils.py +1 -2
  4. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/client.pyi +2 -2
  5. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/cloud_bucket_mount.py +2 -0
  6. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/cloud_bucket_mount.pyi +4 -0
  7. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/experimental/flash.py +2 -3
  8. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/image.py +3 -3
  9. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/image.pyi +9 -9
  10. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/runner.py +13 -5
  11. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/runner.pyi +2 -1
  12. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal.egg-info/PKG-INFO +1 -1
  13. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal_proto/api.proto +10 -0
  14. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal_proto/api_pb2.py +841 -838
  15. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal_proto/api_pb2.pyi +25 -2
  16. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal_version/__init__.py +1 -1
  17. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/LICENSE +0 -0
  18. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/README.md +0 -0
  19. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/__init__.py +0 -0
  20. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/__main__.py +0 -0
  21. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_billing.py +0 -0
  22. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_clustered_functions.py +0 -0
  23. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_clustered_functions.pyi +0 -0
  24. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_container_entrypoint.py +0 -0
  25. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_functions.py +0 -0
  26. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_ipython.py +0 -0
  27. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_location.py +0 -0
  28. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_object.py +0 -0
  29. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_output.py +0 -0
  30. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_partial_function.py +0 -0
  31. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_pty.py +0 -0
  32. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_resolver.py +0 -0
  33. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_resources.py +0 -0
  34. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_runtime/__init__.py +0 -0
  35. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_runtime/asgi.py +0 -0
  36. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_runtime/container_io_manager.py +0 -0
  37. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_runtime/container_io_manager.pyi +0 -0
  38. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_runtime/execution_context.py +0 -0
  39. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_runtime/execution_context.pyi +0 -0
  40. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_runtime/gpu_memory_snapshot.py +0 -0
  41. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_runtime/telemetry.py +0 -0
  42. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_runtime/user_code_imports.py +0 -0
  43. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_serialization.py +0 -0
  44. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_traceback.py +0 -0
  45. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_tunnel.py +0 -0
  46. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_tunnel.pyi +0 -0
  47. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_type_manager.py +0 -0
  48. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_utils/__init__.py +0 -0
  49. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_utils/app_utils.py +0 -0
  50. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_utils/async_utils.py +0 -0
  51. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_utils/auth_token_manager.py +0 -0
  52. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_utils/blob_utils.py +0 -0
  53. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_utils/bytes_io_segment_payload.py +0 -0
  54. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_utils/deprecation.py +0 -0
  55. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_utils/docker_utils.py +0 -0
  56. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_utils/git_utils.py +0 -0
  57. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_utils/grpc_testing.py +0 -0
  58. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_utils/grpc_utils.py +0 -0
  59. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_utils/hash_utils.py +0 -0
  60. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_utils/http_utils.py +0 -0
  61. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_utils/jwt_utils.py +0 -0
  62. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_utils/logger.py +0 -0
  63. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_utils/mount_utils.py +0 -0
  64. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_utils/name_utils.py +0 -0
  65. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_utils/package_utils.py +0 -0
  66. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_utils/pattern_utils.py +0 -0
  67. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_utils/rand_pb_testing.py +0 -0
  68. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_utils/shell_utils.py +0 -0
  69. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_utils/task_command_router_client.py +0 -0
  70. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_utils/time_utils.py +0 -0
  71. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_vendor/__init__.py +0 -0
  72. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_vendor/a2wsgi_wsgi.py +0 -0
  73. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_vendor/cloudpickle.py +0 -0
  74. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_vendor/tblib.py +0 -0
  75. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/_watcher.py +0 -0
  76. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/app.py +0 -0
  77. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/app.pyi +0 -0
  78. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/billing.py +0 -0
  79. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/builder/2023.12.312.txt +0 -0
  80. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/builder/2023.12.txt +0 -0
  81. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/builder/2024.04.txt +0 -0
  82. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/builder/2024.10.txt +0 -0
  83. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/builder/2025.06.txt +0 -0
  84. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/builder/PREVIEW.txt +0 -0
  85. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/builder/README.md +0 -0
  86. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/builder/base-images.json +0 -0
  87. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/call_graph.py +0 -0
  88. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/cli/__init__.py +0 -0
  89. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/cli/_download.py +0 -0
  90. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/cli/_traceback.py +0 -0
  91. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/cli/app.py +0 -0
  92. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/cli/cluster.py +0 -0
  93. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/cli/config.py +0 -0
  94. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/cli/container.py +0 -0
  95. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/cli/dict.py +0 -0
  96. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/cli/entry_point.py +0 -0
  97. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/cli/environment.py +0 -0
  98. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/cli/import_refs.py +0 -0
  99. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/cli/launch.py +0 -0
  100. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/cli/network_file_system.py +0 -0
  101. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/cli/profile.py +0 -0
  102. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/cli/programs/__init__.py +0 -0
  103. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/cli/programs/launch_instance_ssh.py +0 -0
  104. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/cli/programs/run_jupyter.py +0 -0
  105. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/cli/programs/run_marimo.py +0 -0
  106. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/cli/programs/vscode.py +0 -0
  107. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/cli/queues.py +0 -0
  108. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/cli/run.py +0 -0
  109. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/cli/secret.py +0 -0
  110. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/cli/token.py +0 -0
  111. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/cli/utils.py +0 -0
  112. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/cli/volume.py +0 -0
  113. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/client.py +0 -0
  114. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/cls.py +0 -0
  115. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/cls.pyi +0 -0
  116. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/config.py +0 -0
  117. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/container_process.py +0 -0
  118. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/container_process.pyi +0 -0
  119. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/dict.py +0 -0
  120. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/dict.pyi +0 -0
  121. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/environments.py +0 -0
  122. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/environments.pyi +0 -0
  123. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/exception.py +0 -0
  124. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/experimental/__init__.py +0 -0
  125. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/experimental/flash.pyi +0 -0
  126. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/experimental/ipython.py +0 -0
  127. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/file_io.py +0 -0
  128. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/file_io.pyi +0 -0
  129. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/file_pattern_matcher.py +0 -0
  130. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/functions.py +0 -0
  131. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/functions.pyi +0 -0
  132. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/gpu.py +0 -0
  133. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/io_streams.py +0 -0
  134. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/io_streams.pyi +0 -0
  135. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/mount.py +0 -0
  136. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/mount.pyi +0 -0
  137. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/network_file_system.py +0 -0
  138. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/network_file_system.pyi +0 -0
  139. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/object.py +0 -0
  140. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/object.pyi +0 -0
  141. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/output.py +0 -0
  142. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/parallel_map.py +0 -0
  143. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/parallel_map.pyi +0 -0
  144. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/partial_function.py +0 -0
  145. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/partial_function.pyi +0 -0
  146. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/proxy.py +0 -0
  147. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/proxy.pyi +0 -0
  148. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/py.typed +0 -0
  149. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/queue.py +0 -0
  150. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/queue.pyi +0 -0
  151. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/retries.py +0 -0
  152. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/running_app.py +0 -0
  153. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/sandbox.py +0 -0
  154. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/sandbox.pyi +0 -0
  155. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/schedule.py +0 -0
  156. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/scheduler_placement.py +0 -0
  157. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/secret.py +0 -0
  158. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/secret.pyi +0 -0
  159. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/serving.py +0 -0
  160. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/serving.pyi +0 -0
  161. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/snapshot.py +0 -0
  162. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/snapshot.pyi +0 -0
  163. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/stream_type.py +0 -0
  164. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/token_flow.py +0 -0
  165. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/token_flow.pyi +0 -0
  166. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/volume.py +0 -0
  167. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal/volume.pyi +0 -0
  168. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal.egg-info/SOURCES.txt +0 -0
  169. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal.egg-info/dependency_links.txt +0 -0
  170. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal.egg-info/entry_points.txt +0 -0
  171. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal.egg-info/requires.txt +0 -0
  172. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal.egg-info/top_level.txt +0 -0
  173. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal_docs/__init__.py +0 -0
  174. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal_docs/gen_cli_docs.py +0 -0
  175. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal_docs/gen_reference_docs.py +0 -0
  176. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal_docs/mdmd/__init__.py +0 -0
  177. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal_docs/mdmd/mdmd.py +0 -0
  178. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal_docs/mdmd/signatures.py +0 -0
  179. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal_proto/__init__.py +0 -0
  180. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal_proto/api_grpc.py +0 -0
  181. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal_proto/api_pb2_grpc.py +0 -0
  182. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal_proto/api_pb2_grpc.pyi +0 -0
  183. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal_proto/modal_api_grpc.py +0 -0
  184. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal_proto/py.typed +0 -0
  185. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal_proto/sandbox_router.proto +0 -0
  186. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal_proto/sandbox_router_grpc.py +0 -0
  187. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal_proto/sandbox_router_pb2.py +0 -0
  188. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal_proto/sandbox_router_pb2.pyi +0 -0
  189. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal_proto/sandbox_router_pb2_grpc.py +0 -0
  190. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal_proto/sandbox_router_pb2_grpc.pyi +0 -0
  191. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal_proto/task_command_router.proto +0 -0
  192. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal_proto/task_command_router_grpc.py +0 -0
  193. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal_proto/task_command_router_pb2.py +0 -0
  194. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal_proto/task_command_router_pb2.pyi +0 -0
  195. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal_proto/task_command_router_pb2_grpc.py +0 -0
  196. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal_proto/task_command_router_pb2_grpc.pyi +0 -0
  197. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/modal_version/__main__.py +0 -0
  198. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/pyproject.toml +0 -0
  199. {modal-1.2.2.dev24 → modal-1.2.2.dev30}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.2.2.dev24
3
+ Version: 1.2.2.dev30
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -1,5 +1,5 @@
1
1
  # Copyright Modal Labs 2025
2
- from typing import TYPE_CHECKING, Any, Collection, Generic, Literal, Mapping, Optional, TypeVar, Union
2
+ from typing import TYPE_CHECKING, Any, Collection, Generic, Literal, Mapping, Optional, TypeVar, Union, overload
3
3
 
4
4
  import grpclib.client
5
5
  from google.protobuf.message import Message
@@ -47,6 +47,9 @@ class grpc_error_converter:
47
47
  return False
48
48
 
49
49
 
50
+ _DEFAULT_RETRY = Retry()
51
+
52
+
50
53
  class UnaryUnaryWrapper(Generic[RequestType, ResponseType]):
51
54
  # Calls a grpclib.UnaryUnaryMethod using a specific Client instance, respecting
52
55
  # if that client is closed etc. and possibly introducing Modal-specific retry logic
@@ -67,11 +70,31 @@ class UnaryUnaryWrapper(Generic[RequestType, ResponseType]):
67
70
  def name(self) -> str:
68
71
  return self.wrapped_method.name
69
72
 
73
+ @overload
74
+ async def __call__(
75
+ self,
76
+ req: RequestType,
77
+ *,
78
+ retry: Retry = _DEFAULT_RETRY,
79
+ timeout: None = None,
80
+ metadata: Optional[list[tuple[str, str]]] = None,
81
+ ) -> ResponseType: ...
82
+
83
+ @overload
84
+ async def __call__(
85
+ self,
86
+ req: RequestType,
87
+ *,
88
+ retry: None,
89
+ timeout: Optional[float] = None,
90
+ metadata: Optional[list[tuple[str, str]]] = None,
91
+ ) -> ResponseType: ...
92
+
70
93
  async def __call__(
71
94
  self,
72
95
  req: RequestType,
73
96
  *,
74
- retry: Optional[Retry] = Retry(),
97
+ retry: Optional[Retry] = _DEFAULT_RETRY,
75
98
  timeout: Optional[float] = None,
76
99
  metadata: Optional[list[tuple[str, str]]] = None,
77
100
  ) -> ResponseType:
@@ -645,14 +645,13 @@ class FunctionCreationStatus:
645
645
  if not self.response:
646
646
  self.status_row.finish(f"Unknown error when creating function {self.tag}")
647
647
 
648
- elif self.response.function.web_url:
648
+ elif web_url := self.response.handle_metadata.web_url:
649
649
  url_info = self.response.function.web_url_info
650
650
  requires_proxy_auth = self.response.function.webhook_config.requires_proxy_auth
651
651
  proxy_auth_suffix = " 🔑" if requires_proxy_auth else ""
652
652
  # Ensure terms used here match terms used in modal.com/docs/guide/webhook-urls doc.
653
653
  suffix = _get_suffix_from_web_url_info(url_info)
654
654
  # TODO: this is only printed when we're showing progress. Maybe move this somewhere else.
655
- web_url = self.response.handle_metadata.web_url
656
655
  for warning in self.response.server_warnings:
657
656
  self.status_row.warning(warning)
658
657
  self.status_row.finish(
@@ -33,7 +33,7 @@ class _Client:
33
33
  server_url: str,
34
34
  client_type: int,
35
35
  credentials: typing.Optional[tuple[str, str]],
36
- version: str = "1.2.2.dev24",
36
+ version: str = "1.2.2.dev30",
37
37
  ):
38
38
  """mdmd:hidden
39
39
  The Modal client object is not intended to be instantiated directly by users.
@@ -164,7 +164,7 @@ class Client:
164
164
  server_url: str,
165
165
  client_type: int,
166
166
  credentials: typing.Optional[tuple[str, str]],
167
- version: str = "1.2.2.dev24",
167
+ version: str = "1.2.2.dev30",
168
168
  ):
169
169
  """mdmd:hidden
170
170
  The Modal client object is not intended to be instantiated directly by users.
@@ -117,6 +117,7 @@ class _CloudBucketMount:
117
117
 
118
118
  read_only: bool = False
119
119
  requester_pays: bool = False
120
+ force_path_style: bool = False
120
121
 
121
122
 
122
123
  def cloud_bucket_mounts_to_proto(mounts: Sequence[tuple[str, _CloudBucketMount]]) -> list[api_pb2.CloudBucketMount]:
@@ -159,6 +160,7 @@ def cloud_bucket_mounts_to_proto(mounts: Sequence[tuple[str, _CloudBucketMount]]
159
160
  requester_pays=mount.requester_pays,
160
161
  key_prefix=key_prefix,
161
162
  oidc_auth_role_arn=mount.oidc_auth_role_arn,
163
+ force_path_style=mount.force_path_style,
162
164
  )
163
165
  cloud_bucket_mounts.append(cloud_bucket_mount)
164
166
 
@@ -99,6 +99,7 @@ class _CloudBucketMount:
99
99
  oidc_auth_role_arn: typing.Optional[str]
100
100
  read_only: bool
101
101
  requester_pays: bool
102
+ force_path_style: bool
102
103
 
103
104
  def __init__(
104
105
  self,
@@ -109,6 +110,7 @@ class _CloudBucketMount:
109
110
  oidc_auth_role_arn: typing.Optional[str] = None,
110
111
  read_only: bool = False,
111
112
  requester_pays: bool = False,
113
+ force_path_style: bool = False,
112
114
  ) -> None:
113
115
  """Initialize self. See help(type(self)) for accurate signature."""
114
116
  ...
@@ -224,6 +226,7 @@ class CloudBucketMount:
224
226
  oidc_auth_role_arn: typing.Optional[str]
225
227
  read_only: bool
226
228
  requester_pays: bool
229
+ force_path_style: bool
227
230
 
228
231
  def __init__(
229
232
  self,
@@ -234,6 +237,7 @@ class CloudBucketMount:
234
237
  oidc_auth_role_arn: typing.Optional[str] = None,
235
238
  read_only: bool = False,
236
239
  requester_pays: bool = False,
240
+ force_path_style: bool = False,
237
241
  ) -> None: ...
238
242
  def __repr__(self): ...
239
243
  def __eq__(self, other): ...
@@ -112,6 +112,7 @@ class _FlashManager:
112
112
  port=port,
113
113
  ),
114
114
  timeout=10,
115
+ retry=None,
115
116
  )
116
117
  self.num_failures = 0
117
118
  if first_registration:
@@ -145,9 +146,7 @@ class _FlashManager:
145
146
 
146
147
  async def stop(self):
147
148
  self.heartbeat_task.cancel()
148
- await self.client.stub.FlashContainerDeregister(
149
- api_pb2.FlashContainerDeregisterRequest(),
150
- )
149
+ await self.client.stub.FlashContainerDeregister(api_pb2.FlashContainerDeregisterRequest())
151
150
 
152
151
  self.stopped = True
153
152
  logger.warning(f"[Modal Flash] No longer accepting new requests on {self.tunnel.url}.")
@@ -886,8 +886,8 @@ class _Image(_Object, type_prefix="im"):
886
886
  ```python
887
887
  image = modal.Image.debian_slim().uv_pip_install("scipy", "numpy")
888
888
 
889
- app = modal.App("build-image")
890
- with modal.enable_output(), app.run():
889
+ app = modal.App.lookup("build-image", create_if_missing=True)
890
+ with modal.enable_output(): # To see logs in your local terminal
891
891
  image.build(app)
892
892
 
893
893
  # Save the image id
@@ -900,7 +900,7 @@ class _Image(_Object, type_prefix="im"):
900
900
  Alternatively, you can pre-build a image and use it in a sandbox.
901
901
 
902
902
  ```python notest
903
- app = modal.App.lookup("sandbox-example")
903
+ app = modal.App.lookup("sandbox-example", create_if_missing=True)
904
904
 
905
905
  with modal.enable_output():
906
906
  image = modal.Image.debian_slim().uv_pip_install("scipy")
@@ -330,8 +330,8 @@ class _Image(modal._object._Object):
330
330
  ```python
331
331
  image = modal.Image.debian_slim().uv_pip_install("scipy", "numpy")
332
332
 
333
- app = modal.App("build-image")
334
- with modal.enable_output(), app.run():
333
+ app = modal.App.lookup("build-image", create_if_missing=True)
334
+ with modal.enable_output(): # To see logs in your local terminal
335
335
  image.build(app)
336
336
 
337
337
  # Save the image id
@@ -344,7 +344,7 @@ class _Image(modal._object._Object):
344
344
  Alternatively, you can pre-build a image and use it in a sandbox.
345
345
 
346
346
  ```python notest
347
- app = modal.App.lookup("sandbox-example")
347
+ app = modal.App.lookup("sandbox-example", create_if_missing=True)
348
348
 
349
349
  with modal.enable_output():
350
350
  image = modal.Image.debian_slim().uv_pip_install("scipy")
@@ -1257,8 +1257,8 @@ class Image(modal.object.Object):
1257
1257
  ```python
1258
1258
  image = modal.Image.debian_slim().uv_pip_install("scipy", "numpy")
1259
1259
 
1260
- app = modal.App("build-image")
1261
- with modal.enable_output(), app.run():
1260
+ app = modal.App.lookup("build-image", create_if_missing=True)
1261
+ with modal.enable_output(): # To see logs in your local terminal
1262
1262
  image.build(app)
1263
1263
 
1264
1264
  # Save the image id
@@ -1271,7 +1271,7 @@ class Image(modal.object.Object):
1271
1271
  Alternatively, you can pre-build a image and use it in a sandbox.
1272
1272
 
1273
1273
  ```python notest
1274
- app = modal.App.lookup("sandbox-example")
1274
+ app = modal.App.lookup("sandbox-example", create_if_missing=True)
1275
1275
 
1276
1276
  with modal.enable_output():
1277
1277
  image = modal.Image.debian_slim().uv_pip_install("scipy")
@@ -1310,8 +1310,8 @@ class Image(modal.object.Object):
1310
1310
  ```python
1311
1311
  image = modal.Image.debian_slim().uv_pip_install("scipy", "numpy")
1312
1312
 
1313
- app = modal.App("build-image")
1314
- with modal.enable_output(), app.run():
1313
+ app = modal.App.lookup("build-image", create_if_missing=True)
1314
+ with modal.enable_output(): # To see logs in your local terminal
1315
1315
  image.build(app)
1316
1316
 
1317
1317
  # Save the image id
@@ -1324,7 +1324,7 @@ class Image(modal.object.Object):
1324
1324
  Alternatively, you can pre-build a image and use it in a sandbox.
1325
1325
 
1326
1326
  ```python notest
1327
- app = modal.App.lookup("sandbox-example")
1327
+ app = modal.App.lookup("sandbox-example", create_if_missing=True)
1328
1328
 
1329
1329
  with modal.enable_output():
1330
1330
  image = modal.Image.debian_slim().uv_pip_install("scipy")
@@ -76,6 +76,7 @@ async def _init_local_app_existing(client: _Client, existing_app_id: str, enviro
76
76
  async def _init_local_app_new(
77
77
  client: _Client,
78
78
  description: str,
79
+ tags: dict[str, str],
79
80
  app_state: int, # ValueType
80
81
  environment_name: str = "",
81
82
  interactive: bool = False,
@@ -84,6 +85,7 @@ async def _init_local_app_new(
84
85
  description=description,
85
86
  environment_name=environment_name,
86
87
  app_state=app_state, # type: ignore
88
+ tags=tags,
87
89
  )
88
90
  app_resp, _ = await gather_cancel_on_exc( # TODO: use TaskGroup?
89
91
  client.stub.AppCreate(app_req),
@@ -102,6 +104,7 @@ async def _init_local_app_new(
102
104
  async def _init_local_app_from_name(
103
105
  client: _Client,
104
106
  name: str,
107
+ tags: dict[str, str],
105
108
  environment_name: str = "",
106
109
  ) -> RunningApp:
107
110
  # Look up any existing deployment
@@ -117,7 +120,7 @@ async def _init_local_app_from_name(
117
120
  return await _init_local_app_existing(client, existing_app_id, environment_name)
118
121
  else:
119
122
  return await _init_local_app_new(
120
- client, name, api_pb2.APP_STATE_INITIALIZING, environment_name=environment_name
123
+ client, name, tags, api_pb2.APP_STATE_INITIALIZING, environment_name=environment_name
121
124
  )
122
125
 
123
126
 
@@ -295,9 +298,12 @@ async def _run_app(
295
298
  msg = "Interactive mode requires output to be enabled. (Use the the `modal.enable_output()` context manager.)"
296
299
  raise InvalidError(msg)
297
300
 
301
+ local_app_state = app._local_state
302
+
298
303
  running_app: RunningApp = await _init_local_app_new(
299
304
  client,
300
305
  app.description or "",
306
+ local_app_state.tags,
301
307
  environment_name=environment_name or "",
302
308
  app_state=app_state,
303
309
  interactive=interactive,
@@ -333,7 +339,6 @@ async def _run_app(
333
339
  get_app_logs_loop(client, output_mgr, app_id=running_app.app_id, app_logs_url=running_app.app_logs_url)
334
340
  )
335
341
 
336
- local_app_state = app._local_state
337
342
  try:
338
343
  # Create all members
339
344
  await _create_all_objects(client, running_app, local_app_state, environment_name)
@@ -521,12 +526,15 @@ async def _deploy_app(
521
526
  if client is None:
522
527
  client = await _Client.from_env()
523
528
 
529
+ local_app_state = app._local_state
524
530
  t0 = time.time()
525
531
 
526
532
  # Get git information to track deployment history
527
533
  commit_info_task = asyncio.create_task(get_git_commit_info())
528
534
 
529
- running_app: RunningApp = await _init_local_app_from_name(client, name, environment_name=environment_name)
535
+ running_app: RunningApp = await _init_local_app_from_name(
536
+ client, name, local_app_state.tags, environment_name=environment_name
537
+ )
530
538
 
531
539
  async with TaskContext(0) as tc:
532
540
  # Start heartbeats loop to keep the client alive
@@ -540,7 +548,7 @@ async def _deploy_app(
540
548
  await _create_all_objects(
541
549
  client,
542
550
  running_app,
543
- app._local_state,
551
+ local_app_state,
544
552
  environment_name=environment_name,
545
553
  )
546
554
 
@@ -554,7 +562,7 @@ async def _deploy_app(
554
562
  client,
555
563
  running_app,
556
564
  api_pb2.APP_STATE_DEPLOYED,
557
- app._local_state,
565
+ local_app_state,
558
566
  name=name,
559
567
  deployment_tag=tag,
560
568
  commit_info=commit_info,
@@ -16,12 +16,13 @@ async def _init_local_app_existing(
16
16
  async def _init_local_app_new(
17
17
  client: modal.client._Client,
18
18
  description: str,
19
+ tags: dict[str, str],
19
20
  app_state: int,
20
21
  environment_name: str = "",
21
22
  interactive: bool = False,
22
23
  ) -> modal.running_app.RunningApp: ...
23
24
  async def _init_local_app_from_name(
24
- client: modal.client._Client, name: str, environment_name: str = ""
25
+ client: modal.client._Client, name: str, tags: dict[str, str], environment_name: str = ""
25
26
  ) -> modal.running_app.RunningApp: ...
26
27
  async def _create_all_objects(
27
28
  client: modal.client._Client,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.2.2.dev24
3
+ Version: 1.2.2.dev30
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -849,6 +849,12 @@ message CloudBucketMount {
849
849
  GCP = 3;
850
850
  }
851
851
 
852
+ enum MetadataTTLType {
853
+ METADATA_TTL_TYPE_UNSPECIFIED = 0;
854
+ METADATA_TTL_TYPE_MINIMAL = 1;
855
+ METADATA_TTL_TYPE_INDEFINITE = 2;
856
+ }
857
+
852
858
  string bucket_name = 1;
853
859
  string mount_path = 2;
854
860
  string credentials_secret_id = 3;
@@ -859,6 +865,10 @@ message CloudBucketMount {
859
865
  optional string key_prefix = 8;
860
866
  optional string oidc_auth_role_arn = 9;
861
867
  bool force_path_style = 10;
868
+ oneof metadata_ttl_oneof {
869
+ MetadataTTLType metadata_ttl_type = 11;
870
+ uint64 metadata_ttl_seconds = 12;
871
+ }
862
872
  }
863
873
 
864
874
  message ClusterGetRequest {