modal 1.1.5.dev49__tar.gz → 1.1.5.dev51__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.

Potentially problematic release.


This version of modal might be problematic. Click here for more details.

Files changed (196) hide show
  1. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/PKG-INFO +1 -1
  2. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_output.py +27 -12
  3. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/client.pyi +2 -2
  4. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/functions.pyi +6 -6
  5. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal.egg-info/PKG-INFO +1 -1
  6. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal_proto/api.proto +9 -0
  7. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal_proto/api_grpc.py +16 -0
  8. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal_proto/api_pb2.py +671 -651
  9. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal_proto/api_pb2.pyi +27 -0
  10. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal_proto/api_pb2_grpc.py +33 -0
  11. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal_proto/api_pb2_grpc.pyi +10 -0
  12. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal_proto/modal_api_grpc.py +1 -0
  13. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal_version/__init__.py +1 -1
  14. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/LICENSE +0 -0
  15. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/README.md +0 -0
  16. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/__init__.py +0 -0
  17. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/__main__.py +0 -0
  18. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_clustered_functions.py +0 -0
  19. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_clustered_functions.pyi +0 -0
  20. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_container_entrypoint.py +0 -0
  21. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_functions.py +0 -0
  22. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_ipython.py +0 -0
  23. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_location.py +0 -0
  24. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_object.py +0 -0
  25. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_partial_function.py +0 -0
  26. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_pty.py +0 -0
  27. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_resolver.py +0 -0
  28. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_resources.py +0 -0
  29. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_runtime/__init__.py +0 -0
  30. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_runtime/asgi.py +0 -0
  31. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_runtime/container_io_manager.py +0 -0
  32. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_runtime/container_io_manager.pyi +0 -0
  33. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_runtime/execution_context.py +0 -0
  34. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_runtime/execution_context.pyi +0 -0
  35. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_runtime/gpu_memory_snapshot.py +0 -0
  36. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_runtime/telemetry.py +0 -0
  37. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_runtime/user_code_imports.py +0 -0
  38. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_serialization.py +0 -0
  39. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_traceback.py +0 -0
  40. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_tunnel.py +0 -0
  41. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_tunnel.pyi +0 -0
  42. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_type_manager.py +0 -0
  43. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_utils/__init__.py +0 -0
  44. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_utils/app_utils.py +0 -0
  45. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_utils/async_utils.py +0 -0
  46. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_utils/auth_token_manager.py +0 -0
  47. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_utils/blob_utils.py +0 -0
  48. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_utils/bytes_io_segment_payload.py +0 -0
  49. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_utils/deprecation.py +0 -0
  50. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_utils/docker_utils.py +0 -0
  51. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_utils/function_utils.py +0 -0
  52. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_utils/git_utils.py +0 -0
  53. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_utils/grpc_testing.py +0 -0
  54. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_utils/grpc_utils.py +0 -0
  55. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_utils/hash_utils.py +0 -0
  56. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_utils/http_utils.py +0 -0
  57. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_utils/jwt_utils.py +0 -0
  58. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_utils/logger.py +0 -0
  59. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_utils/mount_utils.py +0 -0
  60. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_utils/name_utils.py +0 -0
  61. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_utils/package_utils.py +0 -0
  62. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_utils/pattern_utils.py +0 -0
  63. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_utils/rand_pb_testing.py +0 -0
  64. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_utils/shell_utils.py +0 -0
  65. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_utils/time_utils.py +0 -0
  66. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_vendor/__init__.py +0 -0
  67. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_vendor/a2wsgi_wsgi.py +0 -0
  68. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_vendor/cloudpickle.py +0 -0
  69. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_vendor/tblib.py +0 -0
  70. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/_watcher.py +0 -0
  71. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/app.py +0 -0
  72. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/app.pyi +0 -0
  73. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/builder/2023.12.312.txt +0 -0
  74. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/builder/2023.12.txt +0 -0
  75. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/builder/2024.04.txt +0 -0
  76. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/builder/2024.10.txt +0 -0
  77. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/builder/2025.06.txt +0 -0
  78. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/builder/PREVIEW.txt +0 -0
  79. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/builder/README.md +0 -0
  80. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/builder/base-images.json +0 -0
  81. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/call_graph.py +0 -0
  82. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/cli/__init__.py +0 -0
  83. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/cli/_download.py +0 -0
  84. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/cli/_traceback.py +0 -0
  85. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/cli/app.py +0 -0
  86. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/cli/cluster.py +0 -0
  87. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/cli/config.py +0 -0
  88. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/cli/container.py +0 -0
  89. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/cli/dict.py +0 -0
  90. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/cli/entry_point.py +0 -0
  91. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/cli/environment.py +0 -0
  92. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/cli/import_refs.py +0 -0
  93. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/cli/launch.py +0 -0
  94. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/cli/network_file_system.py +0 -0
  95. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/cli/profile.py +0 -0
  96. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/cli/programs/__init__.py +0 -0
  97. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/cli/programs/launch_instance_ssh.py +0 -0
  98. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/cli/programs/run_jupyter.py +0 -0
  99. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/cli/programs/run_marimo.py +0 -0
  100. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/cli/programs/vscode.py +0 -0
  101. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/cli/queues.py +0 -0
  102. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/cli/run.py +0 -0
  103. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/cli/secret.py +0 -0
  104. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/cli/token.py +0 -0
  105. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/cli/utils.py +0 -0
  106. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/cli/volume.py +0 -0
  107. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/client.py +0 -0
  108. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/cloud_bucket_mount.py +0 -0
  109. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/cloud_bucket_mount.pyi +0 -0
  110. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/cls.py +0 -0
  111. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/cls.pyi +0 -0
  112. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/config.py +0 -0
  113. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/container_process.py +0 -0
  114. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/container_process.pyi +0 -0
  115. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/dict.py +0 -0
  116. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/dict.pyi +0 -0
  117. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/environments.py +0 -0
  118. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/environments.pyi +0 -0
  119. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/exception.py +0 -0
  120. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/experimental/__init__.py +0 -0
  121. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/experimental/flash.py +0 -0
  122. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/experimental/flash.pyi +0 -0
  123. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/experimental/ipython.py +0 -0
  124. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/file_io.py +0 -0
  125. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/file_io.pyi +0 -0
  126. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/file_pattern_matcher.py +0 -0
  127. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/functions.py +0 -0
  128. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/gpu.py +0 -0
  129. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/image.py +0 -0
  130. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/image.pyi +0 -0
  131. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/io_streams.py +0 -0
  132. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/io_streams.pyi +0 -0
  133. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/mount.py +0 -0
  134. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/mount.pyi +0 -0
  135. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/network_file_system.py +0 -0
  136. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/network_file_system.pyi +0 -0
  137. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/object.py +0 -0
  138. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/object.pyi +0 -0
  139. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/output.py +0 -0
  140. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/parallel_map.py +0 -0
  141. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/parallel_map.pyi +0 -0
  142. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/partial_function.py +0 -0
  143. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/partial_function.pyi +0 -0
  144. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/proxy.py +0 -0
  145. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/proxy.pyi +0 -0
  146. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/py.typed +0 -0
  147. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/queue.py +0 -0
  148. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/queue.pyi +0 -0
  149. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/retries.py +0 -0
  150. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/runner.py +0 -0
  151. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/runner.pyi +0 -0
  152. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/running_app.py +0 -0
  153. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/sandbox.py +0 -0
  154. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/sandbox.pyi +0 -0
  155. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/schedule.py +0 -0
  156. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/scheduler_placement.py +0 -0
  157. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/secret.py +0 -0
  158. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/secret.pyi +0 -0
  159. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/serving.py +0 -0
  160. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/serving.pyi +0 -0
  161. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/snapshot.py +0 -0
  162. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/snapshot.pyi +0 -0
  163. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/stream_type.py +0 -0
  164. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/token_flow.py +0 -0
  165. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/token_flow.pyi +0 -0
  166. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/volume.py +0 -0
  167. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal/volume.pyi +0 -0
  168. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal.egg-info/SOURCES.txt +0 -0
  169. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal.egg-info/dependency_links.txt +0 -0
  170. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal.egg-info/entry_points.txt +0 -0
  171. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal.egg-info/requires.txt +0 -0
  172. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal.egg-info/top_level.txt +0 -0
  173. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal_docs/__init__.py +0 -0
  174. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal_docs/gen_cli_docs.py +0 -0
  175. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal_docs/gen_reference_docs.py +0 -0
  176. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal_docs/mdmd/__init__.py +0 -0
  177. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal_docs/mdmd/mdmd.py +0 -0
  178. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal_docs/mdmd/signatures.py +0 -0
  179. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal_proto/__init__.py +0 -0
  180. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal_proto/modal_options_grpc.py +0 -0
  181. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal_proto/options.proto +0 -0
  182. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal_proto/options_grpc.py +0 -0
  183. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal_proto/options_pb2.py +0 -0
  184. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal_proto/options_pb2.pyi +0 -0
  185. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal_proto/options_pb2_grpc.py +0 -0
  186. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal_proto/options_pb2_grpc.pyi +0 -0
  187. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal_proto/py.typed +0 -0
  188. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal_proto/sandbox_router.proto +0 -0
  189. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal_proto/sandbox_router_grpc.py +0 -0
  190. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal_proto/sandbox_router_pb2.py +0 -0
  191. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal_proto/sandbox_router_pb2.pyi +0 -0
  192. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal_proto/sandbox_router_pb2_grpc.py +0 -0
  193. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal_proto/sandbox_router_pb2_grpc.pyi +0 -0
  194. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/modal_version/__main__.py +0 -0
  195. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/pyproject.toml +0 -0
  196. {modal-1.1.5.dev49 → modal-1.1.5.dev51}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.1.5.dev49
3
+ Version: 1.1.5.dev51
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -35,7 +35,7 @@ from modal._utils.time_utils import timestamp_to_localized_str
35
35
  from modal_proto import api_pb2
36
36
 
37
37
  from ._utils.grpc_utils import RETRYABLE_GRPC_STATUS_CODES, retry_transient_errors
38
- from ._utils.shell_utils import stream_from_stdin
38
+ from ._utils.shell_utils import stream_from_stdin, write_to_fd
39
39
  from .client import _Client
40
40
  from .config import logger
41
41
 
@@ -507,17 +507,32 @@ async def put_pty_content(log: api_pb2.TaskLogs, stdout):
507
507
  # because the progress spinner can't interfere with output.
508
508
 
509
509
  data = log.data.encode("utf-8")
510
- written = 0
511
- n_retries = 0
512
- while written < len(data):
513
- try:
514
- written += stdout.buffer.write(data[written:])
515
- stdout.flush()
516
- except BlockingIOError:
517
- if n_retries >= 5:
518
- raise
519
- n_retries += 1
520
- await asyncio.sleep(0.1)
510
+ # Non-blocking terminals can fill the kernel buffer on output bursts, making flush() raise
511
+ # BlockingIOError (EAGAIN) and appear frozen until a key is pressed (this happened e.g. when
512
+ # printing large data from a pdb breakpoint). If stdout has a real fd, we await a
513
+ # non-blocking fd write (write_to_fd) instead.
514
+ fd = None
515
+ try:
516
+ if hasattr(stdout, "fileno"):
517
+ fd = stdout.fileno()
518
+ except Exception:
519
+ fd = None
520
+
521
+ if fd is not None:
522
+ await write_to_fd(fd, data)
523
+ else:
524
+ # For streams without fileno(), use the normal write/flush path.
525
+ written = 0
526
+ n_retries = 0
527
+ while written < len(data):
528
+ try:
529
+ written += stdout.buffer.write(data[written:])
530
+ stdout.flush()
531
+ except BlockingIOError:
532
+ if n_retries >= 5:
533
+ raise
534
+ n_retries += 1
535
+ await asyncio.sleep(0.1)
521
536
  else:
522
537
  # `stdout` isn't always buffered (e.g. %%capture in Jupyter notebooks redirects it to
523
538
  # io.StringIO).
@@ -33,7 +33,7 @@ class _Client:
33
33
  server_url: str,
34
34
  client_type: int,
35
35
  credentials: typing.Optional[tuple[str, str]],
36
- version: str = "1.1.5.dev49",
36
+ version: str = "1.1.5.dev51",
37
37
  ):
38
38
  """mdmd:hidden
39
39
  The Modal client object is not intended to be instantiated directly by users.
@@ -164,7 +164,7 @@ class Client:
164
164
  server_url: str,
165
165
  client_type: int,
166
166
  credentials: typing.Optional[tuple[str, str]],
167
- version: str = "1.1.5.dev49",
167
+ version: str = "1.1.5.dev51",
168
168
  ):
169
169
  """mdmd:hidden
170
170
  The Modal client object is not intended to be instantiated directly by users.
@@ -450,7 +450,7 @@ class Function(
450
450
 
451
451
  _call_generator: ___call_generator_spec[typing_extensions.Self]
452
452
 
453
- class __remote_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
453
+ class __remote_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER, SUPERSELF]):
454
454
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER:
455
455
  """Calls the function remotely, executing it with the given arguments and returning the execution's result."""
456
456
  ...
@@ -459,7 +459,7 @@ class Function(
459
459
  """Calls the function remotely, executing it with the given arguments and returning the execution's result."""
460
460
  ...
461
461
 
462
- remote: __remote_spec[modal._functions.P, modal._functions.ReturnType, typing_extensions.Self]
462
+ remote: __remote_spec[modal._functions.ReturnType, modal._functions.P, typing_extensions.Self]
463
463
 
464
464
  class __remote_gen_spec(typing_extensions.Protocol[SUPERSELF]):
465
465
  def __call__(self, /, *args, **kwargs) -> typing.Generator[typing.Any, None, None]:
@@ -486,7 +486,7 @@ class Function(
486
486
  """
487
487
  ...
488
488
 
489
- class ___experimental_spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
489
+ class ___experimental_spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER, SUPERSELF]):
490
490
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]:
491
491
  """[Experimental] Calls the function with the given arguments, without waiting for the results.
492
492
 
@@ -510,7 +510,7 @@ class Function(
510
510
  ...
511
511
 
512
512
  _experimental_spawn: ___experimental_spawn_spec[
513
- modal._functions.P, modal._functions.ReturnType, typing_extensions.Self
513
+ modal._functions.ReturnType, modal._functions.P, typing_extensions.Self
514
514
  ]
515
515
 
516
516
  class ___spawn_map_inner_spec(typing_extensions.Protocol[P_INNER, SUPERSELF]):
@@ -519,7 +519,7 @@ class Function(
519
519
 
520
520
  _spawn_map_inner: ___spawn_map_inner_spec[modal._functions.P, typing_extensions.Self]
521
521
 
522
- class __spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
522
+ class __spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER, SUPERSELF]):
523
523
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]:
524
524
  """Calls the function with the given arguments, without waiting for the results.
525
525
 
@@ -540,7 +540,7 @@ class Function(
540
540
  """
541
541
  ...
542
542
 
543
- spawn: __spawn_spec[modal._functions.P, modal._functions.ReturnType, typing_extensions.Self]
543
+ spawn: __spawn_spec[modal._functions.ReturnType, modal._functions.P, typing_extensions.Self]
544
544
 
545
545
  def get_raw_f(self) -> collections.abc.Callable[..., typing.Any]:
546
546
  """Return the inner Python object wrapped by this Modal Function."""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.1.5.dev49
3
+ Version: 1.1.5.dev51
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -1345,6 +1345,14 @@ message FlashProxyUpstreamRequest {
1345
1345
  double timestamp = 2;
1346
1346
  }
1347
1347
 
1348
+ message FlashSetTargetSlotsMetricsRequest {
1349
+ // TODO(claudia): add other metrics to use in autoscaling decisions
1350
+ string function_id = 1;
1351
+ uint32 target_slots = 2;
1352
+ }
1353
+
1354
+ message FlashSetTargetSlotsMetricsResponse {}
1355
+
1348
1356
  message Function {
1349
1357
  string module_name = 1;
1350
1358
  string function_name = 2;
@@ -3629,6 +3637,7 @@ service ModalClient {
3629
3637
  rpc FlashContainerDeregister(FlashContainerDeregisterRequest) returns (google.protobuf.Empty);
3630
3638
  rpc FlashContainerList(FlashContainerListRequest) returns (FlashContainerListResponse);
3631
3639
  rpc FlashContainerRegister(FlashContainerRegisterRequest) returns (FlashContainerRegisterResponse);
3640
+ rpc FlashSetTargetSlotsMetrics(FlashSetTargetSlotsMetricsRequest) returns (FlashSetTargetSlotsMetricsResponse);
3632
3641
 
3633
3642
  // Functions
3634
3643
  rpc FunctionAsyncInvoke(FunctionAsyncInvokeRequest) returns (FunctionAsyncInvokeResponse);
@@ -262,6 +262,10 @@ class ModalClientBase(abc.ABC):
262
262
  async def FlashContainerRegister(self, stream: 'grpclib.server.Stream[modal_proto.api_pb2.FlashContainerRegisterRequest, modal_proto.api_pb2.FlashContainerRegisterResponse]') -> None:
263
263
  pass
264
264
 
265
+ @abc.abstractmethod
266
+ async def FlashSetTargetSlotsMetrics(self, stream: 'grpclib.server.Stream[modal_proto.api_pb2.FlashSetTargetSlotsMetricsRequest, modal_proto.api_pb2.FlashSetTargetSlotsMetricsResponse]') -> None:
267
+ pass
268
+
265
269
  @abc.abstractmethod
266
270
  async def FunctionAsyncInvoke(self, stream: 'grpclib.server.Stream[modal_proto.api_pb2.FunctionAsyncInvokeRequest, modal_proto.api_pb2.FunctionAsyncInvokeResponse]') -> None:
267
271
  pass
@@ -1070,6 +1074,12 @@ class ModalClientBase(abc.ABC):
1070
1074
  modal_proto.api_pb2.FlashContainerRegisterRequest,
1071
1075
  modal_proto.api_pb2.FlashContainerRegisterResponse,
1072
1076
  ),
1077
+ '/modal.client.ModalClient/FlashSetTargetSlotsMetrics': grpclib.const.Handler(
1078
+ self.FlashSetTargetSlotsMetrics,
1079
+ grpclib.const.Cardinality.UNARY_UNARY,
1080
+ modal_proto.api_pb2.FlashSetTargetSlotsMetricsRequest,
1081
+ modal_proto.api_pb2.FlashSetTargetSlotsMetricsResponse,
1082
+ ),
1073
1083
  '/modal.client.ModalClient/FunctionAsyncInvoke': grpclib.const.Handler(
1074
1084
  self.FunctionAsyncInvoke,
1075
1085
  grpclib.const.Cardinality.UNARY_UNARY,
@@ -2102,6 +2112,12 @@ class ModalClientStub:
2102
2112
  modal_proto.api_pb2.FlashContainerRegisterRequest,
2103
2113
  modal_proto.api_pb2.FlashContainerRegisterResponse,
2104
2114
  )
2115
+ self.FlashSetTargetSlotsMetrics = grpclib.client.UnaryUnaryMethod(
2116
+ channel,
2117
+ '/modal.client.ModalClient/FlashSetTargetSlotsMetrics',
2118
+ modal_proto.api_pb2.FlashSetTargetSlotsMetricsRequest,
2119
+ modal_proto.api_pb2.FlashSetTargetSlotsMetricsResponse,
2120
+ )
2105
2121
  self.FunctionAsyncInvoke = grpclib.client.UnaryUnaryMethod(
2106
2122
  channel,
2107
2123
  '/modal.client.ModalClient/FunctionAsyncInvoke',