modAL 1.1.3__tar.gz → 1.1.3.dev0__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.3 → modal-1.1.3.dev0}/PKG-INFO +1 -1
  2. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_functions.py +25 -48
  3. {modal-1.1.3 → modal-1.1.3.dev0}/modal/client.pyi +10 -2
  4. {modal-1.1.3 → modal-1.1.3.dev0}/modal/functions.pyi +6 -6
  5. {modal-1.1.3 → modal-1.1.3.dev0}/modal/image.py +1 -2
  6. {modal-1.1.3 → modal-1.1.3.dev0}/modal/image.pyi +2 -4
  7. {modal-1.1.3 → modal-1.1.3.dev0}/modal/parallel_map.py +2 -21
  8. {modal-1.1.3 → modal-1.1.3.dev0}/modal/parallel_map.pyi +0 -3
  9. {modal-1.1.3 → modal-1.1.3.dev0}/modal.egg-info/PKG-INFO +1 -1
  10. {modal-1.1.3 → modal-1.1.3.dev0}/modal_proto/api.proto +3 -8
  11. {modal-1.1.3 → modal-1.1.3.dev0}/modal_proto/api_pb2.py +493 -493
  12. {modal-1.1.3 → modal-1.1.3.dev0}/modal_proto/api_pb2.pyi +6 -15
  13. {modal-1.1.3 → modal-1.1.3.dev0}/modal_version/__init__.py +1 -1
  14. {modal-1.1.3 → modal-1.1.3.dev0}/LICENSE +0 -0
  15. {modal-1.1.3 → modal-1.1.3.dev0}/README.md +0 -0
  16. {modal-1.1.3 → modal-1.1.3.dev0}/modal/__init__.py +0 -0
  17. {modal-1.1.3 → modal-1.1.3.dev0}/modal/__main__.py +0 -0
  18. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_clustered_functions.py +0 -0
  19. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_clustered_functions.pyi +0 -0
  20. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_container_entrypoint.py +0 -0
  21. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_ipython.py +0 -0
  22. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_location.py +0 -0
  23. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_object.py +0 -0
  24. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_output.py +0 -0
  25. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_partial_function.py +0 -0
  26. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_pty.py +0 -0
  27. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_resolver.py +0 -0
  28. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_resources.py +0 -0
  29. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_runtime/__init__.py +0 -0
  30. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_runtime/asgi.py +0 -0
  31. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_runtime/container_io_manager.py +0 -0
  32. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_runtime/container_io_manager.pyi +0 -0
  33. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_runtime/execution_context.py +0 -0
  34. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_runtime/execution_context.pyi +0 -0
  35. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_runtime/gpu_memory_snapshot.py +0 -0
  36. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_runtime/telemetry.py +0 -0
  37. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_runtime/user_code_imports.py +0 -0
  38. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_serialization.py +0 -0
  39. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_traceback.py +0 -0
  40. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_tunnel.py +0 -0
  41. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_tunnel.pyi +0 -0
  42. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_type_manager.py +0 -0
  43. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_utils/__init__.py +0 -0
  44. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_utils/app_utils.py +0 -0
  45. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_utils/async_utils.py +0 -0
  46. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_utils/auth_token_manager.py +0 -0
  47. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_utils/blob_utils.py +0 -0
  48. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_utils/bytes_io_segment_payload.py +0 -0
  49. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_utils/deprecation.py +0 -0
  50. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_utils/docker_utils.py +0 -0
  51. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_utils/function_utils.py +0 -0
  52. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_utils/git_utils.py +0 -0
  53. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_utils/grpc_testing.py +0 -0
  54. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_utils/grpc_utils.py +0 -0
  55. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_utils/hash_utils.py +0 -0
  56. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_utils/http_utils.py +0 -0
  57. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_utils/jwt_utils.py +0 -0
  58. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_utils/logger.py +0 -0
  59. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_utils/mount_utils.py +0 -0
  60. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_utils/name_utils.py +0 -0
  61. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_utils/package_utils.py +0 -0
  62. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_utils/pattern_utils.py +0 -0
  63. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_utils/rand_pb_testing.py +0 -0
  64. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_utils/shell_utils.py +0 -0
  65. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_utils/time_utils.py +0 -0
  66. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_vendor/__init__.py +0 -0
  67. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_vendor/a2wsgi_wsgi.py +0 -0
  68. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_vendor/cloudpickle.py +0 -0
  69. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_vendor/tblib.py +0 -0
  70. {modal-1.1.3 → modal-1.1.3.dev0}/modal/_watcher.py +0 -0
  71. {modal-1.1.3 → modal-1.1.3.dev0}/modal/app.py +0 -0
  72. {modal-1.1.3 → modal-1.1.3.dev0}/modal/app.pyi +0 -0
  73. {modal-1.1.3 → modal-1.1.3.dev0}/modal/builder/2023.12.312.txt +0 -0
  74. {modal-1.1.3 → modal-1.1.3.dev0}/modal/builder/2023.12.txt +0 -0
  75. {modal-1.1.3 → modal-1.1.3.dev0}/modal/builder/2024.04.txt +0 -0
  76. {modal-1.1.3 → modal-1.1.3.dev0}/modal/builder/2024.10.txt +0 -0
  77. {modal-1.1.3 → modal-1.1.3.dev0}/modal/builder/2025.06.txt +0 -0
  78. {modal-1.1.3 → modal-1.1.3.dev0}/modal/builder/PREVIEW.txt +0 -0
  79. {modal-1.1.3 → modal-1.1.3.dev0}/modal/builder/README.md +0 -0
  80. {modal-1.1.3 → modal-1.1.3.dev0}/modal/builder/base-images.json +0 -0
  81. {modal-1.1.3 → modal-1.1.3.dev0}/modal/call_graph.py +0 -0
  82. {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/__init__.py +0 -0
  83. {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/_download.py +0 -0
  84. {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/_traceback.py +0 -0
  85. {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/app.py +0 -0
  86. {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/cluster.py +0 -0
  87. {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/config.py +0 -0
  88. {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/container.py +0 -0
  89. {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/dict.py +0 -0
  90. {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/entry_point.py +0 -0
  91. {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/environment.py +0 -0
  92. {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/import_refs.py +0 -0
  93. {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/launch.py +0 -0
  94. {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/network_file_system.py +0 -0
  95. {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/profile.py +0 -0
  96. {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/programs/__init__.py +0 -0
  97. {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/programs/launch_instance_ssh.py +0 -0
  98. {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/programs/run_jupyter.py +0 -0
  99. {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/programs/run_marimo.py +0 -0
  100. {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/programs/vscode.py +0 -0
  101. {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/queues.py +0 -0
  102. {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/run.py +0 -0
  103. {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/secret.py +0 -0
  104. {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/token.py +0 -0
  105. {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/utils.py +0 -0
  106. {modal-1.1.3 → modal-1.1.3.dev0}/modal/cli/volume.py +0 -0
  107. {modal-1.1.3 → modal-1.1.3.dev0}/modal/client.py +0 -0
  108. {modal-1.1.3 → modal-1.1.3.dev0}/modal/cloud_bucket_mount.py +0 -0
  109. {modal-1.1.3 → modal-1.1.3.dev0}/modal/cloud_bucket_mount.pyi +0 -0
  110. {modal-1.1.3 → modal-1.1.3.dev0}/modal/cls.py +0 -0
  111. {modal-1.1.3 → modal-1.1.3.dev0}/modal/cls.pyi +0 -0
  112. {modal-1.1.3 → modal-1.1.3.dev0}/modal/config.py +0 -0
  113. {modal-1.1.3 → modal-1.1.3.dev0}/modal/container_process.py +0 -0
  114. {modal-1.1.3 → modal-1.1.3.dev0}/modal/container_process.pyi +0 -0
  115. {modal-1.1.3 → modal-1.1.3.dev0}/modal/dict.py +0 -0
  116. {modal-1.1.3 → modal-1.1.3.dev0}/modal/dict.pyi +0 -0
  117. {modal-1.1.3 → modal-1.1.3.dev0}/modal/environments.py +0 -0
  118. {modal-1.1.3 → modal-1.1.3.dev0}/modal/environments.pyi +0 -0
  119. {modal-1.1.3 → modal-1.1.3.dev0}/modal/exception.py +0 -0
  120. {modal-1.1.3 → modal-1.1.3.dev0}/modal/experimental/__init__.py +0 -0
  121. {modal-1.1.3 → modal-1.1.3.dev0}/modal/experimental/flash.py +0 -0
  122. {modal-1.1.3 → modal-1.1.3.dev0}/modal/experimental/flash.pyi +0 -0
  123. {modal-1.1.3 → modal-1.1.3.dev0}/modal/experimental/ipython.py +0 -0
  124. {modal-1.1.3 → modal-1.1.3.dev0}/modal/file_io.py +0 -0
  125. {modal-1.1.3 → modal-1.1.3.dev0}/modal/file_io.pyi +0 -0
  126. {modal-1.1.3 → modal-1.1.3.dev0}/modal/file_pattern_matcher.py +0 -0
  127. {modal-1.1.3 → modal-1.1.3.dev0}/modal/functions.py +0 -0
  128. {modal-1.1.3 → modal-1.1.3.dev0}/modal/gpu.py +0 -0
  129. {modal-1.1.3 → modal-1.1.3.dev0}/modal/io_streams.py +0 -0
  130. {modal-1.1.3 → modal-1.1.3.dev0}/modal/io_streams.pyi +0 -0
  131. {modal-1.1.3 → modal-1.1.3.dev0}/modal/mount.py +0 -0
  132. {modal-1.1.3 → modal-1.1.3.dev0}/modal/mount.pyi +0 -0
  133. {modal-1.1.3 → modal-1.1.3.dev0}/modal/network_file_system.py +0 -0
  134. {modal-1.1.3 → modal-1.1.3.dev0}/modal/network_file_system.pyi +0 -0
  135. {modal-1.1.3 → modal-1.1.3.dev0}/modal/object.py +0 -0
  136. {modal-1.1.3 → modal-1.1.3.dev0}/modal/object.pyi +0 -0
  137. {modal-1.1.3 → modal-1.1.3.dev0}/modal/output.py +0 -0
  138. {modal-1.1.3 → modal-1.1.3.dev0}/modal/partial_function.py +0 -0
  139. {modal-1.1.3 → modal-1.1.3.dev0}/modal/partial_function.pyi +0 -0
  140. {modal-1.1.3 → modal-1.1.3.dev0}/modal/proxy.py +0 -0
  141. {modal-1.1.3 → modal-1.1.3.dev0}/modal/proxy.pyi +0 -0
  142. {modal-1.1.3 → modal-1.1.3.dev0}/modal/py.typed +0 -0
  143. {modal-1.1.3 → modal-1.1.3.dev0}/modal/queue.py +0 -0
  144. {modal-1.1.3 → modal-1.1.3.dev0}/modal/queue.pyi +0 -0
  145. {modal-1.1.3 → modal-1.1.3.dev0}/modal/retries.py +0 -0
  146. {modal-1.1.3 → modal-1.1.3.dev0}/modal/runner.py +0 -0
  147. {modal-1.1.3 → modal-1.1.3.dev0}/modal/runner.pyi +0 -0
  148. {modal-1.1.3 → modal-1.1.3.dev0}/modal/running_app.py +0 -0
  149. {modal-1.1.3 → modal-1.1.3.dev0}/modal/sandbox.py +0 -0
  150. {modal-1.1.3 → modal-1.1.3.dev0}/modal/sandbox.pyi +0 -0
  151. {modal-1.1.3 → modal-1.1.3.dev0}/modal/schedule.py +0 -0
  152. {modal-1.1.3 → modal-1.1.3.dev0}/modal/scheduler_placement.py +0 -0
  153. {modal-1.1.3 → modal-1.1.3.dev0}/modal/secret.py +0 -0
  154. {modal-1.1.3 → modal-1.1.3.dev0}/modal/secret.pyi +0 -0
  155. {modal-1.1.3 → modal-1.1.3.dev0}/modal/serving.py +0 -0
  156. {modal-1.1.3 → modal-1.1.3.dev0}/modal/serving.pyi +0 -0
  157. {modal-1.1.3 → modal-1.1.3.dev0}/modal/snapshot.py +0 -0
  158. {modal-1.1.3 → modal-1.1.3.dev0}/modal/snapshot.pyi +0 -0
  159. {modal-1.1.3 → modal-1.1.3.dev0}/modal/stream_type.py +0 -0
  160. {modal-1.1.3 → modal-1.1.3.dev0}/modal/token_flow.py +0 -0
  161. {modal-1.1.3 → modal-1.1.3.dev0}/modal/token_flow.pyi +0 -0
  162. {modal-1.1.3 → modal-1.1.3.dev0}/modal/volume.py +0 -0
  163. {modal-1.1.3 → modal-1.1.3.dev0}/modal/volume.pyi +0 -0
  164. {modal-1.1.3 → modal-1.1.3.dev0}/modal.egg-info/SOURCES.txt +0 -0
  165. {modal-1.1.3 → modal-1.1.3.dev0}/modal.egg-info/dependency_links.txt +0 -0
  166. {modal-1.1.3 → modal-1.1.3.dev0}/modal.egg-info/entry_points.txt +0 -0
  167. {modal-1.1.3 → modal-1.1.3.dev0}/modal.egg-info/requires.txt +0 -0
  168. {modal-1.1.3 → modal-1.1.3.dev0}/modal.egg-info/top_level.txt +0 -0
  169. {modal-1.1.3 → modal-1.1.3.dev0}/modal_docs/__init__.py +0 -0
  170. {modal-1.1.3 → modal-1.1.3.dev0}/modal_docs/gen_cli_docs.py +0 -0
  171. {modal-1.1.3 → modal-1.1.3.dev0}/modal_docs/gen_reference_docs.py +0 -0
  172. {modal-1.1.3 → modal-1.1.3.dev0}/modal_docs/mdmd/__init__.py +0 -0
  173. {modal-1.1.3 → modal-1.1.3.dev0}/modal_docs/mdmd/mdmd.py +0 -0
  174. {modal-1.1.3 → modal-1.1.3.dev0}/modal_docs/mdmd/signatures.py +0 -0
  175. {modal-1.1.3 → modal-1.1.3.dev0}/modal_proto/__init__.py +0 -0
  176. {modal-1.1.3 → modal-1.1.3.dev0}/modal_proto/api_grpc.py +0 -0
  177. {modal-1.1.3 → modal-1.1.3.dev0}/modal_proto/api_pb2_grpc.py +0 -0
  178. {modal-1.1.3 → modal-1.1.3.dev0}/modal_proto/api_pb2_grpc.pyi +0 -0
  179. {modal-1.1.3 → modal-1.1.3.dev0}/modal_proto/modal_api_grpc.py +0 -0
  180. {modal-1.1.3 → modal-1.1.3.dev0}/modal_proto/modal_options_grpc.py +0 -0
  181. {modal-1.1.3 → modal-1.1.3.dev0}/modal_proto/options.proto +0 -0
  182. {modal-1.1.3 → modal-1.1.3.dev0}/modal_proto/options_grpc.py +0 -0
  183. {modal-1.1.3 → modal-1.1.3.dev0}/modal_proto/options_pb2.py +0 -0
  184. {modal-1.1.3 → modal-1.1.3.dev0}/modal_proto/options_pb2.pyi +0 -0
  185. {modal-1.1.3 → modal-1.1.3.dev0}/modal_proto/options_pb2_grpc.py +0 -0
  186. {modal-1.1.3 → modal-1.1.3.dev0}/modal_proto/options_pb2_grpc.pyi +0 -0
  187. {modal-1.1.3 → modal-1.1.3.dev0}/modal_proto/py.typed +0 -0
  188. {modal-1.1.3 → modal-1.1.3.dev0}/modal_version/__main__.py +0 -0
  189. {modal-1.1.3 → modal-1.1.3.dev0}/pyproject.toml +0 -0
  190. {modal-1.1.3 → modal-1.1.3.dev0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.1.3
3
+ Version: 1.1.3.dev0
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -100,10 +100,6 @@ if TYPE_CHECKING:
100
100
  import modal.partial_function
101
101
 
102
102
  MAX_INTERNAL_FAILURE_COUNT = 8
103
- TERMINAL_STATUSES = (
104
- api_pb2.GenericResult.GENERIC_STATUS_SUCCESS,
105
- api_pb2.GenericResult.GENERIC_STATUS_TERMINATED,
106
- )
107
103
 
108
104
 
109
105
  @dataclasses.dataclass
@@ -304,7 +300,11 @@ class _Invocation:
304
300
 
305
301
  while True:
306
302
  item = await self._get_single_output(ctx.input_jwt)
307
- if item.result.status in TERMINAL_STATUSES:
303
+ if item.result.status in (
304
+ api_pb2.GenericResult.GENERIC_STATUS_SUCCESS,
305
+ api_pb2.GenericResult.GENERIC_STATUS_TERMINATED,
306
+ ):
307
+ # success or cancellations are "final" results
308
308
  return await _process_result(item.result, item.data_format, self.stub, self.client)
309
309
 
310
310
  if item.result.status != api_pb2.GenericResult.GENERIC_STATUS_INTERNAL_FAILURE:
@@ -411,7 +411,6 @@ class _InputPlaneInvocation:
411
411
  client: _Client,
412
412
  input_item: api_pb2.FunctionPutInputsItem,
413
413
  function_id: str,
414
- retry_policy: api_pb2.FunctionRetryPolicy,
415
414
  input_plane_region: str,
416
415
  ):
417
416
  self.stub = stub
@@ -419,7 +418,6 @@ class _InputPlaneInvocation:
419
418
  self.attempt_token = attempt_token
420
419
  self.input_item = input_item
421
420
  self.function_id = function_id
422
- self.retry_policy = retry_policy
423
421
  self.input_plane_region = input_plane_region
424
422
 
425
423
  @staticmethod
@@ -455,15 +453,11 @@ class _InputPlaneInvocation:
455
453
  response = await retry_transient_errors(stub.AttemptStart, request, metadata=metadata)
456
454
  attempt_token = response.attempt_token
457
455
 
458
- return _InputPlaneInvocation(
459
- stub, attempt_token, client, input_item, function_id, response.retry_policy, input_plane_region
460
- )
456
+ return _InputPlaneInvocation(stub, attempt_token, client, input_item, function_id, input_plane_region)
461
457
 
462
458
  async def run_function(self) -> Any:
463
- # User errors including timeouts are managed by the user-specified retry policy.
464
- user_retry_manager = RetryManager(self.retry_policy)
465
-
466
459
  # This will retry when the server returns GENERIC_STATUS_INTERNAL_FAILURE, i.e. lost inputs or worker preemption
460
+ # TODO(ryan): add logic to retry for user defined retry policy
467
461
  internal_failure_count = 0
468
462
  while True:
469
463
  await_request = api_pb2.AttemptAwaitRequest(
@@ -480,48 +474,32 @@ class _InputPlaneInvocation:
480
474
  )
481
475
 
482
476
  if await_response.HasField("output"):
483
- if await_response.output.result.status in TERMINAL_STATUSES:
484
- return await _process_result(
485
- await_response.output.result, await_response.output.data_format, self.client.stub, self.client
486
- )
487
-
488
477
  if await_response.output.result.status == api_pb2.GenericResult.GENERIC_STATUS_INTERNAL_FAILURE:
489
478
  internal_failure_count += 1
490
479
  # Limit the number of times we retry
491
480
  if internal_failure_count < MAX_INTERNAL_FAILURE_COUNT:
492
481
  # For system failures on the server, we retry immediately,
493
482
  # and the failure does not count towards the retry policy.
494
- self.attempt_token = await self._retry_input(metadata)
483
+ retry_request = api_pb2.AttemptRetryRequest(
484
+ function_id=self.function_id,
485
+ parent_input_id=current_input_id() or "",
486
+ input=self.input_item,
487
+ attempt_token=self.attempt_token,
488
+ )
489
+ # TODO(ryan): Add exponential backoff?
490
+ retry_response = await retry_transient_errors(
491
+ self.stub.AttemptRetry,
492
+ retry_request,
493
+ metadata=metadata,
494
+ )
495
+ self.attempt_token = retry_response.attempt_token
495
496
  continue
496
497
 
497
- # We add delays between retries for non-internal failures.
498
- delay_ms = user_retry_manager.get_delay_ms()
499
- if delay_ms is None:
500
- # No more retries either because we reached the retry limit or user didn't set a retry policy
501
- # and the limit defaulted to 0.
502
- # An unsuccessful status should raise an error when it's converted to an exception.
503
- # Note: Blob download is done on the control plane stub not the input plane stub!
504
- return await _process_result(
505
- await_response.output.result, await_response.output.data_format, self.client.stub, self.client
506
- )
507
- await asyncio.sleep(delay_ms / 1000)
508
-
509
- await self._retry_input(metadata)
510
-
511
- async def _retry_input(self, metadata: list[tuple[str, str]]) -> str:
512
- retry_request = api_pb2.AttemptRetryRequest(
513
- function_id=self.function_id,
514
- parent_input_id=current_input_id() or "",
515
- input=self.input_item,
516
- attempt_token=self.attempt_token,
517
- )
518
- # TODO(ryan): Add exponential backoff?
519
- retry_response = await retry_transient_errors(
520
- self.stub.AttemptRetry,
521
- retry_request,
522
- metadata=metadata,
523
- )
524
- return retry_response.attempt_token
498
+ control_plane_stub = self.client.stub
499
+ # Note: Blob download is done on the control plane stub, not the input plane stub!
500
+ return await _process_result(
501
+ await_response.output.result, await_response.output.data_format, control_plane_stub, self.client
502
+ )
525
503
 
526
504
  async def run_generator(self):
527
505
  items_received = 0
@@ -2015,7 +1993,6 @@ class _FunctionCall(typing.Generic[ReturnType], _Object, type_prefix="fc"):
2015
1993
  fc: _FunctionCall[Any] = _FunctionCall._from_loader(_load, rep, hydrate_lazily=True)
2016
1994
  # We already know the object ID, so we can set it directly
2017
1995
  fc._object_id = function_call_id
2018
- fc._client = client
2019
1996
  return fc
2020
1997
 
2021
1998
  @staticmethod
@@ -29,7 +29,11 @@ class _Client:
29
29
  _snapshotted: bool
30
30
 
31
31
  def __init__(
32
- self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "1.1.3"
32
+ self,
33
+ server_url: str,
34
+ client_type: int,
35
+ credentials: typing.Optional[tuple[str, str]],
36
+ version: str = "1.1.3.dev0",
33
37
  ):
34
38
  """mdmd:hidden
35
39
  The Modal client object is not intended to be instantiated directly by users.
@@ -156,7 +160,11 @@ class Client:
156
160
  _snapshotted: bool
157
161
 
158
162
  def __init__(
159
- self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "1.1.3"
163
+ self,
164
+ server_url: str,
165
+ client_type: int,
166
+ credentials: typing.Optional[tuple[str, str]],
167
+ version: str = "1.1.3.dev0",
160
168
  ):
161
169
  """mdmd:hidden
162
170
  The Modal client object is not intended to be instantiated directly by users.
@@ -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."""
@@ -1356,8 +1356,7 @@ class _Image(_Object, type_prefix="im"):
1356
1356
  image = modal.Image.debian_slim().uv_sync()
1357
1357
  ```
1358
1358
 
1359
- The `pyproject.toml` and `uv.lock` in `uv_project_dir` are automatically added to the build context. The
1360
- `uv_project_dir` is relative to the current working directory of where `modal` is called.
1359
+ The `pyproject.toml` and `uv.lock` in `uv_project_dir` are automatically added to the build context.
1361
1360
 
1362
1361
  Added in v1.1.0.
1363
1362
  """
@@ -524,8 +524,7 @@ class _Image(modal._object._Object):
524
524
  image = modal.Image.debian_slim().uv_sync()
525
525
  ```
526
526
 
527
- The `pyproject.toml` and `uv.lock` in `uv_project_dir` are automatically added to the build context. The
528
- `uv_project_dir` is relative to the current working directory of where `modal` is called.
527
+ The `pyproject.toml` and `uv.lock` in `uv_project_dir` are automatically added to the build context.
529
528
 
530
529
  Added in v1.1.0.
531
530
  """
@@ -1369,8 +1368,7 @@ class Image(modal.object.Object):
1369
1368
  image = modal.Image.debian_slim().uv_sync()
1370
1369
  ```
1371
1370
 
1372
- The `pyproject.toml` and `uv.lock` in `uv_project_dir` are automatically added to the build context. The
1373
- `uv_project_dir` is relative to the current working directory of where `modal` is called.
1371
+ The `pyproject.toml` and `uv.lock` in `uv_project_dir` are automatically added to the build context.
1374
1372
 
1375
1373
  Added in v1.1.0.
1376
1374
  """
@@ -673,11 +673,9 @@ async def _map_invocation_inputplane(
673
673
  # any reason).
674
674
  max_inputs_outstanding = MAX_INPUTS_OUTSTANDING_DEFAULT
675
675
 
676
- # Set a default retry policy to construct an instance of _MapItemsManager.
677
- # We'll update the retry policy with the actual user-specified retry policy
678
- # from the server in the first MapStartOrContinue response.
676
+ # Input plane does not yet return a retry policy. So we currently disable retries.
679
677
  retry_policy = api_pb2.FunctionRetryPolicy(
680
- retries=0,
678
+ retries=0, # Input plane does not yet return a retry policy. So only retry server failures for now.
681
679
  initial_delay_ms=1000,
682
680
  max_delay_ms=1000,
683
681
  backoff_coefficient=1.0,
@@ -773,17 +771,10 @@ async def _map_invocation_inputplane(
773
771
 
774
772
  map_items_manager.handle_put_continue_response(response_items_idx_tuple)
775
773
 
776
- # Set the function call id and actual retry policy with the data from the first response.
777
- # This conditional is skipped for subsequent iterations of this for-loop.
778
774
  if function_call_id is None:
779
775
  function_call_id = response.function_call_id
780
776
  function_call_id_received.set()
781
777
  max_inputs_outstanding = response.max_inputs_outstanding or MAX_INPUTS_OUTSTANDING_DEFAULT
782
- map_items_manager.set_retry_policy(response.retry_policy)
783
- # Update the retry policy for the first batch of inputs.
784
- # Subsequent batches will have the correct user-specified retry policy
785
- # set by the updated _MapItemsManager.
786
- map_items_manager.update_items_retry_policy(response.retry_policy)
787
778
  yield
788
779
 
789
780
  async def check_lost_inputs():
@@ -1484,9 +1475,6 @@ class _MapItemContext:
1484
1475
  retry_count=self.retry_manager.retry_count,
1485
1476
  )
1486
1477
 
1487
- def set_retry_policy(self, retry_policy: api_pb2.FunctionRetryPolicy):
1488
- self.retry_manager = RetryManager(retry_policy)
1489
-
1490
1478
  def handle_retry_response(self, input_jwt: str):
1491
1479
  self.input_jwt.set_result(input_jwt)
1492
1480
  self.state = _MapItemState.WAITING_FOR_OUTPUT
@@ -1523,9 +1511,6 @@ class _MapItemsManager:
1523
1511
  self._sync_client_retries_enabled = sync_client_retries_enabled
1524
1512
  self._is_input_plane_instance = is_input_plane_instance
1525
1513
 
1526
- def set_retry_policy(self, retry_policy: api_pb2.FunctionRetryPolicy):
1527
- self._retry_policy = retry_policy
1528
-
1529
1514
  async def add_items(self, items: list[api_pb2.FunctionPutInputsItem]):
1530
1515
  for item in items:
1531
1516
  # acquire semaphore to limit the number of inputs in progress
@@ -1555,10 +1540,6 @@ class _MapItemsManager:
1555
1540
  async def prepare_items_for_retry(self, retriable_idxs: list[int]) -> list[api_pb2.FunctionRetryInputsItem]:
1556
1541
  return [await self._item_context[idx].prepare_item_for_retry() for idx in retriable_idxs]
1557
1542
 
1558
- def update_items_retry_policy(self, retry_policy: api_pb2.FunctionRetryPolicy):
1559
- for ctx in self._item_context.values():
1560
- ctx.set_retry_policy(retry_policy)
1561
-
1562
1543
  def get_input_jwts_waiting_for_output(self) -> list[str]:
1563
1544
  """
1564
1545
  Returns a list of input_jwts for inputs that are waiting for output.
@@ -406,7 +406,6 @@ class _MapItemContext:
406
406
  ...
407
407
 
408
408
  async def prepare_item_for_retry(self) -> modal_proto.api_pb2.FunctionRetryInputsItem: ...
409
- def set_retry_policy(self, retry_policy: modal_proto.api_pb2.FunctionRetryPolicy): ...
410
409
  def handle_retry_response(self, input_jwt: str): ...
411
410
  async def create_map_start_or_continue_item(self, idx: int) -> modal_proto.api_pb2.MapStartOrContinueItem: ...
412
411
 
@@ -423,13 +422,11 @@ class _MapItemsManager:
423
422
  """Initialize self. See help(type(self)) for accurate signature."""
424
423
  ...
425
424
 
426
- def set_retry_policy(self, retry_policy: modal_proto.api_pb2.FunctionRetryPolicy): ...
427
425
  async def add_items(self, items: list[modal_proto.api_pb2.FunctionPutInputsItem]): ...
428
426
  async def add_items_inputplane(self, items: list[modal_proto.api_pb2.MapStartOrContinueItem]): ...
429
427
  async def prepare_items_for_retry(
430
428
  self, retriable_idxs: list[int]
431
429
  ) -> list[modal_proto.api_pb2.FunctionRetryInputsItem]: ...
432
- def update_items_retry_policy(self, retry_policy: modal_proto.api_pb2.FunctionRetryPolicy): ...
433
430
  def get_input_jwts_waiting_for_output(self) -> list[str]:
434
431
  """Returns a list of input_jwts for inputs that are waiting for output."""
435
432
  ...
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.1.3
3
+ Version: 1.1.3.dev0
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -618,7 +618,7 @@ message AttemptStartRequest {
618
618
 
619
619
  message AttemptStartResponse {
620
620
  string attempt_token = 1;
621
- FunctionRetryPolicy retry_policy = 2;
621
+ FunctionRetryPolicy retry_policy = 2; // TODO(ben-okeefe) TODO(nathan): Not currently used
622
622
  }
623
623
 
624
624
  message AuthTokenGetRequest {
@@ -1976,8 +1976,6 @@ message GenericResult { // Used for both tasks and function outputs
1976
1976
  // Terminates the function and all remaining inputs.
1977
1977
  GENERIC_STATUS_INIT_FAILURE = 5;
1978
1978
  GENERIC_STATUS_INTERNAL_FAILURE = 6;
1979
- // Used when sandboxes are terminated due to idle_timeout
1980
- GENERIC_STATUS_IDLE_TIMEOUT = 7;
1981
1979
  }
1982
1980
 
1983
1981
  GenericStatus status = 1; // Status of the task or function output.
@@ -2169,7 +2167,7 @@ message MapStartOrContinueResponse {
2169
2167
  string function_call_id = 2;
2170
2168
  uint32 max_inputs_outstanding = 3;
2171
2169
  repeated string attempt_tokens = 4;
2172
- FunctionRetryPolicy retry_policy = 5;
2170
+ FunctionRetryPolicy retry_policy = 5; // TODO(ben-okeefe): Not currently used
2173
2171
  }
2174
2172
 
2175
2173
  message MethodDefinition {
@@ -2575,7 +2573,7 @@ message Sandbox {
2575
2573
  Resources resources = 5;
2576
2574
  CloudProvider cloud_provider = 6; // Deprecated at some point
2577
2575
 
2578
- uint32 timeout_secs = 7; // The max lifetime of a sandbox in seconds.
2576
+ uint32 timeout_secs = 7;
2579
2577
 
2580
2578
  optional string workdir = 8;
2581
2579
 
@@ -2637,9 +2635,6 @@ message Sandbox {
2637
2635
  map<string, bool> experimental_options = 31;
2638
2636
 
2639
2637
  repeated string preload_path_prefixes = 32; // Internal use only.
2640
-
2641
- // Optional idle timeout in seconds. If set, the sandbox will be terminated after being idle for this duration.
2642
- optional uint32 idle_timeout_secs = 33;
2643
2638
  }
2644
2639
 
2645
2640
  message SandboxCreateRequest {