modal 0.76.5.dev0__tar.gz → 0.76.5.dev4__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 (183) hide show
  1. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/PKG-INFO +1 -1
  2. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/client.pyi +2 -2
  3. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/functions.pyi +7 -7
  4. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/parallel_map.py +98 -88
  5. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/parallel_map.pyi +14 -7
  6. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal.egg-info/PKG-INFO +1 -1
  7. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal_version/__init__.py +1 -1
  8. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/LICENSE +0 -0
  9. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/README.md +0 -0
  10. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/__init__.py +0 -0
  11. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/__main__.py +0 -0
  12. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_clustered_functions.py +0 -0
  13. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_clustered_functions.pyi +0 -0
  14. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_container_entrypoint.py +0 -0
  15. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_functions.py +0 -0
  16. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_ipython.py +0 -0
  17. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_location.py +0 -0
  18. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_object.py +0 -0
  19. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_output.py +0 -0
  20. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_partial_function.py +0 -0
  21. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_pty.py +0 -0
  22. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_resolver.py +0 -0
  23. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_resources.py +0 -0
  24. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_runtime/__init__.py +0 -0
  25. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_runtime/asgi.py +0 -0
  26. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_runtime/container_io_manager.py +0 -0
  27. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_runtime/container_io_manager.pyi +0 -0
  28. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_runtime/execution_context.py +0 -0
  29. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_runtime/execution_context.pyi +0 -0
  30. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_runtime/gpu_memory_snapshot.py +0 -0
  31. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_runtime/telemetry.py +0 -0
  32. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_runtime/user_code_imports.py +0 -0
  33. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_serialization.py +0 -0
  34. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_traceback.py +0 -0
  35. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_tunnel.py +0 -0
  36. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_tunnel.pyi +0 -0
  37. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_type_manager.py +0 -0
  38. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_utils/__init__.py +0 -0
  39. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_utils/app_utils.py +0 -0
  40. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_utils/async_utils.py +0 -0
  41. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_utils/blob_utils.py +0 -0
  42. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_utils/bytes_io_segment_payload.py +0 -0
  43. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_utils/deprecation.py +0 -0
  44. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_utils/docker_utils.py +0 -0
  45. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_utils/function_utils.py +0 -0
  46. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_utils/git_utils.py +0 -0
  47. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_utils/grpc_testing.py +0 -0
  48. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_utils/grpc_utils.py +0 -0
  49. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_utils/hash_utils.py +0 -0
  50. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_utils/http_utils.py +0 -0
  51. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_utils/jwt_utils.py +0 -0
  52. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_utils/logger.py +0 -0
  53. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_utils/mount_utils.py +0 -0
  54. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_utils/name_utils.py +0 -0
  55. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_utils/package_utils.py +0 -0
  56. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_utils/pattern_utils.py +0 -0
  57. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_utils/rand_pb_testing.py +0 -0
  58. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_utils/shell_utils.py +0 -0
  59. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_vendor/__init__.py +0 -0
  60. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_vendor/a2wsgi_wsgi.py +0 -0
  61. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_vendor/cloudpickle.py +0 -0
  62. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_vendor/tblib.py +0 -0
  63. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/_watcher.py +0 -0
  64. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/app.py +0 -0
  65. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/app.pyi +0 -0
  66. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/call_graph.py +0 -0
  67. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/cli/__init__.py +0 -0
  68. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/cli/_download.py +0 -0
  69. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/cli/_traceback.py +0 -0
  70. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/cli/app.py +0 -0
  71. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/cli/cluster.py +0 -0
  72. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/cli/config.py +0 -0
  73. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/cli/container.py +0 -0
  74. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/cli/dict.py +0 -0
  75. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/cli/entry_point.py +0 -0
  76. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/cli/environment.py +0 -0
  77. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/cli/import_refs.py +0 -0
  78. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/cli/launch.py +0 -0
  79. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/cli/network_file_system.py +0 -0
  80. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/cli/profile.py +0 -0
  81. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/cli/programs/__init__.py +0 -0
  82. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/cli/programs/run_jupyter.py +0 -0
  83. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/cli/programs/vscode.py +0 -0
  84. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/cli/queues.py +0 -0
  85. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/cli/run.py +0 -0
  86. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/cli/secret.py +0 -0
  87. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/cli/token.py +0 -0
  88. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/cli/utils.py +0 -0
  89. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/cli/volume.py +0 -0
  90. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/client.py +0 -0
  91. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/cloud_bucket_mount.py +0 -0
  92. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/cloud_bucket_mount.pyi +0 -0
  93. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/cls.py +0 -0
  94. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/cls.pyi +0 -0
  95. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/config.py +0 -0
  96. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/container_process.py +0 -0
  97. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/container_process.pyi +0 -0
  98. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/dict.py +0 -0
  99. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/dict.pyi +0 -0
  100. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/environments.py +0 -0
  101. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/environments.pyi +0 -0
  102. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/exception.py +0 -0
  103. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/experimental/__init__.py +0 -0
  104. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/experimental/ipython.py +0 -0
  105. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/file_io.py +0 -0
  106. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/file_io.pyi +0 -0
  107. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/file_pattern_matcher.py +0 -0
  108. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/functions.py +0 -0
  109. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/gpu.py +0 -0
  110. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/image.py +0 -0
  111. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/image.pyi +0 -0
  112. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/io_streams.py +0 -0
  113. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/io_streams.pyi +0 -0
  114. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/mount.py +0 -0
  115. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/mount.pyi +0 -0
  116. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/network_file_system.py +0 -0
  117. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/network_file_system.pyi +0 -0
  118. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/object.py +0 -0
  119. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/object.pyi +0 -0
  120. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/output.py +0 -0
  121. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/partial_function.py +0 -0
  122. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/partial_function.pyi +0 -0
  123. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/proxy.py +0 -0
  124. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/proxy.pyi +0 -0
  125. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/py.typed +0 -0
  126. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/queue.py +0 -0
  127. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/queue.pyi +0 -0
  128. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/requirements/2023.12.312.txt +0 -0
  129. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/requirements/2023.12.txt +0 -0
  130. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/requirements/2024.04.txt +0 -0
  131. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/requirements/2024.10.txt +0 -0
  132. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/requirements/PREVIEW.txt +0 -0
  133. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/requirements/README.md +0 -0
  134. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/requirements/base-images.json +0 -0
  135. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/retries.py +0 -0
  136. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/runner.py +0 -0
  137. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/runner.pyi +0 -0
  138. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/running_app.py +0 -0
  139. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/sandbox.py +0 -0
  140. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/sandbox.pyi +0 -0
  141. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/schedule.py +0 -0
  142. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/scheduler_placement.py +0 -0
  143. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/secret.py +0 -0
  144. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/secret.pyi +0 -0
  145. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/serving.py +0 -0
  146. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/serving.pyi +0 -0
  147. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/snapshot.py +0 -0
  148. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/snapshot.pyi +0 -0
  149. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/stream_type.py +0 -0
  150. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/token_flow.py +0 -0
  151. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/token_flow.pyi +0 -0
  152. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/volume.py +0 -0
  153. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal/volume.pyi +0 -0
  154. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal.egg-info/SOURCES.txt +0 -0
  155. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal.egg-info/dependency_links.txt +0 -0
  156. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal.egg-info/entry_points.txt +0 -0
  157. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal.egg-info/requires.txt +0 -0
  158. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal.egg-info/top_level.txt +0 -0
  159. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal_docs/__init__.py +0 -0
  160. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal_docs/gen_cli_docs.py +0 -0
  161. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal_docs/gen_reference_docs.py +0 -0
  162. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal_docs/mdmd/__init__.py +0 -0
  163. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal_docs/mdmd/mdmd.py +0 -0
  164. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal_docs/mdmd/signatures.py +0 -0
  165. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal_proto/__init__.py +0 -0
  166. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal_proto/api.proto +0 -0
  167. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal_proto/api_grpc.py +0 -0
  168. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal_proto/api_pb2.py +0 -0
  169. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal_proto/api_pb2.pyi +0 -0
  170. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal_proto/api_pb2_grpc.py +0 -0
  171. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal_proto/api_pb2_grpc.pyi +0 -0
  172. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal_proto/modal_api_grpc.py +0 -0
  173. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal_proto/modal_options_grpc.py +0 -0
  174. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal_proto/options.proto +0 -0
  175. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal_proto/options_grpc.py +0 -0
  176. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal_proto/options_pb2.py +0 -0
  177. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal_proto/options_pb2.pyi +0 -0
  178. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal_proto/options_pb2_grpc.py +0 -0
  179. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal_proto/options_pb2_grpc.pyi +0 -0
  180. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal_proto/py.typed +0 -0
  181. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/modal_version/__main__.py +0 -0
  182. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/pyproject.toml +0 -0
  183. {modal-0.76.5.dev0 → modal-0.76.5.dev4}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 0.76.5.dev0
3
+ Version: 0.76.5.dev4
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -31,7 +31,7 @@ class _Client:
31
31
  server_url: str,
32
32
  client_type: int,
33
33
  credentials: typing.Optional[tuple[str, str]],
34
- version: str = "0.76.5.dev0",
34
+ version: str = "0.76.5.dev4",
35
35
  ): ...
36
36
  def is_closed(self) -> bool: ...
37
37
  @property
@@ -94,7 +94,7 @@ class Client:
94
94
  server_url: str,
95
95
  client_type: int,
96
96
  credentials: typing.Optional[tuple[str, str]],
97
- version: str = "0.76.5.dev0",
97
+ version: str = "0.76.5.dev4",
98
98
  ): ...
99
99
  def is_closed(self) -> bool: ...
100
100
  @property
@@ -234,11 +234,11 @@ class Function(
234
234
 
235
235
  _call_generator_nowait: ___call_generator_nowait_spec[typing_extensions.Self]
236
236
 
237
- class __remote_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER, SUPERSELF]):
237
+ class __remote_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
238
238
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER: ...
239
239
  async def aio(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER: ...
240
240
 
241
- remote: __remote_spec[modal._functions.ReturnType, modal._functions.P, typing_extensions.Self]
241
+ remote: __remote_spec[modal._functions.P, modal._functions.ReturnType, typing_extensions.Self]
242
242
 
243
243
  class __remote_gen_spec(typing_extensions.Protocol[SUPERSELF]):
244
244
  def __call__(self, /, *args, **kwargs) -> typing.Generator[typing.Any, None, None]: ...
@@ -253,12 +253,12 @@ class Function(
253
253
  self, *args: modal._functions.P.args, **kwargs: modal._functions.P.kwargs
254
254
  ) -> modal._functions.OriginalReturnType: ...
255
255
 
256
- class ___experimental_spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER, SUPERSELF]):
256
+ class ___experimental_spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
257
257
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
258
258
  async def aio(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
259
259
 
260
260
  _experimental_spawn: ___experimental_spawn_spec[
261
- modal._functions.ReturnType, modal._functions.P, typing_extensions.Self
261
+ modal._functions.P, modal._functions.ReturnType, typing_extensions.Self
262
262
  ]
263
263
 
264
264
  class ___spawn_map_inner_spec(typing_extensions.Protocol[P_INNER, SUPERSELF]):
@@ -267,11 +267,11 @@ class Function(
267
267
 
268
268
  _spawn_map_inner: ___spawn_map_inner_spec[modal._functions.P, typing_extensions.Self]
269
269
 
270
- class __spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER, SUPERSELF]):
270
+ class __spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
271
271
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
272
272
  async def aio(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
273
273
 
274
- spawn: __spawn_spec[modal._functions.ReturnType, modal._functions.P, typing_extensions.Self]
274
+ spawn: __spawn_spec[modal._functions.P, modal._functions.ReturnType, typing_extensions.Self]
275
275
 
276
276
  def get_raw_f(self) -> collections.abc.Callable[..., typing.Any]: ...
277
277
 
@@ -328,7 +328,7 @@ class Function(
328
328
 
329
329
  class __for_each_spec(typing_extensions.Protocol[SUPERSELF]):
330
330
  def __call__(self, /, *input_iterators, kwargs={}, ignore_exceptions: bool = False): ...
331
- async def aio(self, /, *input_iterators, kwargs={}, ignore_exceptions: bool = False): ...
331
+ async def aio(self, /, *input_iterators, kwargs={}, ignore_exceptions: bool = False) -> None: ...
332
332
 
333
333
  for_each: __for_each_spec[typing_extensions.Self]
334
334
 
@@ -381,6 +381,94 @@ async def _map_invocation(
381
381
  await log_debug_stats_task
382
382
 
383
383
 
384
+ async def _map_helper(
385
+ self: "modal.functions.Function",
386
+ async_input_gen: typing.AsyncGenerator[Any, None],
387
+ kwargs={}, # any extra keyword arguments for the function
388
+ order_outputs: bool = True, # return outputs in order
389
+ return_exceptions: bool = False, # propagate exceptions (False) or aggregate them in the results list (True)
390
+ ) -> typing.AsyncGenerator[Any, None]:
391
+ """Core implementation that supports `_map_async()`, `_starmap_async()` and `_for_each_async()`.
392
+
393
+ Runs in an event loop on the main thread. Concurrently feeds new input to the input queue and yields available
394
+ outputs to the caller.
395
+
396
+ Note that since the iterator(s) can block, it's a bit opaque how often the event
397
+ loop decides to get a new input vs how often it will emit a new output.
398
+
399
+ We could make this explicit as an improvement or even let users decide what they
400
+ prefer: throughput (prioritize queueing inputs) or latency (prioritize yielding results)
401
+ """
402
+
403
+ raw_input_queue: Any = SynchronizedQueue() # type: ignore
404
+ raw_input_queue.init()
405
+
406
+ async def feed_queue():
407
+ async with aclosing(async_input_gen) as streamer:
408
+ async for args in streamer:
409
+ await raw_input_queue.put.aio((args, kwargs))
410
+ await raw_input_queue.put.aio(None) # end-of-input sentinel
411
+ if False:
412
+ # make this a never yielding generator so we can async_merge it below
413
+ # this is important so any exception raised in feed_queue will be propagated
414
+ yield
415
+
416
+ # note that `map()`, `map.aio()`, `starmap()`, `starmap.aio()`, `for_each()`, `for_each.aio()` are not
417
+ # synchronicity-wrapped, since they accept executable code in the form of iterators that we don't want to run inside
418
+ # the synchronicity thread. Instead, we delegate to `._map()` with a safer Queue as input.
419
+ async with aclosing(
420
+ async_merge(self._map.aio(raw_input_queue, order_outputs, return_exceptions), feed_queue())
421
+ ) as map_output_stream:
422
+ async for output in map_output_stream:
423
+ yield output
424
+
425
+
426
+ @warn_if_generator_is_not_consumed(function_name="Function.map.aio")
427
+ async def _map_async(
428
+ self: "modal.functions.Function",
429
+ *input_iterators: typing.Union[
430
+ typing.Iterable[Any], typing.AsyncIterable[Any]
431
+ ], # one input iterator per argument in the mapped-over function/generator
432
+ kwargs={}, # any extra keyword arguments for the function
433
+ order_outputs: bool = True, # return outputs in order
434
+ return_exceptions: bool = False, # propagate exceptions (False) or aggregate them in the results list (True)
435
+ ) -> typing.AsyncGenerator[Any, None]:
436
+ async_input_gen = async_zip(*[sync_or_async_iter(it) for it in input_iterators])
437
+ async for output in _map_helper(
438
+ self, async_input_gen, kwargs=kwargs, order_outputs=order_outputs, return_exceptions=return_exceptions
439
+ ):
440
+ yield output
441
+
442
+
443
+ @warn_if_generator_is_not_consumed(function_name="Function.starmap.aio")
444
+ async def _starmap_async(
445
+ self,
446
+ input_iterator: typing.Union[typing.Iterable[typing.Sequence[Any]], typing.AsyncIterable[typing.Sequence[Any]]],
447
+ *,
448
+ kwargs={},
449
+ order_outputs: bool = True,
450
+ return_exceptions: bool = False,
451
+ ) -> typing.AsyncIterable[Any]:
452
+ async for output in _map_helper(
453
+ self,
454
+ sync_or_async_iter(input_iterator),
455
+ kwargs=kwargs,
456
+ order_outputs=order_outputs,
457
+ return_exceptions=return_exceptions,
458
+ ):
459
+ yield output
460
+
461
+
462
+ async def _for_each_async(self, *input_iterators, kwargs={}, ignore_exceptions: bool = False) -> None:
463
+ # TODO(erikbern): it would be better if this is more like a map_spawn that immediately exits
464
+ # rather than iterating over the result
465
+ async_input_gen = async_zip(*[sync_or_async_iter(it) for it in input_iterators])
466
+ async for _ in _map_helper(
467
+ self, async_input_gen, kwargs=kwargs, order_outputs=False, return_exceptions=ignore_exceptions
468
+ ):
469
+ pass
470
+
471
+
384
472
  @warn_if_generator_is_not_consumed(function_name="Function.map")
385
473
  def _map_sync(
386
474
  self,
@@ -431,60 +519,13 @@ def _map_sync(
431
519
  self, *input_iterators, kwargs=kwargs, order_outputs=order_outputs, return_exceptions=return_exceptions
432
520
  ),
433
521
  nested_async_message=(
434
- "You can't iter(Function.map()) or Function.for_each() from an async function. "
435
- "Use async for ... Function.map.aio() or Function.for_each.aio() instead."
522
+ "You can't iter(Function.map()) from an async function. Use async for ... in Function.map.aio() instead."
436
523
  ),
437
524
  )
438
525
 
439
526
 
440
- @warn_if_generator_is_not_consumed(function_name="Function.map.aio")
441
- async def _map_async(
442
- self: "modal.functions.Function",
443
- *input_iterators: typing.Union[
444
- typing.Iterable[Any], typing.AsyncIterable[Any]
445
- ], # one input iterator per argument in the mapped-over function/generator
446
- kwargs={}, # any extra keyword arguments for the function
447
- order_outputs: bool = True, # return outputs in order
448
- return_exceptions: bool = False, # propagate exceptions (False) or aggregate them in the results list (True)
449
- ) -> typing.AsyncGenerator[Any, None]:
450
- """mdmd:hidden
451
- This runs in an event loop on the main thread
452
-
453
- It concurrently feeds new input to the input queue and yields available outputs
454
- to the caller.
455
- Note that since the iterator(s) can block, it's a bit opaque how often the event
456
- loop decides to get a new input vs how often it will emit a new output.
457
- We could make this explicit as an improvement or even let users decide what they
458
- prefer: throughput (prioritize queueing inputs) or latency (prioritize yielding results)
459
- """
460
- raw_input_queue: Any = SynchronizedQueue() # type: ignore
461
- raw_input_queue.init()
462
-
463
- async def feed_queue():
464
- # This runs in a main thread event loop, so it doesn't block the synchronizer loop
465
- async with aclosing(async_zip(*[sync_or_async_iter(it) for it in input_iterators])) as streamer:
466
- async for args in streamer:
467
- await raw_input_queue.put.aio((args, kwargs))
468
- await raw_input_queue.put.aio(None) # end-of-input sentinel
469
- if False:
470
- # make this a never yielding generator so we can async_merge it below
471
- # this is important so any exception raised in feed_queue will be propagated
472
- yield
473
-
474
- # note that `map()` and `map.aio()` are not synchronicity-wrapped, since
475
- # they accept executable code in the form of
476
- # iterators that we don't want to run inside the synchronicity thread.
477
- # Instead, we delegate to `._map()` with a safer Queue as input
478
- async with aclosing(
479
- async_merge(self._map.aio(raw_input_queue, order_outputs, return_exceptions), feed_queue())
480
- ) as map_output_stream:
481
- async for output in map_output_stream:
482
- yield output
483
-
484
-
485
527
  async def _spawn_map_async(self, *input_iterators, kwargs={}) -> None:
486
- """mdmd:hidden
487
- This runs in an event loop on the main thread. It consumes inputs from the input iterators and creates async
528
+ """This runs in an event loop on the main thread. It consumes inputs from the input iterators and creates async
488
529
  function calls for each.
489
530
  """
490
531
 
@@ -538,47 +579,16 @@ def _for_each_sync(self, *input_iterators, kwargs={}, ignore_exceptions: bool =
538
579
  Convenient alias for `.map()` in cases where the function just needs to be called.
539
580
  as the caller doesn't have to consume the generator to process the inputs.
540
581
  """
541
- # TODO(erikbern): it would be better if this is more like a map_spawn that immediately exits
542
- # rather than iterating over the result
543
- for _ in self.map(*input_iterators, kwargs=kwargs, order_outputs=False, return_exceptions=ignore_exceptions):
544
- pass
545
-
546
582
 
547
- async def _for_each_async(self, *input_iterators, kwargs={}, ignore_exceptions: bool = False):
548
- async for _ in self.map.aio( # type: ignore
549
- *input_iterators, kwargs=kwargs, order_outputs=False, return_exceptions=ignore_exceptions
550
- ):
551
- pass
583
+ return run_coroutine_in_temporary_event_loop(
584
+ _for_each_async(self, *input_iterators, kwargs=kwargs, ignore_exceptions=ignore_exceptions),
585
+ nested_async_message=(
586
+ "You can't run `Function.for_each()` from an async function. Use `await Function.for_each.aio()` instead."
587
+ ),
588
+ )
552
589
 
553
590
 
554
591
  @warn_if_generator_is_not_consumed(function_name="Function.starmap")
555
- async def _starmap_async(
556
- self,
557
- input_iterator: typing.Union[typing.Iterable[typing.Sequence[Any]], typing.AsyncIterable[typing.Sequence[Any]]],
558
- *,
559
- kwargs={},
560
- order_outputs: bool = True,
561
- return_exceptions: bool = False,
562
- ) -> typing.AsyncIterable[Any]:
563
- raw_input_queue: Any = SynchronizedQueue() # type: ignore
564
- raw_input_queue.init()
565
-
566
- async def feed_queue():
567
- # This runs in a main thread event loop, so it doesn't block the synchronizer loop
568
- async with aclosing(sync_or_async_iter(input_iterator)) as streamer:
569
- async for args in streamer:
570
- await raw_input_queue.put.aio((args, kwargs))
571
- await raw_input_queue.put.aio(None) # end-of-input sentinel
572
-
573
- feed_input_task = asyncio.create_task(feed_queue())
574
- try:
575
- async for output in self._map.aio(raw_input_queue, order_outputs, return_exceptions): # type: ignore[reportFunctionMemberAccess]
576
- yield output
577
- finally:
578
- feed_input_task.cancel() # should only be needed in case of exceptions
579
-
580
-
581
- @warn_if_generator_is_not_consumed(function_name="Function.starmap.aio")
582
592
  def _starmap_sync(
583
593
  self,
584
594
  input_iterator: typing.Iterable[typing.Sequence[Any]],
@@ -608,8 +618,8 @@ def _starmap_sync(
608
618
  self, input_iterator, kwargs=kwargs, order_outputs=order_outputs, return_exceptions=return_exceptions
609
619
  ),
610
620
  nested_async_message=(
611
- "You can't run Function.map() or Function.for_each() from an async function. "
612
- "Use Function.map.aio()/Function.for_each.aio() instead."
621
+ "You can't `iter(Function.starmap())` from an async function. "
622
+ "Use `async for ... in Function.starmap.aio()` instead."
613
623
  ),
614
624
  )
615
625
 
@@ -55,9 +55,13 @@ def _map_invocation(
55
55
  count_update_callback: typing.Optional[collections.abc.Callable[[int, int], None]],
56
56
  function_call_invocation_type: int,
57
57
  ): ...
58
- def _map_sync(
59
- self, *input_iterators, kwargs={}, order_outputs: bool = True, return_exceptions: bool = False
60
- ) -> modal._utils.async_utils.AsyncOrSyncIterable: ...
58
+ def _map_helper(
59
+ self: modal.functions.Function,
60
+ async_input_gen: typing.AsyncGenerator[typing.Any, None],
61
+ kwargs={},
62
+ order_outputs: bool = True,
63
+ return_exceptions: bool = False,
64
+ ) -> typing.AsyncGenerator[typing.Any, None]: ...
61
65
  def _map_async(
62
66
  self: modal.functions.Function,
63
67
  *input_iterators: typing.Union[typing.Iterable[typing.Any], typing.AsyncIterable[typing.Any]],
@@ -65,10 +69,6 @@ def _map_async(
65
69
  order_outputs: bool = True,
66
70
  return_exceptions: bool = False,
67
71
  ) -> typing.AsyncGenerator[typing.Any, None]: ...
68
- async def _spawn_map_async(self, *input_iterators, kwargs={}) -> None: ...
69
- def _spawn_map_sync(self, *input_iterators, kwargs={}) -> None: ...
70
- def _for_each_sync(self, *input_iterators, kwargs={}, ignore_exceptions: bool = False): ...
71
- async def _for_each_async(self, *input_iterators, kwargs={}, ignore_exceptions: bool = False): ...
72
72
  def _starmap_async(
73
73
  self,
74
74
  input_iterator: typing.Union[
@@ -79,6 +79,13 @@ def _starmap_async(
79
79
  order_outputs: bool = True,
80
80
  return_exceptions: bool = False,
81
81
  ) -> typing.AsyncIterable[typing.Any]: ...
82
+ async def _for_each_async(self, *input_iterators, kwargs={}, ignore_exceptions: bool = False) -> None: ...
83
+ def _map_sync(
84
+ self, *input_iterators, kwargs={}, order_outputs: bool = True, return_exceptions: bool = False
85
+ ) -> modal._utils.async_utils.AsyncOrSyncIterable: ...
86
+ async def _spawn_map_async(self, *input_iterators, kwargs={}) -> None: ...
87
+ def _spawn_map_sync(self, *input_iterators, kwargs={}) -> None: ...
88
+ def _for_each_sync(self, *input_iterators, kwargs={}, ignore_exceptions: bool = False): ...
82
89
  def _starmap_sync(
83
90
  self,
84
91
  input_iterator: typing.Iterable[typing.Sequence[typing.Any]],
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 0.76.5.dev0
3
+ Version: 0.76.5.dev4
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -1,4 +1,4 @@
1
1
  # Copyright Modal Labs 2025
2
2
  """Supplies the current version of the modal client library."""
3
3
 
4
- __version__ = "0.76.5.dev0"
4
+ __version__ = "0.76.5.dev4"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes