modal 1.5.4.dev16__tar.gz → 1.5.4.dev18__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.4.dev16 → modal-1.5.4.dev18}/PKG-INFO +1 -1
  2. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/cli/container.py +52 -21
  3. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/cli/run.py +16 -1
  4. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/cli/workspace.py +23 -14
  5. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/client.pyi +2 -2
  6. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/runner.py +7 -0
  7. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/runner.pyi +4 -0
  8. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal.egg-info/PKG-INFO +1 -1
  9. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal_proto/api_grpc.py +32 -0
  10. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal_proto/api_pb2.py +1355 -1292
  11. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal_proto/api_pb2.pyi +131 -6
  12. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal_proto/api_pb2_grpc.py +67 -1
  13. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal_proto/api_pb2_grpc.pyi +23 -3
  14. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal_proto/modal_api_grpc.py +2 -0
  15. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal_version/__init__.py +1 -1
  16. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/LICENSE +0 -0
  17. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/README.md +0 -0
  18. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/__init__.py +0 -0
  19. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/__main__.py +0 -0
  20. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_billing.py +0 -0
  21. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_clustered_functions.py +0 -0
  22. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_clustered_functions.pyi +0 -0
  23. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_container_entrypoint.py +0 -0
  24. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_environments.py +0 -0
  25. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_function_variants.py +0 -0
  26. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_functions.py +0 -0
  27. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_grpc_client.py +0 -0
  28. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_image.py +0 -0
  29. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_ipython.py +0 -0
  30. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_load_context.py +0 -0
  31. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_location.py +0 -0
  32. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_logs.py +0 -0
  33. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_logs_manager.py +0 -0
  34. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_logs_manager.pyi +0 -0
  35. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_object.py +0 -0
  36. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_output/__init__.py +0 -0
  37. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_output/manager.py +0 -0
  38. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_output/pty.py +0 -0
  39. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_output/rich.py +0 -0
  40. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_output/status.py +0 -0
  41. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_partial_function.py +0 -0
  42. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_resolver.py +0 -0
  43. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_resources.py +0 -0
  44. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_runtime/__init__.py +0 -0
  45. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_runtime/asgi.py +0 -0
  46. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_runtime/container_io_manager.py +0 -0
  47. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_runtime/container_io_manager.pyi +0 -0
  48. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_runtime/execution_context.py +0 -0
  49. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_runtime/execution_context.pyi +0 -0
  50. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_runtime/gpu_memory_snapshot.py +0 -0
  51. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_runtime/task_lifecycle_manager.py +0 -0
  52. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_runtime/task_lifecycle_manager.pyi +0 -0
  53. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_runtime/telemetry.py +0 -0
  54. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_runtime/user_code_event_loop.py +0 -0
  55. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_runtime/user_code_imports.py +0 -0
  56. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_serialization.py +0 -0
  57. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_server.py +0 -0
  58. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_supports_logs.py +0 -0
  59. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_traceback.py +0 -0
  60. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_tunnel.py +0 -0
  61. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_tunnel.pyi +0 -0
  62. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_type_manager.py +0 -0
  63. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_utils/__init__.py +0 -0
  64. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_utils/app_utils.py +0 -0
  65. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_utils/async_utils.py +0 -0
  66. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_utils/auth_token_manager.py +0 -0
  67. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_utils/blob_utils.py +0 -0
  68. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_utils/browser_utils.py +0 -0
  69. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_utils/bytes_io_segment_payload.py +0 -0
  70. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_utils/curl_utils.py +0 -0
  71. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_utils/deprecation.py +0 -0
  72. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_utils/display_utils.py +0 -0
  73. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_utils/docker_utils.py +0 -0
  74. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_utils/function_utils.py +0 -0
  75. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_utils/git_utils.py +0 -0
  76. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_utils/grpc_testing.py +0 -0
  77. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_utils/grpc_utils.py +0 -0
  78. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_utils/hash_utils.py +0 -0
  79. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_utils/http_utils.py +0 -0
  80. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_utils/jwt_utils.py +0 -0
  81. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_utils/logger.py +0 -0
  82. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_utils/mount_utils.py +0 -0
  83. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_utils/name_utils.py +0 -0
  84. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_utils/package_utils.py +0 -0
  85. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_utils/pattern_utils.py +0 -0
  86. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_utils/proxy_support.py +0 -0
  87. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_utils/rand_pb_testing.py +0 -0
  88. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_utils/sandbox_fs_utils.py +0 -0
  89. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_utils/shell_utils.py +0 -0
  90. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_utils/task_command_router_client.py +0 -0
  91. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_utils/time_utils.py +0 -0
  92. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_vendor/__init__.py +0 -0
  93. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_vendor/a2wsgi_wsgi.py +0 -0
  94. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_vendor/cloudpickle.py +0 -0
  95. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_vendor/tblib.py +0 -0
  96. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_vendor/version.py +0 -0
  97. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_watcher.py +0 -0
  98. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/_workspace.py +0 -0
  99. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/app.py +0 -0
  100. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/app.pyi +0 -0
  101. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/billing.py +0 -0
  102. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/billing.pyi +0 -0
  103. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/builder/2023.12.312.txt +0 -0
  104. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/builder/2023.12.txt +0 -0
  105. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/builder/2024.04.txt +0 -0
  106. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/builder/2024.10.txt +0 -0
  107. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/builder/2025.06.txt +0 -0
  108. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/builder/PREVIEW.txt +0 -0
  109. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/builder/README.md +0 -0
  110. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/builder/base-images.json +0 -0
  111. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/call_graph.py +0 -0
  112. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/cli/__init__.py +0 -0
  113. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/cli/_download.py +0 -0
  114. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/cli/_help.py +0 -0
  115. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/cli/_traceback.py +0 -0
  116. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/cli/app.py +0 -0
  117. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/cli/billing.py +0 -0
  118. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/cli/bootstrap.py +0 -0
  119. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/cli/changelog.py +0 -0
  120. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/cli/cluster.py +0 -0
  121. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/cli/config.py +0 -0
  122. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/cli/curl.py +0 -0
  123. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/cli/dashboard.py +0 -0
  124. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/cli/dict.py +0 -0
  125. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/cli/endpoint.py +0 -0
  126. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/cli/entry_point.py +0 -0
  127. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/cli/environment.py +0 -0
  128. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/cli/image.py +0 -0
  129. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/cli/import_refs.py +0 -0
  130. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/cli/launch.py +0 -0
  131. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/cli/logo.py +0 -0
  132. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/cli/network_file_system.py +0 -0
  133. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/cli/profile.py +0 -0
  134. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/cli/programs/__init__.py +0 -0
  135. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/cli/programs/run_jupyter.py +0 -0
  136. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/cli/programs/vscode.py +0 -0
  137. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/cli/queues.py +0 -0
  138. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/cli/secret.py +0 -0
  139. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/cli/selector.py +0 -0
  140. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/cli/shell.py +0 -0
  141. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/cli/skills.py +0 -0
  142. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/cli/token.py +0 -0
  143. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/cli/utils.py +0 -0
  144. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/cli/volume.py +0 -0
  145. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/client.py +0 -0
  146. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/cloud_bucket_mount.py +0 -0
  147. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/cloud_bucket_mount.pyi +0 -0
  148. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/cls.py +0 -0
  149. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/cls.pyi +0 -0
  150. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/config.py +0 -0
  151. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/container_process.py +0 -0
  152. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/container_process.pyi +0 -0
  153. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/dict.py +0 -0
  154. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/dict.pyi +0 -0
  155. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/environments.py +0 -0
  156. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/environments.pyi +0 -0
  157. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/exception.py +0 -0
  158. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/experimental/__init__.py +0 -0
  159. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/experimental/flash.py +0 -0
  160. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/experimental/flash.pyi +0 -0
  161. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/experimental/ipython.py +0 -0
  162. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/file_io.py +0 -0
  163. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/file_io.pyi +0 -0
  164. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/file_pattern_matcher.py +0 -0
  165. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/functions.py +0 -0
  166. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/functions.pyi +0 -0
  167. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/image.py +0 -0
  168. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/image.pyi +0 -0
  169. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/io_streams.py +0 -0
  170. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/io_streams.pyi +0 -0
  171. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/mount.py +0 -0
  172. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/mount.pyi +0 -0
  173. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/network_file_system.py +0 -0
  174. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/network_file_system.pyi +0 -0
  175. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/object.py +0 -0
  176. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/object.pyi +0 -0
  177. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/output.py +0 -0
  178. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/parallel_map.py +0 -0
  179. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/parallel_map.pyi +0 -0
  180. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/partial_function.py +0 -0
  181. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/partial_function.pyi +0 -0
  182. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/proxy.py +0 -0
  183. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/proxy.pyi +0 -0
  184. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/py.typed +0 -0
  185. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/queue.py +0 -0
  186. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/queue.pyi +0 -0
  187. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/retries.py +0 -0
  188. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/running_app.py +0 -0
  189. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/sandbox.py +0 -0
  190. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/sandbox.pyi +0 -0
  191. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/sandbox_fs.py +0 -0
  192. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/sandbox_fs.pyi +0 -0
  193. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/schedule.py +0 -0
  194. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/scheduler_placement.py +0 -0
  195. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/secret.py +0 -0
  196. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/secret.pyi +0 -0
  197. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/server.py +0 -0
  198. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/server.pyi +0 -0
  199. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/serving.py +0 -0
  200. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/serving.pyi +0 -0
  201. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/skills/modal/SKILL.md +0 -0
  202. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/snapshot.py +0 -0
  203. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/snapshot.pyi +0 -0
  204. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/stream_type.py +0 -0
  205. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/token_flow.py +0 -0
  206. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/token_flow.pyi +0 -0
  207. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/types.py +0 -0
  208. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/volume.py +0 -0
  209. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/volume.pyi +0 -0
  210. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/workspace.py +0 -0
  211. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal/workspace.pyi +0 -0
  212. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal.egg-info/SOURCES.txt +0 -0
  213. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal.egg-info/dependency_links.txt +0 -0
  214. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal.egg-info/entry_points.txt +0 -0
  215. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal.egg-info/requires.txt +0 -0
  216. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal.egg-info/top_level.txt +0 -0
  217. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal_docs/__init__.py +0 -0
  218. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal_docs/gen_cli_docs.py +0 -0
  219. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal_docs/gen_cli_docs_main.py +0 -0
  220. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal_docs/gen_reference_docs.py +0 -0
  221. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal_docs/gen_reference_docs_main.py +0 -0
  222. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal_docs/mdmd/__init__.py +0 -0
  223. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal_docs/mdmd/mdmd.py +0 -0
  224. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal_docs/mdmd/signatures.py +0 -0
  225. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal_docs/mdmd/types.py +0 -0
  226. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal_docs/reference_intro.md +0 -0
  227. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal_proto/__init__.py +0 -0
  228. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal_proto/py.typed +0 -0
  229. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal_proto/task_command_router_grpc.py +0 -0
  230. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal_proto/task_command_router_pb2.py +0 -0
  231. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal_proto/task_command_router_pb2.pyi +0 -0
  232. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal_proto/task_command_router_pb2_grpc.py +0 -0
  233. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal_proto/task_command_router_pb2_grpc.pyi +0 -0
  234. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/modal_version/__main__.py +0 -0
  235. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/pyproject.toml +0 -0
  236. {modal-1.5.4.dev16 → modal-1.5.4.dev18}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.5.4.dev16
3
+ Version: 1.5.4.dev18
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License-Expression: Apache-2.0
@@ -1,4 +1,6 @@
1
1
  # Copyright Modal Labs 2022
2
+ import asyncio
3
+ import dataclasses
2
4
  import warnings
3
5
  from datetime import datetime, timezone
4
6
 
@@ -24,14 +26,16 @@ from modal.cli.utils import (
24
26
  yes_option,
25
27
  )
26
28
  from modal.client import _Client
27
- from modal.exception import InvalidError
28
- from modal.sandbox import _container_exec
29
+ from modal.exception import ConflictError, InvalidError
30
+ from modal.sandbox import SandboxVersion, _container_exec, _get_sandbox_version, _Sandbox
29
31
  from modal_proto import api_pb2
30
32
 
31
33
  from ._help import ModalGroup
32
34
 
33
35
  container_cli = ModalGroup(name="container", help="Manage and connect to running containers.")
34
36
 
37
+ _SANDBOX_TASK_ID_WAIT_SECS = 55.0
38
+
35
39
 
36
40
  @container_cli.command("list")
37
41
  @click.option("--app-id", default="", help="List containers running for a specific App.")
@@ -149,6 +153,13 @@ async def logs(
149
153
  else:
150
154
  raise InvalidError(f"Invalid container ID: {container_id}")
151
155
 
156
+ is_v2_sandbox = sandbox_id is not None and _get_sandbox_version(sandbox_id) == SandboxVersion.V2
157
+
158
+ if follow and is_v2_sandbox:
159
+ raise UsageError(
160
+ "Following logs (-f/--follow) is not supported for this Sandbox. Re-run without -f to fetch its logs."
161
+ )
162
+
152
163
  if follow and (since or until or tail):
153
164
  raise UsageError("--follow cannot be combined with --since, --until, or --tail.")
154
165
 
@@ -190,32 +201,52 @@ async def logs(
190
201
  # Resolve the app_id for the container.
191
202
  client = await _Client.from_env()
192
203
 
193
- if sandbox_id:
194
- sb_resp = await client.stub.SandboxGetTaskId(api_pb2.SandboxGetTaskIdRequest(sandbox_id=sandbox_id))
195
- task_id = sb_resp.task_id
204
+ enqueued_dt: datetime | None = None
205
+ finished_dt: datetime | None = None
206
+
207
+ if is_v2_sandbox:
208
+ assert sandbox_id is not None
209
+ sandbox = await _Sandbox.from_id(sandbox_id, client)
210
+ app_id = sandbox._app_id or ""
211
+ try:
212
+ task_id = await asyncio.wait_for(
213
+ sandbox._get_task_id(raise_if_task_complete=True),
214
+ timeout=_SANDBOX_TASK_ID_WAIT_SECS,
215
+ )
216
+ except (asyncio.TimeoutError, ConflictError):
217
+ # No container ran (still queued, or finished before starting), so there are no
218
+ # logs. Returning empty is consistent with other no-logs-yet cases (e.g. logs not
219
+ # yet flushed to ClickHouse), so we don't warn.
220
+ return
221
+ log_filters = dataclasses.replace(log_filters, sandbox_id="", task_id=task_id)
222
+ else:
223
+ if sandbox_id:
224
+ sb_resp = await client.stub.SandboxGetTaskId(api_pb2.SandboxGetTaskIdRequest(sandbox_id=sandbox_id))
225
+ task_id = sb_resp.task_id
196
226
 
197
- assert task_id
198
- task_info_resp = await client.stub.TaskGetInfo(api_pb2.TaskGetInfoRequest(task_id=task_id))
199
- app_id = task_info_resp.app_id
227
+ assert task_id
228
+ task_info_resp = await client.stub.TaskGetInfo(api_pb2.TaskGetInfoRequest(task_id=task_id))
229
+ app_id = task_info_resp.app_id
200
230
 
201
- if not task_info_resp.info.enqueued_at:
202
- return
231
+ if not task_info_resp.info.enqueued_at:
232
+ return
203
233
 
204
- container_enqueued_dt = datetime.fromtimestamp(task_info_resp.info.enqueued_at, timezone.utc)
234
+ enqueued_dt = datetime.fromtimestamp(task_info_resp.info.enqueued_at, timezone.utc)
235
+ if task_info_resp.info.finished_at:
236
+ finished_dt = datetime.fromtimestamp(task_info_resp.info.finished_at, timezone.utc)
205
237
 
206
238
  now = datetime.now(timezone.utc)
239
+ # V2 Sandboxes don't expose task enqueue/finish times to the client, so fall back to the
240
+ # widest single-query window. This can miss logs older than _MAX_FETCH_RANGE for workspaces
241
+ # whose custom log retention window exceeds it.
242
+ default_since_dt = enqueued_dt or (now - _MAX_FETCH_RANGE)
243
+ default_until_dt = finished_dt or now
244
+
207
245
  if all_logs:
208
- since_dt = container_enqueued_dt
209
- if task_info_resp.info.finished_at:
210
- until_dt = datetime.fromtimestamp(task_info_resp.info.finished_at, timezone.utc)
211
- else:
212
- until_dt = now
246
+ since_dt = default_since_dt
247
+ until_dt = default_until_dt
213
248
  else:
214
- since_dt = _parse_time_arg(since, default=container_enqueued_dt)
215
- if task_info_resp.info.finished_at:
216
- default_until_dt = datetime.fromtimestamp(task_info_resp.info.finished_at, timezone.utc)
217
- else:
218
- default_until_dt = now
249
+ since_dt = _parse_time_arg(since, default=default_since_dt)
219
250
  until_dt = _parse_time_arg(until, default=default_until_dt)
220
251
 
221
252
  if since is not None and until is not None and since_dt >= until_dt:
@@ -539,6 +539,13 @@ def run(
539
539
  help="Deployment strategy",
540
540
  type=click.Choice(get_args(DEPLOYMENT_STRATEGY_TYPE)),
541
541
  )
542
+ @click.option(
543
+ "--staged",
544
+ "staged",
545
+ is_flag=True,
546
+ default=False,
547
+ hidden=True,
548
+ )
542
549
  def deploy(
543
550
  app_ref: str,
544
551
  name: str = "",
@@ -548,6 +555,7 @@ def deploy(
548
555
  use_module_mode: bool = False,
549
556
  timestamps: bool = False,
550
557
  strategy: str = "rolling",
558
+ staged: bool = False,
551
559
  ):
552
560
  """Deploy a Modal application.
553
561
 
@@ -578,7 +586,14 @@ def deploy(
578
586
  "modal deploy ... --name=some-name"
579
587
  )
580
588
 
581
- res = deploy_app(app, name=name, environment_name=env or "", tag=tag, deployment_strategy=strategy)
589
+ res = deploy_app(
590
+ app,
591
+ name=name,
592
+ environment_name=env or "",
593
+ tag=tag,
594
+ deployment_strategy=strategy,
595
+ staged=staged,
596
+ )
582
597
 
583
598
  if stream_logs:
584
599
  # stream_app_logs is defined in cli/utils.py, which does not get type stubs
@@ -3,6 +3,8 @@ import json as json_mod
3
3
 
4
4
  import click
5
5
  import rich
6
+ import rich.box
7
+ import rich.table
6
8
 
7
9
  from modal._utils.time_utils import timestamp_to_localized_str
8
10
  from modal.cli.utils import confirm_or_suggest_yes, display_table, yes_option
@@ -46,15 +48,26 @@ def members_list(json: bool = False):
46
48
 
47
49
  PROXY_TOKENS_HELP_TEXT = """Manage the proxy tokens of the current Workspace.
48
50
 
49
- Proxy tokens provide authentication to HTTP interfaces on Modal Servers and Web Functions.
50
- They are passed as request headers (`Modal-Key` and `Modal-Secret`). On Modal Servers and
51
- Endpoints they can also be joined into a single `Authorization: Bearer
52
- wk-<id>.ws-<secret>` header, which OpenAI-compatible clients accept as an API key. See
53
- https://modal.com/docs/guide/webhook-proxy-auth for more information.
51
+ Proxy tokens provide authentication to Modal Endpoints, Servers, and Web Functions.
54
52
 
55
53
  Proxy tokens and secrets have `wk-` and `ws-` prefixes, respectively. They cannot be
56
54
  interchanged with API tokens (which use `ak-` and `as-` prefixes).
57
55
 
56
+ Proxy tokens are passed as request headers, either as a key / secret pair:
57
+
58
+ ```
59
+ Modal-Key: wk-123
60
+ Modal-Secret: ws-456
61
+ ```
62
+
63
+ Or as a single Bearer token:
64
+
65
+ ```
66
+ Authorization: Bearer wk-123.ws-456
67
+ ```
68
+
69
+ See https://modal.com/docs/guide/webhook-proxy-auth for more information.
70
+
58
71
  On workspaces with RBAC enabled, tokens are scoped to specific environments;
59
72
  use the `allow` and `revoke` commands to manage environment associations.
60
73
  """
@@ -85,13 +98,10 @@ def proxy_tokens_create(*, json: bool = False):
85
98
  )
86
99
  )
87
100
  else:
88
- output_manager.print(
89
- f"Modal-Key: {token.token_id}\n"
90
- f"Modal-Secret: {token.token_secret}\n"
91
- "\n"
92
- "Or as a single header (Endpoints and Servers only):\n"
93
- f"Authorization: {bearer}"
94
- )
101
+ table = rich.table.Table(show_header=False, box=rich.box.HORIZONTALS, show_lines=True)
102
+ table.add_row(f"Modal-Key: {token.token_id}\nModal-Secret: {token.token_secret}")
103
+ table.add_row(f"Authorization: {bearer}")
104
+ output_manager.print(table)
95
105
 
96
106
 
97
107
  @proxy_tokens_cli.command("list", help="List the proxy tokens of the current Workspace.")
@@ -138,8 +148,7 @@ def proxy_tokens_revoke(token_id: str, environment_name: str):
138
148
  def proxy_tokens_delete(token_id: str, yes: bool = False):
139
149
  if not yes:
140
150
  message = (
141
- f"Are you sure you want to delete proxy token {token_id!r}? "
142
- "Any web endpoints relying on it will no longer accept it."
151
+ f"Are you sure you want to delete proxy token {token_id!r}? Requests using this token will be rejected."
143
152
  )
144
153
  confirm_or_suggest_yes(message)
145
154
  Workspace.from_context().proxy_tokens.delete(token_id)
@@ -37,7 +37,7 @@ class _Client:
37
37
  server_url: str,
38
38
  client_type: int,
39
39
  credentials: typing.Optional[tuple[str, str]],
40
- version: str = "1.5.4.dev16",
40
+ version: str = "1.5.4.dev18",
41
41
  ):
42
42
  """mdmd:hidden
43
43
  The Modal client object is not intended to be instantiated directly by users.
@@ -207,7 +207,7 @@ class Client:
207
207
  server_url: str,
208
208
  client_type: int,
209
209
  credentials: typing.Optional[tuple[str, str]],
210
- version: str = "1.5.4.dev16",
210
+ version: str = "1.5.4.dev18",
211
211
  ):
212
212
  """mdmd:hidden
213
213
  The Modal client object is not intended to be instantiated directly by users.
@@ -280,10 +280,14 @@ async def _publish_app(
280
280
  commit_info: api_pb2.CommitInfo | None = None, # Git commit information
281
281
  deployment_strategy: str = "rolling",
282
282
  environment_name: str | None = None,
283
+ staged: bool = False,
283
284
  ) -> tuple[str, list[api_pb2.Warning], float]:
284
285
  """Wrapper for AppPublish RPC."""
285
286
  deployment_strategy = _validate_deployment_strategy(deployment_strategy)
286
287
 
288
+ if staged and deployment_strategy == "recreate":
289
+ raise InvalidError("Cannot use `recreate` deployment strategy with a staged deployment")
290
+
287
291
  functions = app_local_state.functions
288
292
  definition_ids = {obj.object_id: obj._get_metadata().definition_id for obj in functions.values()} # type: ignore
289
293
 
@@ -297,6 +301,7 @@ async def _publish_app(
297
301
  function_ids=running_app.function_ids,
298
302
  class_ids=running_app.class_ids,
299
303
  definition_ids=definition_ids,
304
+ staged=staged,
300
305
  )
301
306
  response = await client.stub.AppPublish(request)
302
307
  print_server_warnings(response.server_warnings)
@@ -590,6 +595,7 @@ async def _deploy_app(
590
595
  tag: str = "",
591
596
  deployment_strategy: str = "rolling",
592
597
  client: _Client | None = None,
598
+ staged: bool = False,
593
599
  ) -> DeployResult:
594
600
  """Internal function for deploying an App.
595
601
 
@@ -665,6 +671,7 @@ async def _deploy_app(
665
671
  commit_info=commit_info,
666
672
  environment_name=root_load_context.environment_name,
667
673
  deployment_strategy=deployment_strategy,
674
+ staged=staged,
668
675
  )
669
676
  except Exception as e:
670
677
  # Note that AppClientDisconnect only stops the app if it's still initializing, and is a no-op otherwise.
@@ -53,6 +53,7 @@ async def _publish_app(
53
53
  commit_info: typing.Optional[modal_proto.api_pb2.CommitInfo] = None,
54
54
  deployment_strategy: str = "rolling",
55
55
  environment_name: typing.Optional[str] = None,
56
+ staged: bool = False,
56
57
  ) -> tuple[str, list[modal_proto.api_pb2.Warning], float]:
57
58
  """Wrapper for AppPublish RPC."""
58
59
  ...
@@ -131,6 +132,7 @@ async def _deploy_app(
131
132
  tag: str = "",
132
133
  deployment_strategy: str = "rolling",
133
134
  client: typing.Optional[modal.client._Client] = None,
135
+ staged: bool = False,
134
136
  ) -> DeployResult:
135
137
  """Internal function for deploying an App.
136
138
 
@@ -238,6 +240,7 @@ class __deploy_app_spec(typing_extensions.Protocol):
238
240
  tag: str = "",
239
241
  deployment_strategy: str = "rolling",
240
242
  client: typing.Optional[modal.client.Client] = None,
243
+ staged: bool = False,
241
244
  ) -> DeployResult:
242
245
  """Internal function for deploying an App.
243
246
 
@@ -255,6 +258,7 @@ class __deploy_app_spec(typing_extensions.Protocol):
255
258
  tag: str = "",
256
259
  deployment_strategy: str = "rolling",
257
260
  client: typing.Optional[modal.client.Client] = None,
261
+ staged: bool = False,
258
262
  ) -> DeployResult:
259
263
  """Internal function for deploying an App.
260
264
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.5.4.dev16
3
+ Version: 1.5.4.dev18
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License-Expression: Apache-2.0
@@ -83,6 +83,10 @@ class ModalClientBase(abc.ABC):
83
83
  async def AppLookup(self, stream: 'grpclib.server.Stream[modal_proto.api_pb2.AppLookupRequest, modal_proto.api_pb2.AppLookupResponse]') -> None:
84
84
  pass
85
85
 
86
+ @abc.abstractmethod
87
+ async def AppPromote(self, stream: 'grpclib.server.Stream[modal_proto.api_pb2.AppPromoteRequest, modal_proto.api_pb2.AppPromoteResponse]') -> None:
88
+ pass
89
+
86
90
  @abc.abstractmethod
87
91
  async def AppPublish(self, stream: 'grpclib.server.Stream[modal_proto.api_pb2.AppPublishRequest, modal_proto.api_pb2.AppPublishResponse]') -> None:
88
92
  pass
@@ -931,6 +935,10 @@ class ModalClientBase(abc.ABC):
931
935
  async def WebhookTokenListForEnvironment(self, stream: 'grpclib.server.Stream[modal_proto.api_pb2.WebhookTokenListForEnvironmentRequest, modal_proto.api_pb2.WebhookTokenListResponse]') -> None:
932
936
  pass
933
937
 
938
+ @abc.abstractmethod
939
+ async def WorkspaceBillingRates(self, stream: 'grpclib.server.Stream[modal_proto.api_pb2.WorkspaceBillingRatesRequest, modal_proto.api_pb2.WorkspaceBillingRatesResponse]') -> None:
940
+ pass
941
+
934
942
  @abc.abstractmethod
935
943
  async def WorkspaceBillingReport(self, stream: 'grpclib.server.Stream[modal_proto.api_pb2.WorkspaceBillingReportRequest, modal_proto.api_pb2.WorkspaceBillingReportItem]') -> None:
936
944
  pass
@@ -1061,6 +1069,12 @@ class ModalClientBase(abc.ABC):
1061
1069
  modal_proto.api_pb2.AppLookupRequest,
1062
1070
  modal_proto.api_pb2.AppLookupResponse,
1063
1071
  ),
1072
+ '/modal.client.ModalClient/AppPromote': grpclib.const.Handler(
1073
+ self.AppPromote,
1074
+ grpclib.const.Cardinality.UNARY_UNARY,
1075
+ modal_proto.api_pb2.AppPromoteRequest,
1076
+ modal_proto.api_pb2.AppPromoteResponse,
1077
+ ),
1064
1078
  '/modal.client.ModalClient/AppPublish': grpclib.const.Handler(
1065
1079
  self.AppPublish,
1066
1080
  grpclib.const.Cardinality.UNARY_UNARY,
@@ -2333,6 +2347,12 @@ class ModalClientBase(abc.ABC):
2333
2347
  modal_proto.api_pb2.WebhookTokenListForEnvironmentRequest,
2334
2348
  modal_proto.api_pb2.WebhookTokenListResponse,
2335
2349
  ),
2350
+ '/modal.client.ModalClient/WorkspaceBillingRates': grpclib.const.Handler(
2351
+ self.WorkspaceBillingRates,
2352
+ grpclib.const.Cardinality.UNARY_UNARY,
2353
+ modal_proto.api_pb2.WorkspaceBillingRatesRequest,
2354
+ modal_proto.api_pb2.WorkspaceBillingRatesResponse,
2355
+ ),
2336
2356
  '/modal.client.ModalClient/WorkspaceBillingReport': grpclib.const.Handler(
2337
2357
  self.WorkspaceBillingReport,
2338
2358
  grpclib.const.Cardinality.UNARY_STREAM,
@@ -2483,6 +2503,12 @@ class ModalClientStub:
2483
2503
  modal_proto.api_pb2.AppLookupRequest,
2484
2504
  modal_proto.api_pb2.AppLookupResponse,
2485
2505
  )
2506
+ self.AppPromote = grpclib.client.UnaryUnaryMethod(
2507
+ channel,
2508
+ '/modal.client.ModalClient/AppPromote',
2509
+ modal_proto.api_pb2.AppPromoteRequest,
2510
+ modal_proto.api_pb2.AppPromoteResponse,
2511
+ )
2486
2512
  self.AppPublish = grpclib.client.UnaryUnaryMethod(
2487
2513
  channel,
2488
2514
  '/modal.client.ModalClient/AppPublish',
@@ -3755,6 +3781,12 @@ class ModalClientStub:
3755
3781
  modal_proto.api_pb2.WebhookTokenListForEnvironmentRequest,
3756
3782
  modal_proto.api_pb2.WebhookTokenListResponse,
3757
3783
  )
3784
+ self.WorkspaceBillingRates = grpclib.client.UnaryUnaryMethod(
3785
+ channel,
3786
+ '/modal.client.ModalClient/WorkspaceBillingRates',
3787
+ modal_proto.api_pb2.WorkspaceBillingRatesRequest,
3788
+ modal_proto.api_pb2.WorkspaceBillingRatesResponse,
3789
+ )
3758
3790
  self.WorkspaceBillingReport = grpclib.client.UnaryStreamMethod(
3759
3791
  channel,
3760
3792
  '/modal.client.ModalClient/WorkspaceBillingReport',