modal 1.1.2.dev36__tar.gz → 1.1.2.dev37__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 (190) hide show
  1. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/PKG-INFO +1 -1
  2. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_functions.py +26 -3
  3. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/client.pyi +2 -2
  4. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/functions.pyi +13 -0
  5. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/parallel_map.py +13 -2
  6. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/parallel_map.pyi +3 -1
  7. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal.egg-info/PKG-INFO +1 -1
  8. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal_version/__init__.py +1 -1
  9. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/LICENSE +0 -0
  10. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/README.md +0 -0
  11. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/__init__.py +0 -0
  12. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/__main__.py +0 -0
  13. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_clustered_functions.py +0 -0
  14. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_clustered_functions.pyi +0 -0
  15. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_container_entrypoint.py +0 -0
  16. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_ipython.py +0 -0
  17. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_location.py +0 -0
  18. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_object.py +0 -0
  19. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_output.py +0 -0
  20. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_partial_function.py +0 -0
  21. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_pty.py +0 -0
  22. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_resolver.py +0 -0
  23. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_resources.py +0 -0
  24. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_runtime/__init__.py +0 -0
  25. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_runtime/asgi.py +0 -0
  26. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_runtime/container_io_manager.py +0 -0
  27. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_runtime/container_io_manager.pyi +0 -0
  28. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_runtime/execution_context.py +0 -0
  29. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_runtime/execution_context.pyi +0 -0
  30. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_runtime/gpu_memory_snapshot.py +0 -0
  31. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_runtime/telemetry.py +0 -0
  32. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_runtime/user_code_imports.py +0 -0
  33. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_serialization.py +0 -0
  34. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_traceback.py +0 -0
  35. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_tunnel.py +0 -0
  36. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_tunnel.pyi +0 -0
  37. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_type_manager.py +0 -0
  38. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_utils/__init__.py +0 -0
  39. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_utils/app_utils.py +0 -0
  40. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_utils/async_utils.py +0 -0
  41. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_utils/auth_token_manager.py +0 -0
  42. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_utils/blob_utils.py +0 -0
  43. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_utils/bytes_io_segment_payload.py +0 -0
  44. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_utils/deprecation.py +0 -0
  45. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_utils/docker_utils.py +0 -0
  46. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_utils/function_utils.py +0 -0
  47. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_utils/git_utils.py +0 -0
  48. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_utils/grpc_testing.py +0 -0
  49. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_utils/grpc_utils.py +0 -0
  50. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_utils/hash_utils.py +0 -0
  51. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_utils/http_utils.py +0 -0
  52. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_utils/jwt_utils.py +0 -0
  53. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_utils/logger.py +0 -0
  54. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_utils/mount_utils.py +0 -0
  55. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_utils/name_utils.py +0 -0
  56. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_utils/package_utils.py +0 -0
  57. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_utils/pattern_utils.py +0 -0
  58. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_utils/rand_pb_testing.py +0 -0
  59. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_utils/shell_utils.py +0 -0
  60. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_utils/time_utils.py +0 -0
  61. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_vendor/__init__.py +0 -0
  62. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_vendor/a2wsgi_wsgi.py +0 -0
  63. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_vendor/cloudpickle.py +0 -0
  64. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_vendor/tblib.py +0 -0
  65. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/_watcher.py +0 -0
  66. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/app.py +0 -0
  67. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/app.pyi +0 -0
  68. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/builder/2023.12.312.txt +0 -0
  69. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/builder/2023.12.txt +0 -0
  70. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/builder/2024.04.txt +0 -0
  71. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/builder/2024.10.txt +0 -0
  72. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/builder/2025.06.txt +0 -0
  73. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/builder/PREVIEW.txt +0 -0
  74. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/builder/README.md +0 -0
  75. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/builder/base-images.json +0 -0
  76. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/call_graph.py +0 -0
  77. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/cli/__init__.py +0 -0
  78. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/cli/_download.py +0 -0
  79. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/cli/_traceback.py +0 -0
  80. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/cli/app.py +0 -0
  81. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/cli/cluster.py +0 -0
  82. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/cli/config.py +0 -0
  83. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/cli/container.py +0 -0
  84. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/cli/dict.py +0 -0
  85. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/cli/entry_point.py +0 -0
  86. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/cli/environment.py +0 -0
  87. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/cli/import_refs.py +0 -0
  88. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/cli/launch.py +0 -0
  89. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/cli/network_file_system.py +0 -0
  90. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/cli/profile.py +0 -0
  91. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/cli/programs/__init__.py +0 -0
  92. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/cli/programs/launch_instance_ssh.py +0 -0
  93. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/cli/programs/run_jupyter.py +0 -0
  94. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/cli/programs/run_marimo.py +0 -0
  95. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/cli/programs/vscode.py +0 -0
  96. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/cli/queues.py +0 -0
  97. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/cli/run.py +0 -0
  98. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/cli/secret.py +0 -0
  99. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/cli/token.py +0 -0
  100. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/cli/utils.py +0 -0
  101. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/cli/volume.py +0 -0
  102. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/client.py +0 -0
  103. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/cloud_bucket_mount.py +0 -0
  104. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/cloud_bucket_mount.pyi +0 -0
  105. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/cls.py +0 -0
  106. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/cls.pyi +0 -0
  107. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/config.py +0 -0
  108. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/container_process.py +0 -0
  109. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/container_process.pyi +0 -0
  110. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/dict.py +0 -0
  111. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/dict.pyi +0 -0
  112. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/environments.py +0 -0
  113. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/environments.pyi +0 -0
  114. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/exception.py +0 -0
  115. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/experimental/__init__.py +0 -0
  116. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/experimental/flash.py +0 -0
  117. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/experimental/flash.pyi +0 -0
  118. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/experimental/ipython.py +0 -0
  119. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/file_io.py +0 -0
  120. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/file_io.pyi +0 -0
  121. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/file_pattern_matcher.py +0 -0
  122. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/functions.py +0 -0
  123. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/gpu.py +0 -0
  124. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/image.py +0 -0
  125. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/image.pyi +0 -0
  126. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/io_streams.py +0 -0
  127. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/io_streams.pyi +0 -0
  128. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/mount.py +0 -0
  129. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/mount.pyi +0 -0
  130. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/network_file_system.py +0 -0
  131. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/network_file_system.pyi +0 -0
  132. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/object.py +0 -0
  133. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/object.pyi +0 -0
  134. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/output.py +0 -0
  135. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/partial_function.py +0 -0
  136. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/partial_function.pyi +0 -0
  137. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/proxy.py +0 -0
  138. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/proxy.pyi +0 -0
  139. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/py.typed +0 -0
  140. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/queue.py +0 -0
  141. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/queue.pyi +0 -0
  142. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/retries.py +0 -0
  143. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/runner.py +0 -0
  144. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/runner.pyi +0 -0
  145. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/running_app.py +0 -0
  146. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/sandbox.py +0 -0
  147. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/sandbox.pyi +0 -0
  148. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/schedule.py +0 -0
  149. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/scheduler_placement.py +0 -0
  150. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/secret.py +0 -0
  151. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/secret.pyi +0 -0
  152. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/serving.py +0 -0
  153. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/serving.pyi +0 -0
  154. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/snapshot.py +0 -0
  155. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/snapshot.pyi +0 -0
  156. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/stream_type.py +0 -0
  157. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/token_flow.py +0 -0
  158. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/token_flow.pyi +0 -0
  159. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/volume.py +0 -0
  160. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal/volume.pyi +0 -0
  161. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal.egg-info/SOURCES.txt +0 -0
  162. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal.egg-info/dependency_links.txt +0 -0
  163. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal.egg-info/entry_points.txt +0 -0
  164. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal.egg-info/requires.txt +0 -0
  165. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal.egg-info/top_level.txt +0 -0
  166. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal_docs/__init__.py +0 -0
  167. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal_docs/gen_cli_docs.py +0 -0
  168. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal_docs/gen_reference_docs.py +0 -0
  169. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal_docs/mdmd/__init__.py +0 -0
  170. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal_docs/mdmd/mdmd.py +0 -0
  171. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal_docs/mdmd/signatures.py +0 -0
  172. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal_proto/__init__.py +0 -0
  173. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal_proto/api.proto +0 -0
  174. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal_proto/api_grpc.py +0 -0
  175. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal_proto/api_pb2.py +0 -0
  176. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal_proto/api_pb2.pyi +0 -0
  177. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal_proto/api_pb2_grpc.py +0 -0
  178. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal_proto/api_pb2_grpc.pyi +0 -0
  179. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal_proto/modal_api_grpc.py +0 -0
  180. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal_proto/modal_options_grpc.py +0 -0
  181. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal_proto/options.proto +0 -0
  182. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal_proto/options_grpc.py +0 -0
  183. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal_proto/options_pb2.py +0 -0
  184. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal_proto/options_pb2.pyi +0 -0
  185. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal_proto/options_pb2_grpc.py +0 -0
  186. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal_proto/options_pb2_grpc.pyi +0 -0
  187. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal_proto/py.typed +0 -0
  188. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/modal_version/__main__.py +0 -0
  189. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/pyproject.toml +0 -0
  190. {modal-1.1.2.dev36 → modal-1.1.2.dev37}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.1.2.dev36
3
+ Version: 1.1.2.dev37
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -1564,12 +1564,13 @@ Use the `Function.get_web_url()` method instead.
1564
1564
  raise InvalidError("A generator function cannot be called with `.spawn_map(...)`.")
1565
1565
 
1566
1566
  assert self._function_name
1567
- function_call_id = await _spawn_map_invocation(
1567
+ function_call_id, num_inputs = await _spawn_map_invocation(
1568
1568
  self,
1569
1569
  input_queue,
1570
1570
  self.client,
1571
1571
  )
1572
- fc: _FunctionCall[ReturnType] = _FunctionCall._new_hydrated(function_call_id, self.client, None)
1572
+ metadata = api_pb2.FunctionCallFromIdResponse(function_call_id=function_call_id, num_inputs=num_inputs)
1573
+ fc: _FunctionCall[ReturnType] = _FunctionCall._new_hydrated(function_call_id, self.client, metadata)
1573
1574
  return fc
1574
1575
 
1575
1576
  async def _call_function(self, args, kwargs) -> ReturnType:
@@ -1833,10 +1834,24 @@ class _FunctionCall(typing.Generic[ReturnType], _Object, type_prefix="fc"):
1833
1834
  """
1834
1835
 
1835
1836
  _is_generator: bool = False
1837
+ _num_inputs: Optional[int] = None
1836
1838
 
1837
1839
  def _invocation(self):
1838
1840
  return _Invocation(self.client.stub, self.object_id, self.client)
1839
1841
 
1842
+ def _hydrate_metadata(self, metadata: Optional[Message]):
1843
+ if not metadata:
1844
+ return
1845
+ assert isinstance(metadata, api_pb2.FunctionCallFromIdResponse)
1846
+ self._num_inputs = metadata.num_inputs
1847
+
1848
+ @live_method
1849
+ async def num_inputs(self) -> int:
1850
+ """Get the number of inputs in the function call."""
1851
+ # Should have been hydrated.
1852
+ assert self._num_inputs is not None
1853
+ return self._num_inputs
1854
+
1840
1855
  async def get(self, timeout: Optional[float] = None, *, index: int = 0) -> ReturnType:
1841
1856
  """Get the result of the index-th input of the function call.
1842
1857
  `.spawn()` calls have a single output, so only specifying `index=0` is valid.
@@ -1902,7 +1917,15 @@ class _FunctionCall(typing.Generic[ReturnType], _Object, type_prefix="fc"):
1902
1917
  if client is None:
1903
1918
  client = await _Client.from_env()
1904
1919
 
1905
- fc: _FunctionCall[Any] = _FunctionCall._new_hydrated(function_call_id, client, None)
1920
+ async def _load(self: _FunctionCall, resolver: Resolver, existing_object_id: Optional[str]):
1921
+ request = api_pb2.FunctionCallFromIdRequest(function_call_id=function_call_id)
1922
+ resp = await retry_transient_errors(resolver.client.stub.FunctionCallFromId, request)
1923
+ self._hydrate(function_call_id, resolver.client, resp)
1924
+
1925
+ rep = f"FunctionCall.from_id({function_call_id!r})"
1926
+ fc: _FunctionCall[Any] = _FunctionCall._from_loader(_load, rep, hydrate_lazily=True)
1927
+ # We already know the object ID, so we can set it directly
1928
+ fc._object_id = function_call_id
1906
1929
  return fc
1907
1930
 
1908
1931
  @staticmethod
@@ -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.2.dev36",
36
+ version: str = "1.1.2.dev37",
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.2.dev36",
167
+ version: str = "1.1.2.dev37",
168
168
  ):
169
169
  """mdmd:hidden
170
170
  The Modal client object is not intended to be instantiated directly by users.
@@ -738,12 +738,25 @@ class FunctionCall(typing.Generic[modal._functions.ReturnType], modal.object.Obj
738
738
  """
739
739
 
740
740
  _is_generator: bool
741
+ _num_inputs: typing.Optional[int]
741
742
 
742
743
  def __init__(self, *args, **kwargs):
743
744
  """mdmd:hidden"""
744
745
  ...
745
746
 
746
747
  def _invocation(self): ...
748
+ def _hydrate_metadata(self, metadata: typing.Optional[google.protobuf.message.Message]): ...
749
+
750
+ class __num_inputs_spec(typing_extensions.Protocol[SUPERSELF]):
751
+ def __call__(self, /) -> int:
752
+ """Get the number of inputs in the function call."""
753
+ ...
754
+
755
+ async def aio(self, /) -> int:
756
+ """Get the number of inputs in the function call."""
757
+ ...
758
+
759
+ num_inputs: __num_inputs_spec[typing_extensions.Self]
747
760
 
748
761
  class __get_spec(typing_extensions.Protocol[ReturnType_INNER, SUPERSELF]):
749
762
  def __call__(self, /, timeout: typing.Optional[float] = None, *, index: int = 0) -> ReturnType_INNER:
@@ -271,10 +271,21 @@ class AsyncInputPumper(InputPumper):
271
271
  ):
272
272
  super().__init__(client, input_queue=input_queue, function=function, function_call_id=function_call_id)
273
273
 
274
+ async def pump_inputs(self):
275
+ async for _ in super().pump_inputs():
276
+ pass
277
+ request = api_pb2.FunctionFinishInputsRequest(
278
+ function_id=self.function.object_id,
279
+ function_call_id=self.function_call_id,
280
+ num_inputs=self.inputs_sent,
281
+ )
282
+ await retry_transient_errors(self.client.stub.FunctionFinishInputs, request, max_retries=None)
283
+ yield
284
+
274
285
 
275
286
  async def _spawn_map_invocation(
276
287
  function: "modal.functions._Function", raw_input_queue: _SynchronizedQueue, client: "modal.client._Client"
277
- ) -> str:
288
+ ) -> tuple[str, int]:
278
289
  assert client.stub
279
290
  request = api_pb2.FunctionMapRequest(
280
291
  function_id=function.object_id,
@@ -340,7 +351,7 @@ async def _spawn_map_invocation(
340
351
  )
341
352
  log_debug_stats_task.cancel()
342
353
  await log_debug_stats_task
343
- return function_call_id
354
+ return function_call_id, inputs_created
344
355
 
345
356
 
346
357
  async def _map_invocation(
@@ -136,9 +136,11 @@ class AsyncInputPumper(InputPumper):
136
136
  """Initialize self. See help(type(self)) for accurate signature."""
137
137
  ...
138
138
 
139
+ def pump_inputs(self): ...
140
+
139
141
  async def _spawn_map_invocation(
140
142
  function: modal._functions._Function, raw_input_queue: _SynchronizedQueue, client: modal.client._Client
141
- ) -> str: ...
143
+ ) -> tuple[str, int]: ...
142
144
  def _map_invocation(
143
145
  function: modal._functions._Function,
144
146
  raw_input_queue: _SynchronizedQueue,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.1.2.dev36
3
+ Version: 1.1.2.dev37
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__ = "1.1.2.dev36"
4
+ __version__ = "1.1.2.dev37"
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