modal 1.5.4.dev16__tar.gz → 1.5.4.dev17__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.dev17}/PKG-INFO +1 -1
  2. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/cli/container.py +52 -21
  3. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/cli/run.py +16 -1
  4. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/cli/workspace.py +23 -14
  5. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/client.pyi +2 -2
  6. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/functions.pyi +6 -6
  7. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/runner.py +7 -0
  8. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/runner.pyi +4 -0
  9. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal.egg-info/PKG-INFO +1 -1
  10. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal_proto/api_pb2.py +1289 -1289
  11. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal_proto/api_pb2.pyi +23 -5
  12. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal_version/__init__.py +1 -1
  13. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/LICENSE +0 -0
  14. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/README.md +0 -0
  15. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/__init__.py +0 -0
  16. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/__main__.py +0 -0
  17. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_billing.py +0 -0
  18. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_clustered_functions.py +0 -0
  19. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_clustered_functions.pyi +0 -0
  20. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_container_entrypoint.py +0 -0
  21. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_environments.py +0 -0
  22. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_function_variants.py +0 -0
  23. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_functions.py +0 -0
  24. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_grpc_client.py +0 -0
  25. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_image.py +0 -0
  26. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_ipython.py +0 -0
  27. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_load_context.py +0 -0
  28. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_location.py +0 -0
  29. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_logs.py +0 -0
  30. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_logs_manager.py +0 -0
  31. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_logs_manager.pyi +0 -0
  32. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_object.py +0 -0
  33. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_output/__init__.py +0 -0
  34. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_output/manager.py +0 -0
  35. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_output/pty.py +0 -0
  36. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_output/rich.py +0 -0
  37. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_output/status.py +0 -0
  38. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_partial_function.py +0 -0
  39. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_resolver.py +0 -0
  40. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_resources.py +0 -0
  41. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_runtime/__init__.py +0 -0
  42. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_runtime/asgi.py +0 -0
  43. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_runtime/container_io_manager.py +0 -0
  44. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_runtime/container_io_manager.pyi +0 -0
  45. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_runtime/execution_context.py +0 -0
  46. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_runtime/execution_context.pyi +0 -0
  47. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_runtime/gpu_memory_snapshot.py +0 -0
  48. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_runtime/task_lifecycle_manager.py +0 -0
  49. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_runtime/task_lifecycle_manager.pyi +0 -0
  50. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_runtime/telemetry.py +0 -0
  51. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_runtime/user_code_event_loop.py +0 -0
  52. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_runtime/user_code_imports.py +0 -0
  53. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_serialization.py +0 -0
  54. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_server.py +0 -0
  55. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_supports_logs.py +0 -0
  56. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_traceback.py +0 -0
  57. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_tunnel.py +0 -0
  58. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_tunnel.pyi +0 -0
  59. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_type_manager.py +0 -0
  60. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_utils/__init__.py +0 -0
  61. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_utils/app_utils.py +0 -0
  62. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_utils/async_utils.py +0 -0
  63. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_utils/auth_token_manager.py +0 -0
  64. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_utils/blob_utils.py +0 -0
  65. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_utils/browser_utils.py +0 -0
  66. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_utils/bytes_io_segment_payload.py +0 -0
  67. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_utils/curl_utils.py +0 -0
  68. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_utils/deprecation.py +0 -0
  69. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_utils/display_utils.py +0 -0
  70. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_utils/docker_utils.py +0 -0
  71. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_utils/function_utils.py +0 -0
  72. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_utils/git_utils.py +0 -0
  73. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_utils/grpc_testing.py +0 -0
  74. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_utils/grpc_utils.py +0 -0
  75. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_utils/hash_utils.py +0 -0
  76. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_utils/http_utils.py +0 -0
  77. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_utils/jwt_utils.py +0 -0
  78. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_utils/logger.py +0 -0
  79. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_utils/mount_utils.py +0 -0
  80. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_utils/name_utils.py +0 -0
  81. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_utils/package_utils.py +0 -0
  82. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_utils/pattern_utils.py +0 -0
  83. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_utils/proxy_support.py +0 -0
  84. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_utils/rand_pb_testing.py +0 -0
  85. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_utils/sandbox_fs_utils.py +0 -0
  86. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_utils/shell_utils.py +0 -0
  87. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_utils/task_command_router_client.py +0 -0
  88. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_utils/time_utils.py +0 -0
  89. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_vendor/__init__.py +0 -0
  90. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_vendor/a2wsgi_wsgi.py +0 -0
  91. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_vendor/cloudpickle.py +0 -0
  92. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_vendor/tblib.py +0 -0
  93. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_vendor/version.py +0 -0
  94. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_watcher.py +0 -0
  95. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/_workspace.py +0 -0
  96. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/app.py +0 -0
  97. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/app.pyi +0 -0
  98. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/billing.py +0 -0
  99. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/billing.pyi +0 -0
  100. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/builder/2023.12.312.txt +0 -0
  101. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/builder/2023.12.txt +0 -0
  102. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/builder/2024.04.txt +0 -0
  103. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/builder/2024.10.txt +0 -0
  104. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/builder/2025.06.txt +0 -0
  105. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/builder/PREVIEW.txt +0 -0
  106. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/builder/README.md +0 -0
  107. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/builder/base-images.json +0 -0
  108. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/call_graph.py +0 -0
  109. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/cli/__init__.py +0 -0
  110. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/cli/_download.py +0 -0
  111. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/cli/_help.py +0 -0
  112. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/cli/_traceback.py +0 -0
  113. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/cli/app.py +0 -0
  114. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/cli/billing.py +0 -0
  115. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/cli/bootstrap.py +0 -0
  116. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/cli/changelog.py +0 -0
  117. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/cli/cluster.py +0 -0
  118. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/cli/config.py +0 -0
  119. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/cli/curl.py +0 -0
  120. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/cli/dashboard.py +0 -0
  121. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/cli/dict.py +0 -0
  122. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/cli/endpoint.py +0 -0
  123. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/cli/entry_point.py +0 -0
  124. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/cli/environment.py +0 -0
  125. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/cli/image.py +0 -0
  126. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/cli/import_refs.py +0 -0
  127. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/cli/launch.py +0 -0
  128. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/cli/logo.py +0 -0
  129. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/cli/network_file_system.py +0 -0
  130. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/cli/profile.py +0 -0
  131. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/cli/programs/__init__.py +0 -0
  132. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/cli/programs/run_jupyter.py +0 -0
  133. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/cli/programs/vscode.py +0 -0
  134. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/cli/queues.py +0 -0
  135. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/cli/secret.py +0 -0
  136. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/cli/selector.py +0 -0
  137. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/cli/shell.py +0 -0
  138. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/cli/skills.py +0 -0
  139. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/cli/token.py +0 -0
  140. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/cli/utils.py +0 -0
  141. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/cli/volume.py +0 -0
  142. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/client.py +0 -0
  143. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/cloud_bucket_mount.py +0 -0
  144. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/cloud_bucket_mount.pyi +0 -0
  145. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/cls.py +0 -0
  146. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/cls.pyi +0 -0
  147. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/config.py +0 -0
  148. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/container_process.py +0 -0
  149. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/container_process.pyi +0 -0
  150. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/dict.py +0 -0
  151. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/dict.pyi +0 -0
  152. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/environments.py +0 -0
  153. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/environments.pyi +0 -0
  154. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/exception.py +0 -0
  155. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/experimental/__init__.py +0 -0
  156. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/experimental/flash.py +0 -0
  157. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/experimental/flash.pyi +0 -0
  158. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/experimental/ipython.py +0 -0
  159. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/file_io.py +0 -0
  160. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/file_io.pyi +0 -0
  161. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/file_pattern_matcher.py +0 -0
  162. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/functions.py +0 -0
  163. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/image.py +0 -0
  164. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/image.pyi +0 -0
  165. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/io_streams.py +0 -0
  166. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/io_streams.pyi +0 -0
  167. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/mount.py +0 -0
  168. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/mount.pyi +0 -0
  169. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/network_file_system.py +0 -0
  170. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/network_file_system.pyi +0 -0
  171. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/object.py +0 -0
  172. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/object.pyi +0 -0
  173. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/output.py +0 -0
  174. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/parallel_map.py +0 -0
  175. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/parallel_map.pyi +0 -0
  176. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/partial_function.py +0 -0
  177. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/partial_function.pyi +0 -0
  178. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/proxy.py +0 -0
  179. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/proxy.pyi +0 -0
  180. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/py.typed +0 -0
  181. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/queue.py +0 -0
  182. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/queue.pyi +0 -0
  183. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/retries.py +0 -0
  184. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/running_app.py +0 -0
  185. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/sandbox.py +0 -0
  186. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/sandbox.pyi +0 -0
  187. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/sandbox_fs.py +0 -0
  188. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/sandbox_fs.pyi +0 -0
  189. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/schedule.py +0 -0
  190. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/scheduler_placement.py +0 -0
  191. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/secret.py +0 -0
  192. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/secret.pyi +0 -0
  193. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/server.py +0 -0
  194. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/server.pyi +0 -0
  195. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/serving.py +0 -0
  196. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/serving.pyi +0 -0
  197. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/skills/modal/SKILL.md +0 -0
  198. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/snapshot.py +0 -0
  199. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/snapshot.pyi +0 -0
  200. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/stream_type.py +0 -0
  201. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/token_flow.py +0 -0
  202. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/token_flow.pyi +0 -0
  203. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/types.py +0 -0
  204. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/volume.py +0 -0
  205. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/volume.pyi +0 -0
  206. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/workspace.py +0 -0
  207. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal/workspace.pyi +0 -0
  208. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal.egg-info/SOURCES.txt +0 -0
  209. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal.egg-info/dependency_links.txt +0 -0
  210. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal.egg-info/entry_points.txt +0 -0
  211. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal.egg-info/requires.txt +0 -0
  212. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal.egg-info/top_level.txt +0 -0
  213. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal_docs/__init__.py +0 -0
  214. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal_docs/gen_cli_docs.py +0 -0
  215. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal_docs/gen_cli_docs_main.py +0 -0
  216. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal_docs/gen_reference_docs.py +0 -0
  217. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal_docs/gen_reference_docs_main.py +0 -0
  218. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal_docs/mdmd/__init__.py +0 -0
  219. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal_docs/mdmd/mdmd.py +0 -0
  220. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal_docs/mdmd/signatures.py +0 -0
  221. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal_docs/mdmd/types.py +0 -0
  222. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal_docs/reference_intro.md +0 -0
  223. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal_proto/__init__.py +0 -0
  224. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal_proto/api_grpc.py +0 -0
  225. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal_proto/api_pb2_grpc.py +0 -0
  226. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal_proto/api_pb2_grpc.pyi +0 -0
  227. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal_proto/modal_api_grpc.py +0 -0
  228. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal_proto/py.typed +0 -0
  229. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal_proto/task_command_router_grpc.py +0 -0
  230. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal_proto/task_command_router_pb2.py +0 -0
  231. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal_proto/task_command_router_pb2.pyi +0 -0
  232. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal_proto/task_command_router_pb2_grpc.py +0 -0
  233. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal_proto/task_command_router_pb2_grpc.pyi +0 -0
  234. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/modal_version/__main__.py +0 -0
  235. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/pyproject.toml +0 -0
  236. {modal-1.5.4.dev16 → modal-1.5.4.dev17}/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.dev17
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.dev17",
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.dev17",
211
211
  ):
212
212
  """mdmd:hidden
213
213
  The Modal client object is not intended to be instantiated directly by users.
@@ -546,7 +546,7 @@ class Function(
546
546
 
547
547
  _call_generator: ___call_generator_spec
548
548
 
549
- class __remote_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER]):
549
+ class __remote_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
550
550
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER:
551
551
  """Calls the function remotely, executing it with the given arguments and returning the execution's result.
552
552
 
@@ -571,7 +571,7 @@ class Function(
571
571
  """
572
572
  ...
573
573
 
574
- remote: __remote_spec[modal._functions.P, modal._functions.ReturnType]
574
+ remote: __remote_spec[modal._functions.ReturnType, modal._functions.P]
575
575
 
576
576
  class __remote_gen_spec(typing_extensions.Protocol):
577
577
  def __call__(self, /, *args, **kwargs) -> typing.Generator[typing.Any, None, None]:
@@ -621,7 +621,7 @@ class Function(
621
621
  """
622
622
  ...
623
623
 
624
- class ___experimental_spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER]):
624
+ class ___experimental_spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
625
625
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]:
626
626
  """[Experimental] Calls the function with the given arguments, without waiting for the results.
627
627
 
@@ -654,7 +654,7 @@ class Function(
654
654
  """
655
655
  ...
656
656
 
657
- _experimental_spawn: ___experimental_spawn_spec[modal._functions.P, modal._functions.ReturnType]
657
+ _experimental_spawn: ___experimental_spawn_spec[modal._functions.ReturnType, modal._functions.P]
658
658
 
659
659
  class ___spawn_map_inner_spec(typing_extensions.Protocol[P_INNER]):
660
660
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> None: ...
@@ -662,7 +662,7 @@ class Function(
662
662
 
663
663
  _spawn_map_inner: ___spawn_map_inner_spec[modal._functions.P]
664
664
 
665
- class __spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER]):
665
+ class __spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
666
666
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]:
667
667
  """Calls the function with the given arguments, without waiting for the results.
668
668
 
@@ -695,7 +695,7 @@ class Function(
695
695
  """
696
696
  ...
697
697
 
698
- spawn: __spawn_spec[modal._functions.P, modal._functions.ReturnType]
698
+ spawn: __spawn_spec[modal._functions.ReturnType, modal._functions.P]
699
699
 
700
700
  def get_raw_f(self) -> collections.abc.Callable[..., typing.Any]:
701
701
  """Return the inner Python object wrapped by this Modal Function.
@@ -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.dev17
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License-Expression: Apache-2.0