modal 1.1.2.dev35__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.dev35 → modal-1.1.2.dev37}/PKG-INFO +1 -1
  2. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_functions.py +26 -3
  3. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/client.pyi +2 -2
  4. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/file_io.py +1 -1
  5. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/file_io.pyi +2 -2
  6. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/functions.pyi +13 -0
  7. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/parallel_map.py +13 -2
  8. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/parallel_map.pyi +3 -1
  9. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/sandbox.py +3 -2
  10. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/sandbox.pyi +9 -6
  11. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal.egg-info/PKG-INFO +1 -1
  12. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal_version/__init__.py +1 -1
  13. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/LICENSE +0 -0
  14. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/README.md +0 -0
  15. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/__init__.py +0 -0
  16. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/__main__.py +0 -0
  17. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_clustered_functions.py +0 -0
  18. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_clustered_functions.pyi +0 -0
  19. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_container_entrypoint.py +0 -0
  20. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_ipython.py +0 -0
  21. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_location.py +0 -0
  22. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_object.py +0 -0
  23. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_output.py +0 -0
  24. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_partial_function.py +0 -0
  25. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_pty.py +0 -0
  26. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_resolver.py +0 -0
  27. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_resources.py +0 -0
  28. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_runtime/__init__.py +0 -0
  29. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_runtime/asgi.py +0 -0
  30. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_runtime/container_io_manager.py +0 -0
  31. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_runtime/container_io_manager.pyi +0 -0
  32. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_runtime/execution_context.py +0 -0
  33. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_runtime/execution_context.pyi +0 -0
  34. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_runtime/gpu_memory_snapshot.py +0 -0
  35. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_runtime/telemetry.py +0 -0
  36. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_runtime/user_code_imports.py +0 -0
  37. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_serialization.py +0 -0
  38. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_traceback.py +0 -0
  39. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_tunnel.py +0 -0
  40. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_tunnel.pyi +0 -0
  41. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_type_manager.py +0 -0
  42. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_utils/__init__.py +0 -0
  43. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_utils/app_utils.py +0 -0
  44. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_utils/async_utils.py +0 -0
  45. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_utils/auth_token_manager.py +0 -0
  46. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_utils/blob_utils.py +0 -0
  47. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_utils/bytes_io_segment_payload.py +0 -0
  48. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_utils/deprecation.py +0 -0
  49. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_utils/docker_utils.py +0 -0
  50. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_utils/function_utils.py +0 -0
  51. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_utils/git_utils.py +0 -0
  52. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_utils/grpc_testing.py +0 -0
  53. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_utils/grpc_utils.py +0 -0
  54. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_utils/hash_utils.py +0 -0
  55. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_utils/http_utils.py +0 -0
  56. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_utils/jwt_utils.py +0 -0
  57. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_utils/logger.py +0 -0
  58. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_utils/mount_utils.py +0 -0
  59. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_utils/name_utils.py +0 -0
  60. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_utils/package_utils.py +0 -0
  61. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_utils/pattern_utils.py +0 -0
  62. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_utils/rand_pb_testing.py +0 -0
  63. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_utils/shell_utils.py +0 -0
  64. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_utils/time_utils.py +0 -0
  65. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_vendor/__init__.py +0 -0
  66. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_vendor/a2wsgi_wsgi.py +0 -0
  67. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_vendor/cloudpickle.py +0 -0
  68. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_vendor/tblib.py +0 -0
  69. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/_watcher.py +0 -0
  70. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/app.py +0 -0
  71. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/app.pyi +0 -0
  72. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/builder/2023.12.312.txt +0 -0
  73. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/builder/2023.12.txt +0 -0
  74. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/builder/2024.04.txt +0 -0
  75. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/builder/2024.10.txt +0 -0
  76. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/builder/2025.06.txt +0 -0
  77. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/builder/PREVIEW.txt +0 -0
  78. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/builder/README.md +0 -0
  79. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/builder/base-images.json +0 -0
  80. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/call_graph.py +0 -0
  81. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/cli/__init__.py +0 -0
  82. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/cli/_download.py +0 -0
  83. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/cli/_traceback.py +0 -0
  84. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/cli/app.py +0 -0
  85. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/cli/cluster.py +0 -0
  86. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/cli/config.py +0 -0
  87. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/cli/container.py +0 -0
  88. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/cli/dict.py +0 -0
  89. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/cli/entry_point.py +0 -0
  90. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/cli/environment.py +0 -0
  91. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/cli/import_refs.py +0 -0
  92. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/cli/launch.py +0 -0
  93. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/cli/network_file_system.py +0 -0
  94. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/cli/profile.py +0 -0
  95. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/cli/programs/__init__.py +0 -0
  96. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/cli/programs/launch_instance_ssh.py +0 -0
  97. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/cli/programs/run_jupyter.py +0 -0
  98. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/cli/programs/run_marimo.py +0 -0
  99. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/cli/programs/vscode.py +0 -0
  100. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/cli/queues.py +0 -0
  101. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/cli/run.py +0 -0
  102. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/cli/secret.py +0 -0
  103. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/cli/token.py +0 -0
  104. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/cli/utils.py +0 -0
  105. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/cli/volume.py +0 -0
  106. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/client.py +0 -0
  107. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/cloud_bucket_mount.py +0 -0
  108. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/cloud_bucket_mount.pyi +0 -0
  109. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/cls.py +0 -0
  110. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/cls.pyi +0 -0
  111. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/config.py +0 -0
  112. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/container_process.py +0 -0
  113. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/container_process.pyi +0 -0
  114. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/dict.py +0 -0
  115. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/dict.pyi +0 -0
  116. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/environments.py +0 -0
  117. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/environments.pyi +0 -0
  118. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/exception.py +0 -0
  119. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/experimental/__init__.py +0 -0
  120. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/experimental/flash.py +0 -0
  121. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/experimental/flash.pyi +0 -0
  122. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/experimental/ipython.py +0 -0
  123. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/file_pattern_matcher.py +0 -0
  124. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/functions.py +0 -0
  125. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/gpu.py +0 -0
  126. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/image.py +0 -0
  127. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/image.pyi +0 -0
  128. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/io_streams.py +0 -0
  129. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/io_streams.pyi +0 -0
  130. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/mount.py +0 -0
  131. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/mount.pyi +0 -0
  132. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/network_file_system.py +0 -0
  133. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/network_file_system.pyi +0 -0
  134. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/object.py +0 -0
  135. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/object.pyi +0 -0
  136. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/output.py +0 -0
  137. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/partial_function.py +0 -0
  138. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/partial_function.pyi +0 -0
  139. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/proxy.py +0 -0
  140. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/proxy.pyi +0 -0
  141. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/py.typed +0 -0
  142. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/queue.py +0 -0
  143. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/queue.pyi +0 -0
  144. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/retries.py +0 -0
  145. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/runner.py +0 -0
  146. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/runner.pyi +0 -0
  147. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/running_app.py +0 -0
  148. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/schedule.py +0 -0
  149. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/scheduler_placement.py +0 -0
  150. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/secret.py +0 -0
  151. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/secret.pyi +0 -0
  152. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/serving.py +0 -0
  153. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/serving.pyi +0 -0
  154. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/snapshot.py +0 -0
  155. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/snapshot.pyi +0 -0
  156. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/stream_type.py +0 -0
  157. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/token_flow.py +0 -0
  158. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/token_flow.pyi +0 -0
  159. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/volume.py +0 -0
  160. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal/volume.pyi +0 -0
  161. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal.egg-info/SOURCES.txt +0 -0
  162. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal.egg-info/dependency_links.txt +0 -0
  163. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal.egg-info/entry_points.txt +0 -0
  164. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal.egg-info/requires.txt +0 -0
  165. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal.egg-info/top_level.txt +0 -0
  166. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal_docs/__init__.py +0 -0
  167. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal_docs/gen_cli_docs.py +0 -0
  168. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal_docs/gen_reference_docs.py +0 -0
  169. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal_docs/mdmd/__init__.py +0 -0
  170. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal_docs/mdmd/mdmd.py +0 -0
  171. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal_docs/mdmd/signatures.py +0 -0
  172. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal_proto/__init__.py +0 -0
  173. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal_proto/api.proto +0 -0
  174. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal_proto/api_grpc.py +0 -0
  175. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal_proto/api_pb2.py +0 -0
  176. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal_proto/api_pb2.pyi +0 -0
  177. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal_proto/api_pb2_grpc.py +0 -0
  178. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal_proto/api_pb2_grpc.pyi +0 -0
  179. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal_proto/modal_api_grpc.py +0 -0
  180. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal_proto/modal_options_grpc.py +0 -0
  181. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal_proto/options.proto +0 -0
  182. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal_proto/options_grpc.py +0 -0
  183. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal_proto/options_pb2.py +0 -0
  184. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal_proto/options_pb2.pyi +0 -0
  185. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal_proto/options_pb2_grpc.py +0 -0
  186. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal_proto/options_pb2_grpc.pyi +0 -0
  187. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal_proto/py.typed +0 -0
  188. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/modal_version/__main__.py +0 -0
  189. {modal-1.1.2.dev35 → modal-1.1.2.dev37}/pyproject.toml +0 -0
  190. {modal-1.1.2.dev35 → 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.dev35
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.dev35",
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.dev35",
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.
@@ -128,7 +128,7 @@ class _FileIO(Generic[T]):
128
128
 
129
129
  **Usage**
130
130
 
131
- ```python
131
+ ```python notest
132
132
  import modal
133
133
 
134
134
  app = modal.App.lookup("my-app", create_if_missing=True)
@@ -62,7 +62,7 @@ class _FileIO(typing.Generic[T]):
62
62
 
63
63
  **Usage**
64
64
 
65
- ```python
65
+ ```python notest
66
66
  import modal
67
67
 
68
68
  app = modal.App.lookup("my-app", create_if_missing=True)
@@ -232,7 +232,7 @@ class FileIO(typing.Generic[T]):
232
232
 
233
233
  **Usage**
234
234
 
235
- ```python
235
+ ```python notest
236
236
  import modal
237
237
 
238
238
  app = modal.App.lookup("my-app", create_if_missing=True)
@@ -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,
@@ -296,8 +296,9 @@ class _Sandbox(_Object, type_prefix="sb"):
296
296
  environment_name: Optional[str] = None, # *DEPRECATED* Optionally override the default environment
297
297
  ) -> "_Sandbox":
298
298
  """
299
- Create a new Sandbox to run untrusted, arbitrary code. The Sandbox's corresponding container
300
- will be created asynchronously.
299
+ Create a new Sandbox to run untrusted, arbitrary code.
300
+
301
+ The Sandbox's corresponding container will be created asynchronously.
301
302
 
302
303
  **Usage**
303
304
 
@@ -120,8 +120,9 @@ class _Sandbox(modal._object._Object):
120
120
  client: typing.Optional[modal.client._Client] = None,
121
121
  environment_name: typing.Optional[str] = None,
122
122
  ) -> _Sandbox:
123
- """Create a new Sandbox to run untrusted, arbitrary code. The Sandbox's corresponding container
124
- will be created asynchronously.
123
+ """Create a new Sandbox to run untrusted, arbitrary code.
124
+
125
+ The Sandbox's corresponding container will be created asynchronously.
125
126
 
126
127
  **Usage**
127
128
 
@@ -432,8 +433,9 @@ class Sandbox(modal.object.Object):
432
433
  client: typing.Optional[modal.client.Client] = None,
433
434
  environment_name: typing.Optional[str] = None,
434
435
  ) -> Sandbox:
435
- """Create a new Sandbox to run untrusted, arbitrary code. The Sandbox's corresponding container
436
- will be created asynchronously.
436
+ """Create a new Sandbox to run untrusted, arbitrary code.
437
+
438
+ The Sandbox's corresponding container will be created asynchronously.
437
439
 
438
440
  **Usage**
439
441
 
@@ -482,8 +484,9 @@ class Sandbox(modal.object.Object):
482
484
  client: typing.Optional[modal.client.Client] = None,
483
485
  environment_name: typing.Optional[str] = None,
484
486
  ) -> Sandbox:
485
- """Create a new Sandbox to run untrusted, arbitrary code. The Sandbox's corresponding container
486
- will be created asynchronously.
487
+ """Create a new Sandbox to run untrusted, arbitrary code.
488
+
489
+ The Sandbox's corresponding container will be created asynchronously.
487
490
 
488
491
  **Usage**
489
492
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.1.2.dev35
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.dev35"
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