modal 1.1.2.dev37__tar.gz → 1.1.2.dev41__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.dev37 → modal-1.1.2.dev41}/PKG-INFO +1 -1
  2. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_container_entrypoint.py +6 -0
  3. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_functions.py +2 -2
  4. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_runtime/asgi.py +3 -2
  5. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_runtime/container_io_manager.py +9 -4
  6. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_runtime/container_io_manager.pyi +32 -9
  7. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_utils/function_utils.py +4 -3
  8. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/app.py +2 -2
  9. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/app.pyi +4 -4
  10. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/client.pyi +2 -2
  11. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/functions.pyi +7 -7
  12. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/image.py +1 -1
  13. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/image.pyi +2 -2
  14. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/sandbox.py +3 -3
  15. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/sandbox.pyi +8 -8
  16. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/volume.py +6 -0
  17. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/volume.pyi +3 -0
  18. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal.egg-info/PKG-INFO +1 -1
  19. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal_version/__init__.py +1 -1
  20. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/LICENSE +0 -0
  21. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/README.md +0 -0
  22. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/__init__.py +0 -0
  23. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/__main__.py +0 -0
  24. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_clustered_functions.py +0 -0
  25. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_clustered_functions.pyi +0 -0
  26. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_ipython.py +0 -0
  27. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_location.py +0 -0
  28. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_object.py +0 -0
  29. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_output.py +0 -0
  30. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_partial_function.py +0 -0
  31. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_pty.py +0 -0
  32. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_resolver.py +0 -0
  33. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_resources.py +0 -0
  34. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_runtime/__init__.py +0 -0
  35. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_runtime/execution_context.py +0 -0
  36. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_runtime/execution_context.pyi +0 -0
  37. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_runtime/gpu_memory_snapshot.py +0 -0
  38. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_runtime/telemetry.py +0 -0
  39. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_runtime/user_code_imports.py +0 -0
  40. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_serialization.py +0 -0
  41. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_traceback.py +0 -0
  42. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_tunnel.py +0 -0
  43. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_tunnel.pyi +0 -0
  44. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_type_manager.py +0 -0
  45. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_utils/__init__.py +0 -0
  46. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_utils/app_utils.py +0 -0
  47. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_utils/async_utils.py +0 -0
  48. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_utils/auth_token_manager.py +0 -0
  49. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_utils/blob_utils.py +0 -0
  50. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_utils/bytes_io_segment_payload.py +0 -0
  51. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_utils/deprecation.py +0 -0
  52. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_utils/docker_utils.py +0 -0
  53. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_utils/git_utils.py +0 -0
  54. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_utils/grpc_testing.py +0 -0
  55. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_utils/grpc_utils.py +0 -0
  56. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_utils/hash_utils.py +0 -0
  57. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_utils/http_utils.py +0 -0
  58. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_utils/jwt_utils.py +0 -0
  59. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_utils/logger.py +0 -0
  60. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_utils/mount_utils.py +0 -0
  61. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_utils/name_utils.py +0 -0
  62. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_utils/package_utils.py +0 -0
  63. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_utils/pattern_utils.py +0 -0
  64. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_utils/rand_pb_testing.py +0 -0
  65. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_utils/shell_utils.py +0 -0
  66. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_utils/time_utils.py +0 -0
  67. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_vendor/__init__.py +0 -0
  68. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_vendor/a2wsgi_wsgi.py +0 -0
  69. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_vendor/cloudpickle.py +0 -0
  70. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_vendor/tblib.py +0 -0
  71. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/_watcher.py +0 -0
  72. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/builder/2023.12.312.txt +0 -0
  73. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/builder/2023.12.txt +0 -0
  74. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/builder/2024.04.txt +0 -0
  75. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/builder/2024.10.txt +0 -0
  76. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/builder/2025.06.txt +0 -0
  77. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/builder/PREVIEW.txt +0 -0
  78. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/builder/README.md +0 -0
  79. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/builder/base-images.json +0 -0
  80. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/call_graph.py +0 -0
  81. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/cli/__init__.py +0 -0
  82. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/cli/_download.py +0 -0
  83. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/cli/_traceback.py +0 -0
  84. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/cli/app.py +0 -0
  85. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/cli/cluster.py +0 -0
  86. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/cli/config.py +0 -0
  87. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/cli/container.py +0 -0
  88. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/cli/dict.py +0 -0
  89. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/cli/entry_point.py +0 -0
  90. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/cli/environment.py +0 -0
  91. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/cli/import_refs.py +0 -0
  92. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/cli/launch.py +0 -0
  93. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/cli/network_file_system.py +0 -0
  94. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/cli/profile.py +0 -0
  95. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/cli/programs/__init__.py +0 -0
  96. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/cli/programs/launch_instance_ssh.py +0 -0
  97. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/cli/programs/run_jupyter.py +0 -0
  98. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/cli/programs/run_marimo.py +0 -0
  99. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/cli/programs/vscode.py +0 -0
  100. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/cli/queues.py +0 -0
  101. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/cli/run.py +0 -0
  102. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/cli/secret.py +0 -0
  103. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/cli/token.py +0 -0
  104. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/cli/utils.py +0 -0
  105. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/cli/volume.py +0 -0
  106. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/client.py +0 -0
  107. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/cloud_bucket_mount.py +0 -0
  108. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/cloud_bucket_mount.pyi +0 -0
  109. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/cls.py +0 -0
  110. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/cls.pyi +0 -0
  111. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/config.py +0 -0
  112. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/container_process.py +0 -0
  113. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/container_process.pyi +0 -0
  114. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/dict.py +0 -0
  115. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/dict.pyi +0 -0
  116. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/environments.py +0 -0
  117. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/environments.pyi +0 -0
  118. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/exception.py +0 -0
  119. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/experimental/__init__.py +0 -0
  120. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/experimental/flash.py +0 -0
  121. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/experimental/flash.pyi +0 -0
  122. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/experimental/ipython.py +0 -0
  123. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/file_io.py +0 -0
  124. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/file_io.pyi +0 -0
  125. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/file_pattern_matcher.py +0 -0
  126. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/functions.py +0 -0
  127. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/gpu.py +0 -0
  128. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/io_streams.py +0 -0
  129. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/io_streams.pyi +0 -0
  130. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/mount.py +0 -0
  131. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/mount.pyi +0 -0
  132. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/network_file_system.py +0 -0
  133. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/network_file_system.pyi +0 -0
  134. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/object.py +0 -0
  135. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/object.pyi +0 -0
  136. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/output.py +0 -0
  137. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/parallel_map.py +0 -0
  138. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/parallel_map.pyi +0 -0
  139. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/partial_function.py +0 -0
  140. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/partial_function.pyi +0 -0
  141. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/proxy.py +0 -0
  142. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/proxy.pyi +0 -0
  143. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/py.typed +0 -0
  144. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/queue.py +0 -0
  145. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/queue.pyi +0 -0
  146. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/retries.py +0 -0
  147. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/runner.py +0 -0
  148. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/runner.pyi +0 -0
  149. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/running_app.py +0 -0
  150. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/schedule.py +0 -0
  151. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/scheduler_placement.py +0 -0
  152. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/secret.py +0 -0
  153. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/secret.pyi +0 -0
  154. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/serving.py +0 -0
  155. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/serving.pyi +0 -0
  156. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/snapshot.py +0 -0
  157. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/snapshot.pyi +0 -0
  158. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/stream_type.py +0 -0
  159. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/token_flow.py +0 -0
  160. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal/token_flow.pyi +0 -0
  161. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal.egg-info/SOURCES.txt +0 -0
  162. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal.egg-info/dependency_links.txt +0 -0
  163. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal.egg-info/entry_points.txt +0 -0
  164. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal.egg-info/requires.txt +0 -0
  165. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal.egg-info/top_level.txt +0 -0
  166. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal_docs/__init__.py +0 -0
  167. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal_docs/gen_cli_docs.py +0 -0
  168. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal_docs/gen_reference_docs.py +0 -0
  169. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal_docs/mdmd/__init__.py +0 -0
  170. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal_docs/mdmd/mdmd.py +0 -0
  171. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal_docs/mdmd/signatures.py +0 -0
  172. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal_proto/__init__.py +0 -0
  173. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal_proto/api.proto +0 -0
  174. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal_proto/api_grpc.py +0 -0
  175. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal_proto/api_pb2.py +0 -0
  176. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal_proto/api_pb2.pyi +0 -0
  177. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal_proto/api_pb2_grpc.py +0 -0
  178. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal_proto/api_pb2_grpc.pyi +0 -0
  179. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal_proto/modal_api_grpc.py +0 -0
  180. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal_proto/modal_options_grpc.py +0 -0
  181. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal_proto/options.proto +0 -0
  182. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal_proto/options_grpc.py +0 -0
  183. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal_proto/options_pb2.py +0 -0
  184. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal_proto/options_pb2.pyi +0 -0
  185. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal_proto/options_pb2_grpc.py +0 -0
  186. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal_proto/options_pb2_grpc.pyi +0 -0
  187. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal_proto/py.typed +0 -0
  188. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/modal_version/__main__.py +0 -0
  189. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/pyproject.toml +0 -0
  190. {modal-1.1.2.dev37 → modal-1.1.2.dev41}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.1.2.dev37
3
+ Version: 1.1.2.dev41
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -198,9 +198,12 @@ def call_function(
198
198
  # Send up to this many outputs at a time.
199
199
  current_function_call_id = execution_context.current_function_call_id()
200
200
  assert current_function_call_id is not None # Set above.
201
+ current_attempt_token = execution_context.current_attempt_token()
202
+ assert current_attempt_token is not None # Set above, but can be empty string.
201
203
  generator_queue: asyncio.Queue[Any] = await container_io_manager._queue_create.aio(1024)
202
204
  async with container_io_manager.generator_output_sender(
203
205
  current_function_call_id,
206
+ current_attempt_token,
204
207
  io_context.finalized_function.data_format,
205
208
  generator_queue,
206
209
  ):
@@ -247,9 +250,12 @@ def call_function(
247
250
  # Send up to this many outputs at a time.
248
251
  current_function_call_id = execution_context.current_function_call_id()
249
252
  assert current_function_call_id is not None # Set above.
253
+ current_attempt_token = execution_context.current_attempt_token()
254
+ assert current_attempt_token is not None # Set above, but can be empty string.
250
255
  generator_queue: asyncio.Queue[Any] = container_io_manager._queue_create(1024)
251
256
  with container_io_manager.generator_output_sender(
252
257
  current_function_call_id,
258
+ current_attempt_token,
253
259
  io_context.finalized_function.data_format,
254
260
  generator_queue,
255
261
  ):
@@ -473,7 +473,7 @@ class _InputPlaneInvocation:
473
473
  _stream_function_call_data(
474
474
  self.client,
475
475
  self.stub,
476
- "",
476
+ function_call_id=None,
477
477
  variant="data_out",
478
478
  attempt_token=self.attempt_token,
479
479
  ),
@@ -614,7 +614,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
614
614
  memory: Optional[Union[int, tuple[int, int]]] = None,
615
615
  proxy: Optional[_Proxy] = None,
616
616
  retries: Optional[Union[int, Retries]] = None,
617
- timeout: Optional[int] = None,
617
+ timeout: int = 300,
618
618
  min_containers: Optional[int] = None,
619
619
  max_containers: Optional[int] = None,
620
620
  buffer_containers: Optional[int] = None,
@@ -16,7 +16,7 @@ from modal.config import logger
16
16
  from modal.exception import ExecutionError, InvalidError
17
17
  from modal.experimental import stop_fetching_inputs
18
18
 
19
- from .execution_context import current_function_call_id
19
+ from .execution_context import current_attempt_token, current_function_call_id
20
20
 
21
21
  FIRST_MESSAGE_TIMEOUT_SECONDS = 5.0
22
22
 
@@ -106,6 +106,7 @@ def asgi_app_wrapper(asgi_app, container_io_manager) -> tuple[Callable[..., Asyn
106
106
  raise ExecutionError("Unpexected state in ASGI scope")
107
107
  scope["state"] = state
108
108
  function_call_id = current_function_call_id()
109
+ attempt_token = current_attempt_token()
109
110
  assert function_call_id, "internal error: function_call_id not set in asgi_app() scope"
110
111
 
111
112
  messages_from_app: asyncio.Queue[dict[str, Any]] = asyncio.Queue(1)
@@ -142,7 +143,7 @@ def asgi_app_wrapper(asgi_app, container_io_manager) -> tuple[Callable[..., Asyn
142
143
  # This initial message, "http.request" or "websocket.connect", should be sent
143
144
  # immediately after starting the ASGI app's function call. If it is not received, that
144
145
  # indicates a request cancellation or other abnormal circumstance.
145
- message_gen = container_io_manager.get_data_in.aio(function_call_id)
146
+ message_gen = container_io_manager.get_data_in.aio(function_call_id, attempt_token)
146
147
  first_message_task = asyncio.create_task(message_gen.__anext__())
147
148
 
148
149
  try:
@@ -483,18 +483,21 @@ class _ContainerIOManager:
483
483
  else {"data": data}
484
484
  )
485
485
 
486
- async def get_data_in(self, function_call_id: str) -> AsyncIterator[Any]:
486
+ async def get_data_in(self, function_call_id: str, attempt_token: Optional[str]) -> AsyncIterator[Any]:
487
487
  """Read from the `data_in` stream of a function call."""
488
488
  stub = self._client.stub
489
489
  if self.input_plane_server_url:
490
490
  stub = await self._client.get_stub(self.input_plane_server_url)
491
491
 
492
- async for data in _stream_function_call_data(self._client, stub, function_call_id, "data_in"):
492
+ async for data in _stream_function_call_data(
493
+ self._client, stub, function_call_id, variant="data_in", attempt_token=attempt_token
494
+ ):
493
495
  yield data
494
496
 
495
497
  async def put_data_out(
496
498
  self,
497
499
  function_call_id: str,
500
+ attempt_token: str,
498
501
  start_index: int,
499
502
  data_format: int,
500
503
  serialized_messages: list[Any],
@@ -515,6 +518,8 @@ class _ContainerIOManager:
515
518
  data_chunks.append(chunk)
516
519
 
517
520
  req = api_pb2.FunctionCallPutDataRequest(function_call_id=function_call_id, data_chunks=data_chunks)
521
+ if attempt_token:
522
+ req.attempt_token = attempt_token # oneof clears function_call_id.
518
523
 
519
524
  if self.input_plane_server_url:
520
525
  stub = await self._client.get_stub(self.input_plane_server_url)
@@ -524,7 +529,7 @@ class _ContainerIOManager:
524
529
 
525
530
  @asynccontextmanager
526
531
  async def generator_output_sender(
527
- self, function_call_id: str, data_format: int, message_rx: asyncio.Queue
532
+ self, function_call_id: str, attempt_token: str, data_format: int, message_rx: asyncio.Queue
528
533
  ) -> AsyncGenerator[None, None]:
529
534
  """Runs background task that feeds generator outputs into a function call's `data_out` stream."""
530
535
  GENERATOR_STOP_SENTINEL = Sentinel()
@@ -553,7 +558,7 @@ class _ContainerIOManager:
553
558
  else:
554
559
  serialized_messages.append(serialize_data_format(message, data_format))
555
560
  total_size += len(serialized_messages[-1]) + 512 # 512 bytes for estimated framing overhead
556
- await self.put_data_out(function_call_id, index, data_format, serialized_messages)
561
+ await self.put_data_out(function_call_id, attempt_token, index, data_format, serialized_messages)
557
562
  index += len(serialized_messages)
558
563
 
559
564
  task = asyncio.create_task(generator_output_task())
@@ -135,12 +135,19 @@ class _ContainerIOManager:
135
135
  async def _dynamic_concurrency_loop(self): ...
136
136
  def serialize_data_format(self, obj: typing.Any, data_format: int) -> bytes: ...
137
137
  async def format_blob_data(self, data: bytes) -> dict[str, typing.Any]: ...
138
- def get_data_in(self, function_call_id: str) -> collections.abc.AsyncIterator[typing.Any]:
138
+ def get_data_in(
139
+ self, function_call_id: str, attempt_token: typing.Optional[str]
140
+ ) -> collections.abc.AsyncIterator[typing.Any]:
139
141
  """Read from the `data_in` stream of a function call."""
140
142
  ...
141
143
 
142
144
  async def put_data_out(
143
- self, function_call_id: str, start_index: int, data_format: int, serialized_messages: list[typing.Any]
145
+ self,
146
+ function_call_id: str,
147
+ attempt_token: str,
148
+ start_index: int,
149
+ data_format: int,
150
+ serialized_messages: list[typing.Any],
144
151
  ) -> None:
145
152
  """Put data onto the `data_out` stream of a function call.
146
153
 
@@ -151,7 +158,7 @@ class _ContainerIOManager:
151
158
  ...
152
159
 
153
160
  def generator_output_sender(
154
- self, function_call_id: str, data_format: int, message_rx: asyncio.queues.Queue
161
+ self, function_call_id: str, attempt_token: str, data_format: int, message_rx: asyncio.queues.Queue
155
162
  ) -> typing.AsyncContextManager[None]:
156
163
  """Runs background task that feeds generator outputs into a function call's `data_out` stream."""
157
164
  ...
@@ -334,11 +341,15 @@ class ContainerIOManager:
334
341
  format_blob_data: __format_blob_data_spec[typing_extensions.Self]
335
342
 
336
343
  class __get_data_in_spec(typing_extensions.Protocol[SUPERSELF]):
337
- def __call__(self, /, function_call_id: str) -> typing.Iterator[typing.Any]:
344
+ def __call__(
345
+ self, /, function_call_id: str, attempt_token: typing.Optional[str]
346
+ ) -> typing.Iterator[typing.Any]:
338
347
  """Read from the `data_in` stream of a function call."""
339
348
  ...
340
349
 
341
- def aio(self, /, function_call_id: str) -> collections.abc.AsyncIterator[typing.Any]:
350
+ def aio(
351
+ self, /, function_call_id: str, attempt_token: typing.Optional[str]
352
+ ) -> collections.abc.AsyncIterator[typing.Any]:
342
353
  """Read from the `data_in` stream of a function call."""
343
354
  ...
344
355
 
@@ -346,7 +357,13 @@ class ContainerIOManager:
346
357
 
347
358
  class __put_data_out_spec(typing_extensions.Protocol[SUPERSELF]):
348
359
  def __call__(
349
- self, /, function_call_id: str, start_index: int, data_format: int, serialized_messages: list[typing.Any]
360
+ self,
361
+ /,
362
+ function_call_id: str,
363
+ attempt_token: str,
364
+ start_index: int,
365
+ data_format: int,
366
+ serialized_messages: list[typing.Any],
350
367
  ) -> None:
351
368
  """Put data onto the `data_out` stream of a function call.
352
369
 
@@ -357,7 +374,13 @@ class ContainerIOManager:
357
374
  ...
358
375
 
359
376
  async def aio(
360
- self, /, function_call_id: str, start_index: int, data_format: int, serialized_messages: list[typing.Any]
377
+ self,
378
+ /,
379
+ function_call_id: str,
380
+ attempt_token: str,
381
+ start_index: int,
382
+ data_format: int,
383
+ serialized_messages: list[typing.Any],
361
384
  ) -> None:
362
385
  """Put data onto the `data_out` stream of a function call.
363
386
 
@@ -371,13 +394,13 @@ class ContainerIOManager:
371
394
 
372
395
  class __generator_output_sender_spec(typing_extensions.Protocol[SUPERSELF]):
373
396
  def __call__(
374
- self, /, function_call_id: str, data_format: int, message_rx: asyncio.queues.Queue
397
+ self, /, function_call_id: str, attempt_token: str, data_format: int, message_rx: asyncio.queues.Queue
375
398
  ) -> synchronicity.combined_types.AsyncAndBlockingContextManager[None]:
376
399
  """Runs background task that feeds generator outputs into a function call's `data_out` stream."""
377
400
  ...
378
401
 
379
402
  def aio(
380
- self, /, function_call_id: str, data_format: int, message_rx: asyncio.queues.Queue
403
+ self, /, function_call_id: str, attempt_token: str, data_format: int, message_rx: asyncio.queues.Queue
381
404
  ) -> typing.AsyncContextManager[None]:
382
405
  """Runs background task that feeds generator outputs into a function call's `data_out` stream."""
383
406
  ...
@@ -392,8 +392,8 @@ async def _stream_function_call_data(
392
392
  attempt_token: Optional[str] = None,
393
393
  ) -> AsyncGenerator[Any, None]:
394
394
  """Read from the `data_in` or `data_out` stream of a function call."""
395
- if function_call_id is None and attempt_token is None:
396
- raise ValueError("function_call_id or attempt_token is required for data_out stream")
395
+ if not function_call_id and not attempt_token:
396
+ raise ValueError("function_call_id or attempt_token is required to read from a data stream")
397
397
 
398
398
  if stub is None:
399
399
  stub = client.stub
@@ -415,8 +415,9 @@ async def _stream_function_call_data(
415
415
  req = api_pb2.FunctionCallGetDataRequest(
416
416
  function_call_id=function_call_id,
417
417
  last_index=last_index,
418
- attempt_token=attempt_token,
419
418
  )
419
+ if attempt_token:
420
+ req.attempt_token = attempt_token # oneof clears function_call_id.
420
421
  try:
421
422
  async for chunk in stub_fn.unary_stream(req):
422
423
  if chunk.index <= last_index:
@@ -641,7 +641,7 @@ class _App:
641
641
  scaledown_window: Optional[int] = None, # Max time (in seconds) a container can remain idle while scaling down.
642
642
  proxy: Optional[_Proxy] = None, # Reference to a Modal Proxy to use in front of this function.
643
643
  retries: Optional[Union[int, Retries]] = None, # Number of times to retry each input in case of failure.
644
- timeout: Optional[int] = None, # Maximum execution time of the function in seconds.
644
+ timeout: int = 300, # Maximum execution time of the function in seconds.
645
645
  name: Optional[str] = None, # Sets the Modal name of the function within the app
646
646
  is_generator: Optional[
647
647
  bool
@@ -869,7 +869,7 @@ class _App:
869
869
  scaledown_window: Optional[int] = None, # Max time (in seconds) a container can remain idle while scaling down.
870
870
  proxy: Optional[_Proxy] = None, # Reference to a Modal Proxy to use in front of this function.
871
871
  retries: Optional[Union[int, Retries]] = None, # Number of times to retry each input in case of failure.
872
- timeout: Optional[int] = None, # Maximum execution time of the function in seconds.
872
+ timeout: int = 300, # Maximum execution time of the function in seconds.
873
873
  cloud: Optional[str] = None, # Cloud provider to run the function on. Possible values are aws, gcp, oci, auto.
874
874
  region: Optional[Union[str, Sequence[str]]] = None, # Region or regions to run the function on.
875
875
  enable_memory_snapshot: bool = False, # Enable memory checkpointing for faster cold starts.
@@ -410,7 +410,7 @@ class _App:
410
410
  scaledown_window: typing.Optional[int] = None,
411
411
  proxy: typing.Optional[modal.proxy._Proxy] = None,
412
412
  retries: typing.Union[int, modal.retries.Retries, None] = None,
413
- timeout: typing.Optional[int] = None,
413
+ timeout: int = 300,
414
414
  name: typing.Optional[str] = None,
415
415
  is_generator: typing.Optional[bool] = None,
416
416
  cloud: typing.Optional[str] = None,
@@ -463,7 +463,7 @@ class _App:
463
463
  scaledown_window: typing.Optional[int] = None,
464
464
  proxy: typing.Optional[modal.proxy._Proxy] = None,
465
465
  retries: typing.Union[int, modal.retries.Retries, None] = None,
466
- timeout: typing.Optional[int] = None,
466
+ timeout: int = 300,
467
467
  cloud: typing.Optional[str] = None,
468
468
  region: typing.Union[str, collections.abc.Sequence[str], None] = None,
469
469
  enable_memory_snapshot: bool = False,
@@ -1013,7 +1013,7 @@ class App:
1013
1013
  scaledown_window: typing.Optional[int] = None,
1014
1014
  proxy: typing.Optional[modal.proxy.Proxy] = None,
1015
1015
  retries: typing.Union[int, modal.retries.Retries, None] = None,
1016
- timeout: typing.Optional[int] = None,
1016
+ timeout: int = 300,
1017
1017
  name: typing.Optional[str] = None,
1018
1018
  is_generator: typing.Optional[bool] = None,
1019
1019
  cloud: typing.Optional[str] = None,
@@ -1066,7 +1066,7 @@ class App:
1066
1066
  scaledown_window: typing.Optional[int] = None,
1067
1067
  proxy: typing.Optional[modal.proxy.Proxy] = None,
1068
1068
  retries: typing.Union[int, modal.retries.Retries, None] = None,
1069
- timeout: typing.Optional[int] = None,
1069
+ timeout: int = 300,
1070
1070
  cloud: typing.Optional[str] = None,
1071
1071
  region: typing.Union[str, collections.abc.Sequence[str], None] = None,
1072
1072
  enable_memory_snapshot: bool = False,
@@ -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.dev37",
36
+ version: str = "1.1.2.dev41",
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.dev37",
167
+ version: str = "1.1.2.dev41",
168
168
  ):
169
169
  """mdmd:hidden
170
170
  The Modal client object is not intended to be instantiated directly by users.
@@ -84,7 +84,7 @@ class Function(
84
84
  memory: typing.Union[int, tuple[int, int], None] = None,
85
85
  proxy: typing.Optional[modal.proxy.Proxy] = None,
86
86
  retries: typing.Union[int, modal.retries.Retries, None] = None,
87
- timeout: typing.Optional[int] = None,
87
+ timeout: int = 300,
88
88
  min_containers: typing.Optional[int] = None,
89
89
  max_containers: typing.Optional[int] = None,
90
90
  buffer_containers: typing.Optional[int] = None,
@@ -433,7 +433,7 @@ class Function(
433
433
 
434
434
  _call_generator: ___call_generator_spec[typing_extensions.Self]
435
435
 
436
- class __remote_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER, SUPERSELF]):
436
+ class __remote_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
437
437
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER:
438
438
  """Calls the function remotely, executing it with the given arguments and returning the execution's result."""
439
439
  ...
@@ -442,7 +442,7 @@ class Function(
442
442
  """Calls the function remotely, executing it with the given arguments and returning the execution's result."""
443
443
  ...
444
444
 
445
- remote: __remote_spec[modal._functions.ReturnType, modal._functions.P, typing_extensions.Self]
445
+ remote: __remote_spec[modal._functions.P, modal._functions.ReturnType, typing_extensions.Self]
446
446
 
447
447
  class __remote_gen_spec(typing_extensions.Protocol[SUPERSELF]):
448
448
  def __call__(self, /, *args, **kwargs) -> typing.Generator[typing.Any, None, None]:
@@ -469,7 +469,7 @@ class Function(
469
469
  """
470
470
  ...
471
471
 
472
- class ___experimental_spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER, SUPERSELF]):
472
+ class ___experimental_spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
473
473
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]:
474
474
  """[Experimental] Calls the function with the given arguments, without waiting for the results.
475
475
 
@@ -493,7 +493,7 @@ class Function(
493
493
  ...
494
494
 
495
495
  _experimental_spawn: ___experimental_spawn_spec[
496
- modal._functions.ReturnType, modal._functions.P, typing_extensions.Self
496
+ modal._functions.P, modal._functions.ReturnType, typing_extensions.Self
497
497
  ]
498
498
 
499
499
  class ___spawn_map_inner_spec(typing_extensions.Protocol[P_INNER, SUPERSELF]):
@@ -502,7 +502,7 @@ class Function(
502
502
 
503
503
  _spawn_map_inner: ___spawn_map_inner_spec[modal._functions.P, typing_extensions.Self]
504
504
 
505
- class __spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER, SUPERSELF]):
505
+ class __spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
506
506
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]:
507
507
  """Calls the function with the given arguments, without waiting for the results.
508
508
 
@@ -523,7 +523,7 @@ class Function(
523
523
  """
524
524
  ...
525
525
 
526
- spawn: __spawn_spec[modal._functions.ReturnType, modal._functions.P, typing_extensions.Self]
526
+ spawn: __spawn_spec[modal._functions.P, modal._functions.ReturnType, typing_extensions.Self]
527
527
 
528
528
  def get_raw_f(self) -> collections.abc.Callable[..., typing.Any]:
529
529
  """Return the inner Python object wrapped by this Modal Function."""
@@ -2114,7 +2114,7 @@ class _Image(_Object, type_prefix="im"):
2114
2114
  gpu: Union[GPU_T, list[GPU_T]] = None, # Requested GPU or or list of acceptable GPUs( e.g. ["A10", "A100"])
2115
2115
  cpu: Optional[float] = None, # How many CPU cores to request. This is a soft limit.
2116
2116
  memory: Optional[int] = None, # How much memory to request, in MiB. This is a soft limit.
2117
- timeout: Optional[int] = 60 * 60, # Maximum execution time of the function in seconds.
2117
+ timeout: int = 60 * 60, # Maximum execution time of the function in seconds.
2118
2118
  cloud: Optional[str] = None, # Cloud provider to run the function on. Possible values are aws, gcp, oci, auto.
2119
2119
  region: Optional[Union[str, Sequence[str]]] = None, # Region or regions to run the function on.
2120
2120
  force_build: bool = False, # Ignore cached builds, similar to 'docker build --no-cache'
@@ -845,7 +845,7 @@ class _Image(modal._object._Object):
845
845
  gpu: typing.Union[None, str, modal.gpu._GPUConfig, list[typing.Union[None, str, modal.gpu._GPUConfig]]] = None,
846
846
  cpu: typing.Optional[float] = None,
847
847
  memory: typing.Optional[int] = None,
848
- timeout: typing.Optional[int] = 3600,
848
+ timeout: int = 3600,
849
849
  cloud: typing.Optional[str] = None,
850
850
  region: typing.Union[str, collections.abc.Sequence[str], None] = None,
851
851
  force_build: bool = False,
@@ -1689,7 +1689,7 @@ class Image(modal.object.Object):
1689
1689
  gpu: typing.Union[None, str, modal.gpu._GPUConfig, list[typing.Union[None, str, modal.gpu._GPUConfig]]] = None,
1690
1690
  cpu: typing.Optional[float] = None,
1691
1691
  memory: typing.Optional[int] = None,
1692
- timeout: typing.Optional[int] = 3600,
1692
+ timeout: int = 3600,
1693
1693
  cloud: typing.Optional[str] = None,
1694
1694
  region: typing.Union[str, collections.abc.Sequence[str], None] = None,
1695
1695
  force_build: bool = False,
@@ -108,7 +108,7 @@ class _Sandbox(_Object, type_prefix="sb"):
108
108
  image: _Image,
109
109
  secrets: Sequence[_Secret],
110
110
  name: Optional[str] = None,
111
- timeout: Optional[int] = None,
111
+ timeout: int = 300,
112
112
  workdir: Optional[str] = None,
113
113
  gpu: GPU_T = None,
114
114
  cloud: Optional[str] = None,
@@ -257,7 +257,7 @@ class _Sandbox(_Object, type_prefix="sb"):
257
257
  image: Optional[_Image] = None, # The image to run as the container for the sandbox.
258
258
  secrets: Sequence[_Secret] = (), # Environment variables to inject into the sandbox.
259
259
  network_file_systems: dict[Union[str, os.PathLike], _NetworkFileSystem] = {},
260
- timeout: Optional[int] = None, # Maximum execution time of the sandbox in seconds.
260
+ timeout: int = 300, # Maximum execution time of the sandbox in seconds.
261
261
  workdir: Optional[str] = None, # Working directory of the sandbox.
262
262
  gpu: GPU_T = None,
263
263
  cloud: Optional[str] = None,
@@ -355,7 +355,7 @@ class _Sandbox(_Object, type_prefix="sb"):
355
355
  secrets: Sequence[_Secret] = (), # Environment variables to inject into the sandbox.
356
356
  mounts: Sequence[_Mount] = (),
357
357
  network_file_systems: dict[Union[str, os.PathLike], _NetworkFileSystem] = {},
358
- timeout: Optional[int] = None, # Maximum execution time of the sandbox in seconds.
358
+ timeout: int = 300, # Maximum execution time of the sandbox in seconds.
359
359
  workdir: Optional[str] = None, # Working directory of the sandbox.
360
360
  gpu: GPU_T = None,
361
361
  cloud: Optional[str] = None,
@@ -59,7 +59,7 @@ class _Sandbox(modal._object._Object):
59
59
  image: modal.image._Image,
60
60
  secrets: collections.abc.Sequence[modal.secret._Secret],
61
61
  name: typing.Optional[str] = None,
62
- timeout: typing.Optional[int] = None,
62
+ timeout: int = 300,
63
63
  workdir: typing.Optional[str] = None,
64
64
  gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
65
65
  cloud: typing.Optional[str] = None,
@@ -95,7 +95,7 @@ class _Sandbox(modal._object._Object):
95
95
  image: typing.Optional[modal.image._Image] = None,
96
96
  secrets: collections.abc.Sequence[modal.secret._Secret] = (),
97
97
  network_file_systems: dict[typing.Union[str, os.PathLike], modal.network_file_system._NetworkFileSystem] = {},
98
- timeout: typing.Optional[int] = None,
98
+ timeout: int = 300,
99
99
  workdir: typing.Optional[str] = None,
100
100
  gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
101
101
  cloud: typing.Optional[str] = None,
@@ -144,7 +144,7 @@ class _Sandbox(modal._object._Object):
144
144
  secrets: collections.abc.Sequence[modal.secret._Secret] = (),
145
145
  mounts: collections.abc.Sequence[modal.mount._Mount] = (),
146
146
  network_file_systems: dict[typing.Union[str, os.PathLike], modal.network_file_system._NetworkFileSystem] = {},
147
- timeout: typing.Optional[int] = None,
147
+ timeout: int = 300,
148
148
  workdir: typing.Optional[str] = None,
149
149
  gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
150
150
  cloud: typing.Optional[str] = None,
@@ -369,7 +369,7 @@ class Sandbox(modal.object.Object):
369
369
  image: modal.image.Image,
370
370
  secrets: collections.abc.Sequence[modal.secret.Secret],
371
371
  name: typing.Optional[str] = None,
372
- timeout: typing.Optional[int] = None,
372
+ timeout: int = 300,
373
373
  workdir: typing.Optional[str] = None,
374
374
  gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
375
375
  cloud: typing.Optional[str] = None,
@@ -408,7 +408,7 @@ class Sandbox(modal.object.Object):
408
408
  network_file_systems: dict[
409
409
  typing.Union[str, os.PathLike], modal.network_file_system.NetworkFileSystem
410
410
  ] = {},
411
- timeout: typing.Optional[int] = None,
411
+ timeout: int = 300,
412
412
  workdir: typing.Optional[str] = None,
413
413
  gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
414
414
  cloud: typing.Optional[str] = None,
@@ -459,7 +459,7 @@ class Sandbox(modal.object.Object):
459
459
  network_file_systems: dict[
460
460
  typing.Union[str, os.PathLike], modal.network_file_system.NetworkFileSystem
461
461
  ] = {},
462
- timeout: typing.Optional[int] = None,
462
+ timeout: int = 300,
463
463
  workdir: typing.Optional[str] = None,
464
464
  gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
465
465
  cloud: typing.Optional[str] = None,
@@ -514,7 +514,7 @@ class Sandbox(modal.object.Object):
514
514
  network_file_systems: dict[
515
515
  typing.Union[str, os.PathLike], modal.network_file_system.NetworkFileSystem
516
516
  ] = {},
517
- timeout: typing.Optional[int] = None,
517
+ timeout: int = 300,
518
518
  workdir: typing.Optional[str] = None,
519
519
  gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
520
520
  cloud: typing.Optional[str] = None,
@@ -550,7 +550,7 @@ class Sandbox(modal.object.Object):
550
550
  network_file_systems: dict[
551
551
  typing.Union[str, os.PathLike], modal.network_file_system.NetworkFileSystem
552
552
  ] = {},
553
- timeout: typing.Optional[int] = None,
553
+ timeout: int = 300,
554
554
  workdir: typing.Optional[str] = None,
555
555
  gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
556
556
  cloud: typing.Optional[str] = None,
@@ -120,6 +120,7 @@ class _VolumeManager:
120
120
  async def create(
121
121
  name: str, # Name to use for the new Volume
122
122
  *,
123
+ version: Optional[int] = None, # Experimental: Configure the backend VolumeFS version
123
124
  allow_existing: bool = False, # If True, no-op when the Volume already exists
124
125
  environment_name: Optional[str] = None, # Uses active environment if not specified
125
126
  client: Optional[_Client] = None, # Optional client with Modal credentials
@@ -154,10 +155,15 @@ class _VolumeManager:
154
155
  if allow_existing
155
156
  else api_pb2.OBJECT_CREATION_TYPE_CREATE_FAIL_IF_EXISTS
156
157
  )
158
+
159
+ if version is not None and version not in {1, 2}:
160
+ raise InvalidError("VolumeFS version must be either 1 or 2")
161
+
157
162
  req = api_pb2.VolumeGetOrCreateRequest(
158
163
  deployment_name=name,
159
164
  environment_name=_get_environment_name(environment_name),
160
165
  object_creation_type=object_creation_type,
166
+ version=version,
161
167
  )
162
168
  try:
163
169
  await retry_transient_errors(client.stub.VolumeGetOrCreate, req)
@@ -86,6 +86,7 @@ class _VolumeManager:
86
86
  async def create(
87
87
  name: str,
88
88
  *,
89
+ version: typing.Optional[int] = None,
89
90
  allow_existing: bool = False,
90
91
  environment_name: typing.Optional[str] = None,
91
92
  client: typing.Optional[modal.client._Client] = None,
@@ -186,6 +187,7 @@ class VolumeManager:
186
187
  /,
187
188
  name: str,
188
189
  *,
190
+ version: typing.Optional[int] = None,
189
191
  allow_existing: bool = False,
190
192
  environment_name: typing.Optional[str] = None,
191
193
  client: typing.Optional[modal.client.Client] = None,
@@ -220,6 +222,7 @@ class VolumeManager:
220
222
  /,
221
223
  name: str,
222
224
  *,
225
+ version: typing.Optional[int] = None,
223
226
  allow_existing: bool = False,
224
227
  environment_name: typing.Optional[str] = None,
225
228
  client: typing.Optional[modal.client.Client] = None,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.1.2.dev37
3
+ Version: 1.1.2.dev41
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.dev37"
4
+ __version__ = "1.1.2.dev41"
File without changes
File without changes
File without changes