modal 1.6.4.dev2__tar.gz → 1.6.4.dev3__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 (250) hide show
  1. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/PKG-INFO +1 -1
  2. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_runtime/task_lifecycle_manager.py +23 -2
  3. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_runtime/task_lifecycle_manager.pyi +6 -0
  4. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/cli/image.py +119 -1
  5. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/client.pyi +2 -2
  6. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/config.py +5 -7
  7. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/functions.pyi +6 -6
  8. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/runner.py +10 -7
  9. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/runner.pyi +5 -0
  10. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal.egg-info/PKG-INFO +1 -1
  11. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal_proto/api_pb2.py +1398 -1398
  12. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal_proto/api_pb2.pyi +4 -1
  13. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal_version/__init__.py +1 -1
  14. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/pyproject.toml +0 -1
  15. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/LICENSE +0 -0
  16. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/README.md +0 -0
  17. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/__init__.py +0 -0
  18. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/__main__.py +0 -0
  19. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_billing.py +0 -0
  20. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_cluster.py +0 -0
  21. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_cluster.pyi +0 -0
  22. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_container_entrypoint.py +0 -0
  23. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_environments.py +0 -0
  24. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_function_variants.py +0 -0
  25. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_functions.py +0 -0
  26. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_grpc_client.py +0 -0
  27. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_image.py +0 -0
  28. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_ipython.py +0 -0
  29. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_load_context.py +0 -0
  30. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_location.py +0 -0
  31. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_logs.py +0 -0
  32. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_logs_manager.py +0 -0
  33. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_logs_manager.pyi +0 -0
  34. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_metrics.py +0 -0
  35. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_metrics.pyi +0 -0
  36. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_object.py +0 -0
  37. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_outbound_policy.py +0 -0
  38. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_outbound_policy.pyi +0 -0
  39. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_output/__init__.py +0 -0
  40. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_output/manager.py +0 -0
  41. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_output/pty.py +0 -0
  42. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_output/rich.py +0 -0
  43. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_output/status.py +0 -0
  44. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_partial_function.py +0 -0
  45. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_resolver.py +0 -0
  46. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_resources.py +0 -0
  47. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_runtime/__init__.py +0 -0
  48. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_runtime/asgi.py +0 -0
  49. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_runtime/container_io_manager.py +0 -0
  50. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_runtime/container_io_manager.pyi +0 -0
  51. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_runtime/execution_context.py +0 -0
  52. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_runtime/execution_context.pyi +0 -0
  53. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_runtime/gpu_memory_snapshot.py +0 -0
  54. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_runtime/telemetry.py +0 -0
  55. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_runtime/user_code_event_loop.py +0 -0
  56. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_runtime/user_code_imports.py +0 -0
  57. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_serialization.py +0 -0
  58. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_server.py +0 -0
  59. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_server.pyi +0 -0
  60. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_supports_logs.py +0 -0
  61. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_traceback.py +0 -0
  62. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_tunnel.py +0 -0
  63. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_tunnel.pyi +0 -0
  64. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_type_manager.py +0 -0
  65. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_utils/__init__.py +0 -0
  66. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_utils/app_utils.py +0 -0
  67. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_utils/async_utils.py +0 -0
  68. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_utils/auth_token_manager.py +0 -0
  69. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_utils/blob_utils.py +0 -0
  70. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_utils/browser_utils.py +0 -0
  71. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_utils/bytes_io_segment_payload.py +0 -0
  72. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_utils/curl_utils.py +0 -0
  73. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_utils/deprecation.py +0 -0
  74. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_utils/display_utils.py +0 -0
  75. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_utils/docker_utils.py +0 -0
  76. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_utils/function_utils.py +0 -0
  77. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_utils/git_utils.py +0 -0
  78. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_utils/grpc_testing.py +0 -0
  79. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_utils/grpc_utils.py +0 -0
  80. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_utils/hash_utils.py +0 -0
  81. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_utils/http_utils.py +0 -0
  82. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_utils/idle_countdown.py +0 -0
  83. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_utils/jwt_utils.py +0 -0
  84. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_utils/logger.py +0 -0
  85. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_utils/mount_utils.py +0 -0
  86. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_utils/name_utils.py +0 -0
  87. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_utils/oauth.py +0 -0
  88. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_utils/package_utils.py +0 -0
  89. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_utils/pattern_utils.py +0 -0
  90. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_utils/proxy_support.py +0 -0
  91. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_utils/rand_pb_testing.py +0 -0
  92. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_utils/sandbox_fs_utils.py +0 -0
  93. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_utils/shell_utils.py +0 -0
  94. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_utils/time_utils.py +0 -0
  95. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_vendor/__init__.py +0 -0
  96. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_vendor/a2wsgi_wsgi.py +0 -0
  97. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_vendor/cloudpickle.py +0 -0
  98. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_vendor/tblib.py +0 -0
  99. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_vendor/version.py +0 -0
  100. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_watcher.py +0 -0
  101. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/_workspace.py +0 -0
  102. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/app.py +0 -0
  103. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/app.pyi +0 -0
  104. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/billing.py +0 -0
  105. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/billing.pyi +0 -0
  106. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/builder/2023.12.312.txt +0 -0
  107. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/builder/2023.12.txt +0 -0
  108. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/builder/2024.04.txt +0 -0
  109. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/builder/2024.10.txt +0 -0
  110. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/builder/2025.06.txt +0 -0
  111. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/builder/2026.10.txt +0 -0
  112. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/builder/PREVIEW.txt +0 -0
  113. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/builder/README.md +0 -0
  114. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/builder/base-images.json +0 -0
  115. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/call_graph.py +0 -0
  116. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/cli/__init__.py +0 -0
  117. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/cli/_download.py +0 -0
  118. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/cli/_help.py +0 -0
  119. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/cli/_logs.py +0 -0
  120. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/cli/_stats.py +0 -0
  121. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/cli/_traceback.py +0 -0
  122. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/cli/app.py +0 -0
  123. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/cli/billing.py +0 -0
  124. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/cli/changelog.py +0 -0
  125. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/cli/config.py +0 -0
  126. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/cli/container.py +0 -0
  127. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/cli/curl.py +0 -0
  128. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/cli/dashboard.py +0 -0
  129. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/cli/dict.py +0 -0
  130. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/cli/endpoint.py +0 -0
  131. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/cli/entry_point.py +0 -0
  132. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/cli/environment.py +0 -0
  133. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/cli/function.py +0 -0
  134. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/cli/import_refs.py +0 -0
  135. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/cli/logo.py +0 -0
  136. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/cli/network_file_system.py +0 -0
  137. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/cli/profile.py +0 -0
  138. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/cli/queues.py +0 -0
  139. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/cli/run.py +0 -0
  140. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/cli/secret.py +0 -0
  141. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/cli/selector.py +0 -0
  142. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/cli/server.py +0 -0
  143. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/cli/shell.py +0 -0
  144. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/cli/skills.py +0 -0
  145. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/cli/token.py +0 -0
  146. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/cli/utils.py +0 -0
  147. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/cli/volume.py +0 -0
  148. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/cli/workspace.py +0 -0
  149. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/client.py +0 -0
  150. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/cloud_bucket_mount.py +0 -0
  151. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/cloud_bucket_mount.pyi +0 -0
  152. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/cls.py +0 -0
  153. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/cls.pyi +0 -0
  154. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/cluster.py +0 -0
  155. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/cluster.pyi +0 -0
  156. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/container_process.py +0 -0
  157. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/container_process.pyi +0 -0
  158. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/dict.py +0 -0
  159. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/dict.pyi +0 -0
  160. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/environments.py +0 -0
  161. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/environments.pyi +0 -0
  162. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/exception.py +0 -0
  163. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/experimental/__init__.py +0 -0
  164. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/experimental/_flash_container_entry.py +0 -0
  165. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/experimental/flash.py +0 -0
  166. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/experimental/flash.pyi +0 -0
  167. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/experimental/flash_server.py +0 -0
  168. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/experimental/flash_server.pyi +0 -0
  169. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/experimental/ipython.py +0 -0
  170. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/file_pattern_matcher.py +0 -0
  171. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/functions.py +0 -0
  172. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/image.py +0 -0
  173. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/image.pyi +0 -0
  174. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/io_streams.py +0 -0
  175. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/io_streams.pyi +0 -0
  176. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/mount.py +0 -0
  177. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/mount.pyi +0 -0
  178. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/network_file_system.py +0 -0
  179. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/network_file_system.pyi +0 -0
  180. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/object.py +0 -0
  181. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/object.pyi +0 -0
  182. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/output.py +0 -0
  183. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/parallel_map.py +0 -0
  184. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/parallel_map.pyi +0 -0
  185. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/partial_function.py +0 -0
  186. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/partial_function.pyi +0 -0
  187. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/proxy.py +0 -0
  188. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/proxy.pyi +0 -0
  189. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/py.typed +0 -0
  190. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/queue.py +0 -0
  191. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/queue.pyi +0 -0
  192. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/retries.py +0 -0
  193. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/running_app.py +0 -0
  194. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/sandbox/__init__.py +0 -0
  195. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/sandbox/_common.py +0 -0
  196. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/sandbox/_filesystem.py +0 -0
  197. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/sandbox/_impl_persistent.py +0 -0
  198. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/sandbox/_impl_v1.py +0 -0
  199. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/sandbox/_impl_v2.py +0 -0
  200. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/sandbox/_sandbox.py +0 -0
  201. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/sandbox/_sidecar.py +0 -0
  202. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/sandbox/_snapshot.py +0 -0
  203. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/sandbox/_task_command_router_client.py +0 -0
  204. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/sandbox/sandbox.py +0 -0
  205. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/sandbox/sandbox.pyi +0 -0
  206. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/schedule.py +0 -0
  207. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/scheduler_placement.py +0 -0
  208. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/secret.py +0 -0
  209. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/secret.pyi +0 -0
  210. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/server.py +0 -0
  211. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/server.pyi +0 -0
  212. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/serving.py +0 -0
  213. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/serving.pyi +0 -0
  214. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/skills/modal/SKILL.md +0 -0
  215. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/stream_type.py +0 -0
  216. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/token_flow.py +0 -0
  217. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/token_flow.pyi +0 -0
  218. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/types.py +0 -0
  219. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/volume.py +0 -0
  220. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/volume.pyi +0 -0
  221. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/workspace.py +0 -0
  222. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal/workspace.pyi +0 -0
  223. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal.egg-info/SOURCES.txt +0 -0
  224. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal.egg-info/dependency_links.txt +0 -0
  225. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal.egg-info/entry_points.txt +0 -0
  226. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal.egg-info/requires.txt +0 -0
  227. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal.egg-info/top_level.txt +0 -0
  228. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal_docs/__init__.py +0 -0
  229. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal_docs/gen_cli_docs.py +0 -0
  230. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal_docs/gen_cli_docs_main.py +0 -0
  231. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal_docs/gen_reference_docs.py +0 -0
  232. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal_docs/gen_reference_docs_main.py +0 -0
  233. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal_docs/mdmd/__init__.py +0 -0
  234. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal_docs/mdmd/mdmd.py +0 -0
  235. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal_docs/mdmd/signatures.py +0 -0
  236. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal_docs/mdmd/types.py +0 -0
  237. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal_docs/reference_intro.md +0 -0
  238. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal_proto/__init__.py +0 -0
  239. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal_proto/api_grpc.py +0 -0
  240. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal_proto/api_pb2_grpc.py +0 -0
  241. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal_proto/api_pb2_grpc.pyi +0 -0
  242. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal_proto/modal_api_grpc.py +0 -0
  243. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal_proto/py.typed +0 -0
  244. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal_proto/task_command_router_grpc.py +0 -0
  245. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal_proto/task_command_router_pb2.py +0 -0
  246. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal_proto/task_command_router_pb2.pyi +0 -0
  247. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal_proto/task_command_router_pb2_grpc.py +0 -0
  248. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal_proto/task_command_router_pb2_grpc.pyi +0 -0
  249. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/modal_version/__main__.py +0 -0
  250. {modal-1.6.4.dev2 → modal-1.6.4.dev3}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.6.4.dev2
3
+ Version: 1.6.4.dev3
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License-Expression: Apache-2.0
@@ -25,9 +25,19 @@ from modal._utils.blob_utils import format_blob_data
25
25
  from modal._utils.grpc_utils import Retry
26
26
  from modal._utils.package_utils import parse_major_minor_version
27
27
  from modal.client import _Client
28
- from modal.config import config, logger
28
+ from modal.config import _env_var_name, config, logger
29
29
  from modal_proto import api_pb2
30
30
 
31
+ SPEC_ENVIRON_PATH: str = "/proc/gvisor/spec_environ"
32
+
33
+
34
+ def _read_spec_environ() -> dict[str, str]:
35
+ path = Path(SPEC_ENVIRON_PATH)
36
+ if not path.exists():
37
+ return {}
38
+ entries = (entry.partition("=") for entry in path.read_text("utf8").split("\0"))
39
+ return {key: value for key, sep, value in entries if sep}
40
+
31
41
 
32
42
  class UserException(Exception):
33
43
  """Used to shut down the task gracefully."""
@@ -42,6 +52,7 @@ class _TaskLifecycleManager:
42
52
  checkpoint_id: str | None
43
53
  _client: _Client
44
54
  _cuda_checkpoint_session: gpu_memory_snapshot.CudaCheckpointSession | None
55
+ _snapshot_spec_environ: dict[str, str]
45
56
 
46
57
  def _init(
47
58
  self,
@@ -57,6 +68,7 @@ class _TaskLifecycleManager:
57
68
  self.checkpoint_id = checkpoint_id
58
69
  self._client = client
59
70
  self._cuda_checkpoint_session = None
71
+ self._snapshot_spec_environ = {}
60
72
 
61
73
  def __new__(
62
74
  cls,
@@ -171,10 +183,18 @@ class _TaskLifecycleManager:
171
183
  setattr(self, key, restored_state[key])
172
184
 
173
185
  # Env vars and global state.
186
+ env_updates = {}
187
+ for key, value in _read_spec_environ().items():
188
+ if self._snapshot_spec_environ.get(key) != value:
189
+ env_updates[key] = value
190
+
191
+ # Values from the restore state take precedence.
174
192
  for key, value in restored_state.items():
175
193
  # Empty string indicates that value does not need to be updated.
176
194
  if value != "":
177
- config.override_locally(key, value)
195
+ env_updates[_env_var_name(key)] = value
196
+
197
+ os.environ.update(env_updates)
178
198
 
179
199
  # Restore GPU memory.
180
200
  if self.function_def._experimental_enable_gpu_snapshot and self.function_def.resources.gpu_config.gpu_type:
@@ -205,6 +225,7 @@ class _TaskLifecycleManager:
205
225
  self._cuda_checkpoint_session = gpu_memory_snapshot.CudaCheckpointSession()
206
226
  self._cuda_checkpoint_session.checkpoint()
207
227
 
228
+ self._snapshot_spec_environ = _read_spec_environ()
208
229
  await self._client._stub.ContainerCheckpoint(
209
230
  api_pb2.ContainerCheckpointRequest(checkpoint_id=self.checkpoint_id)
210
231
  )
@@ -5,6 +5,8 @@ import synchronicity.combined_types
5
5
  import typing
6
6
  import typing_extensions
7
7
 
8
+ def _read_spec_environ() -> dict[str, str]: ...
9
+
8
10
  class UserException(Exception):
9
11
  """Used to shut down the task gracefully."""
10
12
 
@@ -18,6 +20,7 @@ class _TaskLifecycleManager:
18
20
  checkpoint_id: typing.Optional[str]
19
21
  _client: modal.client._Client
20
22
  _cuda_checkpoint_session: typing.Optional[modal._runtime.gpu_memory_snapshot.CudaCheckpointSession]
23
+ _snapshot_spec_environ: dict[str, str]
21
24
 
22
25
  def _init(
23
26
  self,
@@ -67,6 +70,7 @@ class TaskLifecycleManager:
67
70
  checkpoint_id: typing.Optional[str]
68
71
  _client: modal.client.Client
69
72
  _cuda_checkpoint_session: typing.Optional[modal._runtime.gpu_memory_snapshot.CudaCheckpointSession]
73
+ _snapshot_spec_environ: dict[str, str]
70
74
 
71
75
  def __init__(self, /, *args, **kwargs):
72
76
  """Initialize self. See help(type(self)) for accurate signature."""
@@ -136,3 +140,5 @@ def check_fastapi_pydantic_compatibility(exc: ImportError) -> None:
136
140
  building an image that specifies a more recent version only for pydantic.
137
141
  """
138
142
  ...
143
+
144
+ SPEC_ENVIRON_PATH: str
@@ -4,21 +4,27 @@ from __future__ import annotations
4
4
 
5
5
  import asyncio
6
6
  import json as json_module
7
+ import os
7
8
  from collections.abc import AsyncIterator
8
9
  from typing import Optional
9
10
 
10
11
  import click
12
+ from rich.syntax import Syntax
11
13
 
12
14
  from modal._environments import ensure_env
13
- from modal._image import _upgrade_image_name
15
+ from modal._image import _Image, _infer_registry_auth_type, _upgrade_image_name
14
16
  from modal._logs_manager import _resolve_source
15
17
  from modal._utils.async_utils import synchronizer
16
18
  from modal._utils.time_utils import timestamp_to_localized_str
19
+ from modal.app import _App
17
20
  from modal.cli.utils import display_table, env_option
18
21
  from modal.client import _Client
19
22
  from modal.config import config
23
+ from modal.exception import InvalidError
20
24
  from modal.image import Image
21
25
  from modal.output import OutputManager
26
+ from modal.runner import _run_app
27
+ from modal.secret import _Secret
22
28
  from modal_proto import api_pb2
23
29
 
24
30
  from ._help import ModalGroup
@@ -36,6 +42,118 @@ def _print_result_summary(count: int) -> None:
36
42
  OutputManager.get().print(f"Showing {count} {result_label}")
37
43
 
38
44
 
45
+ async def _registry_secret(
46
+ secret_name: Optional[str], secret_vars: Optional[str], env: str
47
+ ) -> tuple[Optional[_Secret], set[str]]:
48
+ if secret_name and secret_vars:
49
+ raise click.UsageError("--registry-secret and --registry-secret-from-env cannot be used together.")
50
+ if secret_name:
51
+ secret = _Secret.from_name(secret_name, environment_name=env)
52
+ return secret, await secret._get_keys()
53
+ keys = [key.strip() for key in (secret_vars or "").split(",") if key.strip()]
54
+ if not keys:
55
+ return None, set()
56
+ return _Secret.from_local_environ(keys), set(keys)
57
+
58
+
59
+ @image_cli.command("build", no_args_is_help=True)
60
+ @click.argument("context_dir", metavar="CONTEXT_DIR")
61
+ @click.option(
62
+ "-t",
63
+ "--name",
64
+ "name",
65
+ metavar="[ENV/]NAME[:TAG]",
66
+ required=True,
67
+ help="Name to publish the Image as, e.g. `my-image`, `my-image:v2`, or `my-env/my-image`.",
68
+ )
69
+ @click.option(
70
+ "-f",
71
+ "--file",
72
+ "dockerfile",
73
+ type=click.Path(exists=True, dir_okay=False),
74
+ default=None,
75
+ help="Path to the Dockerfile. Defaults to `CONTEXT_DIR/Dockerfile`.",
76
+ )
77
+ @click.option(
78
+ "--registry-secret",
79
+ "registry_secret_name",
80
+ metavar="SECRET_NAME",
81
+ default=None,
82
+ help="Name of a Secret with credentials for pulling the base image from a private registry.",
83
+ )
84
+ @click.option(
85
+ "--registry-secret-from-env",
86
+ "registry_secret_vars",
87
+ default=None,
88
+ metavar="VAR[,VAR...]",
89
+ help=(
90
+ "Comma-separated local environment variable names holding registry credentials. "
91
+ "Cannot be combined with --registry-secret."
92
+ ),
93
+ )
94
+ @click.option("--force-build", is_flag=True, help="Rebuild every layer of the Image, ignoring cached builds.")
95
+ @env_option
96
+ @synchronizer.create_blocking
97
+ async def build(
98
+ context_dir: str,
99
+ name: str,
100
+ dockerfile: Optional[str],
101
+ registry_secret_name: Optional[str],
102
+ registry_secret_vars: Optional[str],
103
+ force_build: bool,
104
+ env: Optional[str],
105
+ ) -> None:
106
+ """Build an Image from a Dockerfile and publish it as NAME.
107
+
108
+ CONTEXT_DIR is the build context used to resolve relative COPY paths. Use `.` for the current directory.
109
+
110
+ NAME defaults to the `latest` tag. `--env` sets the environment the build runs in and where
111
+ `--registry-secret` is looked up. The Image is published into that environment unless NAME has an
112
+ environment prefix, e.g. `my-env/my-image`.
113
+
114
+ Examples:
115
+
116
+ ```
117
+ modal image build -t my-image .
118
+ modal image build --name my-image:v2 -f docker/Dockerfile .
119
+ modal image build -t my-env/my-image .
120
+ modal image build -t my-image --registry-secret my-registry-creds .
121
+ modal image build -t my-image --registry-secret-from-env REGISTRY_USERNAME,REGISTRY_PASSWORD .
122
+ ```
123
+ """
124
+ if not os.path.isdir(context_dir):
125
+ raise click.UsageError(f"CONTEXT_DIR {context_dir!r} is not a directory.")
126
+ if dockerfile is None:
127
+ dockerfile = os.path.join(context_dir, "Dockerfile")
128
+ if not os.path.isfile(dockerfile):
129
+ raise click.UsageError(f"No Dockerfile found at {dockerfile}. Use --file to specify one.")
130
+ env = ensure_env(env)
131
+ try:
132
+ tag = _upgrade_image_name(name, fallback_environment_name=env)
133
+ except InvalidError as exc:
134
+ raise click.UsageError(str(exc))
135
+
136
+ secret, keys = await _registry_secret(registry_secret_name, registry_secret_vars, env)
137
+ if secret is not None:
138
+ # Fail before creating the app; from_dockerfile runs the same check during the build
139
+ try:
140
+ _infer_registry_auth_type(keys)
141
+ except InvalidError as exc:
142
+ raise click.UsageError(str(exc)) from exc
143
+ image = _Image.from_dockerfile(dockerfile, context_dir=context_dir, registry_secret=secret, force_build=force_build)
144
+ app = _App("modal-image-build")
145
+ # Only show the Image build output, which includes its logs
146
+ async with _run_app(app, environment_name=env, stream_output=False):
147
+ await image.build(app)
148
+ await image.publish(tag)
149
+
150
+ output_mgr = OutputManager.get()
151
+ output_mgr.step_completed(f"Image built: [bold]{image.object_id}[/bold]")
152
+ output_mgr.step_completed(f"Image published as [bold magenta]{tag}[/bold magenta]! 🎉")
153
+ output_mgr.print("\nUse it with:\n")
154
+ output_mgr.print(Syntax(f'modal.Image.from_name("{tag}")', "python"))
155
+
156
+
39
157
  @image_cli.command("logs", no_args_is_help=True)
40
158
  @click.argument("image_id")
41
159
  @click.option(
@@ -87,7 +87,7 @@ class _Client:
87
87
  server_url: str,
88
88
  client_type: int,
89
89
  credentials: typing.Optional[tuple[str, str]],
90
- version: str = "1.6.4.dev2",
90
+ version: str = "1.6.4.dev3",
91
91
  *,
92
92
  oauth_credentials: typing.Optional[_OAuthCredentials] = None,
93
93
  ):
@@ -304,7 +304,7 @@ class Client:
304
304
  server_url: str,
305
305
  client_type: int,
306
306
  credentials: typing.Optional[tuple[str, str]],
307
- version: str = "1.6.4.dev2",
307
+ version: str = "1.6.4.dev3",
308
308
  *,
309
309
  oauth_credentials: typing.Optional[_OAuthCredentials] = None,
310
310
  ):
@@ -414,6 +414,10 @@ _SETTINGS = {
414
414
  }
415
415
 
416
416
 
417
+ def _env_var_name(key: str) -> str:
418
+ return f"MODAL_{key.upper()}" if key in _SETTINGS else key.upper()
419
+
420
+
417
421
  class Config:
418
422
  """Singleton that holds configuration used by Modal internally."""
419
423
 
@@ -474,13 +478,7 @@ class Config:
474
478
  # Override setting in this process by overriding environment variable for the setting
475
479
  #
476
480
  # Does NOT write back to settings file etc.
477
- try:
478
- self.get(key)
479
- os.environ["MODAL_" + key.upper()] = value
480
- except KeyError:
481
- # Override env vars not available in config, e.g. NVIDIA_VISIBLE_DEVICES.
482
- # This is used for restoring env vars from a memory snapshot.
483
- os.environ[key.upper()] = value
481
+ os.environ[_env_var_name(key)] = value
484
482
 
485
483
  def __getitem__(self, key):
486
484
  return self.get(key)
@@ -619,7 +619,7 @@ class Function(
619
619
 
620
620
  _call_generator: ___call_generator_spec
621
621
 
622
- class __remote_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
622
+ class __remote_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER]):
623
623
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER:
624
624
  """Calls the function remotely, executing it with the given arguments and returning the execution's result.
625
625
 
@@ -644,7 +644,7 @@ class Function(
644
644
  """
645
645
  ...
646
646
 
647
- remote: __remote_spec[modal._functions.ReturnType, modal._functions.P]
647
+ remote: __remote_spec[modal._functions.P, modal._functions.ReturnType]
648
648
 
649
649
  class __remote_gen_spec(typing_extensions.Protocol):
650
650
  def __call__(self, /, *args, **kwargs) -> typing.Generator[typing.Any, None, None]:
@@ -694,7 +694,7 @@ class Function(
694
694
  """
695
695
  ...
696
696
 
697
- class ___experimental_spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
697
+ class ___experimental_spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER]):
698
698
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]:
699
699
  """[Experimental] Calls the function with the given arguments, without waiting for the results.
700
700
 
@@ -727,7 +727,7 @@ class Function(
727
727
  """
728
728
  ...
729
729
 
730
- _experimental_spawn: ___experimental_spawn_spec[modal._functions.ReturnType, modal._functions.P]
730
+ _experimental_spawn: ___experimental_spawn_spec[modal._functions.P, modal._functions.ReturnType]
731
731
 
732
732
  class ___spawn_map_inner_spec(typing_extensions.Protocol[P_INNER]):
733
733
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> None: ...
@@ -735,7 +735,7 @@ class Function(
735
735
 
736
736
  _spawn_map_inner: ___spawn_map_inner_spec[modal._functions.P]
737
737
 
738
- class __spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
738
+ class __spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER]):
739
739
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]:
740
740
  """Calls the function with the given arguments, without waiting for the results.
741
741
 
@@ -768,7 +768,7 @@ class Function(
768
768
  """
769
769
  ...
770
770
 
771
- spawn: __spawn_spec[modal._functions.ReturnType, modal._functions.P]
771
+ spawn: __spawn_spec[modal._functions.P, modal._functions.ReturnType]
772
772
 
773
773
  @property
774
774
  def _raw_f_(self) -> collections.abc.Callable[..., typing.Any]: ...
@@ -25,6 +25,7 @@ from modal_proto import api_pb2
25
25
  from ._environments import _get_environment_cached
26
26
  from ._functions import _Function
27
27
  from ._object import _get_environment_name, _Object
28
+ from ._output.manager import _DISABLED_OUTPUT_MANAGER
28
29
  from ._output.pty import get_app_logs_loop, get_pty_info
29
30
  from ._resolver import Resolver
30
31
  from ._traceback import print_server_warnings, traceback_contains_remote_call
@@ -139,6 +140,7 @@ async def _create_all_objects(
139
140
  running_app: RunningApp,
140
141
  local_app_state: "modal.app._LocalAppState",
141
142
  load_context: LoadContext,
143
+ output_mgr: OutputManager,
142
144
  ) -> None:
143
145
  """Create objects that have been defined but not created on the server.
144
146
 
@@ -149,7 +151,6 @@ async def _create_all_objects(
149
151
  tc = load_context.task_context
150
152
 
151
153
  resolver = Resolver()
152
- output_mgr = OutputManager.get()
153
154
  with output_mgr.display_object_tree():
154
155
  # Get current objects, and reset all objects.
155
156
  # Only reuse an existing object id when its type matches the object now being
@@ -377,6 +378,7 @@ async def _run_app(
377
378
  environment_name: str | None = None,
378
379
  interactive: bool = False,
379
380
  deployment_strategy: str = "rolling",
381
+ stream_output: bool = True,
380
382
  ) -> AsyncGenerator["modal.app._App", None]:
381
383
  """mdmd:hidden"""
382
384
  if modal._runtime.execution_context._in_import_context():
@@ -409,7 +411,8 @@ async def _run_app(
409
411
  app._description = __main__.__name__
410
412
 
411
413
  app_state = api_pb2.APP_STATE_DETACHED if detach else api_pb2.APP_STATE_EPHEMERAL
412
- output_mgr = OutputManager.get()
414
+ # stream_output covers the App's own status, spinner, and log stream; objects print their own output
415
+ output_mgr = OutputManager.get() if stream_output else _DISABLED_OUTPUT_MANAGER
413
416
 
414
417
  if interactive and not output_mgr.is_enabled:
415
418
  msg = "Interactive mode requires output to be enabled. (Use the the `modal.enable_output()` context manager.)"
@@ -454,7 +457,7 @@ async def _run_app(
454
457
 
455
458
  try:
456
459
  # Create all members
457
- await _create_all_objects(running_app, local_app_state, load_context)
460
+ await _create_all_objects(running_app, local_app_state, load_context, output_mgr)
458
461
 
459
462
  # Publish the app
460
463
  await _publish_app(
@@ -467,7 +470,7 @@ async def _run_app(
467
470
  )
468
471
  except asyncio.CancelledError as e:
469
472
  # this typically happens on sigint/ctrl-C during setup (the KeyboardInterrupt happens in the main thread)
470
- OutputManager.get().print("Aborting app initialization...\n")
473
+ output_mgr.print("Aborting app initialization...\n")
471
474
  await _status_based_disconnect(load_context.client, running_app.app_id, e)
472
475
  raise
473
476
  except BaseException as e:
@@ -541,7 +544,7 @@ async def _run_app(
541
544
 
542
545
  # Print completion message if output is still enabled (it may have been disabled during PTY mode)
543
546
  # Re-fetch the output manager in case it was disabled
544
- output_mgr = OutputManager.get()
547
+ output_mgr = OutputManager.get() if stream_output else _DISABLED_OUTPUT_MANAGER
545
548
  if output_mgr.is_enabled:
546
549
  output_mgr.step_completed(
547
550
  f"App completed. [grey70]View run at [underline]{running_app.app_page_url}[/underline][/grey70]"
@@ -564,7 +567,7 @@ async def _serve_update(
564
567
  # Create objects with a TaskContext for proper exception handling
565
568
  async with TaskContext() as tc:
566
569
  await load_context.in_place_upgrade(task_context=tc, app_id=running_app.app_id)
567
- await _create_all_objects(running_app, local_app_state, load_context)
570
+ await _create_all_objects(running_app, local_app_state, load_context, OutputManager.get())
568
571
 
569
572
  # Publish the updated app
570
573
  await _publish_app(
@@ -665,7 +668,7 @@ async def _deploy_app(
665
668
 
666
669
  try:
667
670
  # Create all members
668
- await _create_all_objects(running_app, local_app_state, root_load_context)
671
+ await _create_all_objects(running_app, local_app_state, root_load_context, OutputManager.get())
669
672
 
670
673
  commit_info = None
671
674
  try:
@@ -1,4 +1,5 @@
1
1
  import modal._load_context
2
+ import modal._output.manager
2
3
  import modal.app
3
4
  import modal.client
4
5
  import modal.running_app
@@ -31,6 +32,7 @@ async def _create_all_objects(
31
32
  running_app: modal.running_app.RunningApp,
32
33
  local_app_state: modal.app._LocalAppState,
33
34
  load_context: modal._load_context.LoadContext,
35
+ output_mgr: modal._output.manager.OutputManager,
34
36
  ) -> None:
35
37
  """Create objects that have been defined but not created on the server.
36
38
 
@@ -82,6 +84,7 @@ def _run_app(
82
84
  environment_name: typing.Optional[str] = None,
83
85
  interactive: bool = False,
84
86
  deployment_strategy: str = "rolling",
87
+ stream_output: bool = True,
85
88
  ) -> typing.AsyncContextManager[modal.app._App]:
86
89
  """mdmd:hidden"""
87
90
  ...
@@ -185,6 +188,7 @@ class __run_app_spec(typing_extensions.Protocol):
185
188
  environment_name: typing.Optional[str] = None,
186
189
  interactive: bool = False,
187
190
  deployment_strategy: str = "rolling",
191
+ stream_output: bool = True,
188
192
  ) -> synchronicity.combined_types.AsyncAndBlockingContextManager[modal.app.App]:
189
193
  """mdmd:hidden"""
190
194
  ...
@@ -200,6 +204,7 @@ class __run_app_spec(typing_extensions.Protocol):
200
204
  environment_name: typing.Optional[str] = None,
201
205
  interactive: bool = False,
202
206
  deployment_strategy: str = "rolling",
207
+ stream_output: bool = True,
203
208
  ) -> typing.AsyncContextManager[modal.app.App]:
204
209
  """mdmd:hidden"""
205
210
  ...
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.6.4.dev2
3
+ Version: 1.6.4.dev3
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License-Expression: Apache-2.0