modal 1.0.1.dev5__tar.gz → 1.0.2.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 (184) hide show
  1. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/PKG-INFO +1 -1
  2. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_functions.py +34 -10
  3. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/client.pyi +2 -2
  4. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal.egg-info/PKG-INFO +1 -1
  5. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal_version/__init__.py +1 -1
  6. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/LICENSE +0 -0
  7. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/README.md +0 -0
  8. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/__init__.py +0 -0
  9. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/__main__.py +0 -0
  10. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_clustered_functions.py +0 -0
  11. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_clustered_functions.pyi +0 -0
  12. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_container_entrypoint.py +0 -0
  13. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_ipython.py +0 -0
  14. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_location.py +0 -0
  15. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_object.py +0 -0
  16. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_output.py +0 -0
  17. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_partial_function.py +0 -0
  18. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_pty.py +0 -0
  19. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_resolver.py +0 -0
  20. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_resources.py +0 -0
  21. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_runtime/__init__.py +0 -0
  22. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_runtime/asgi.py +0 -0
  23. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_runtime/container_io_manager.py +0 -0
  24. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_runtime/container_io_manager.pyi +0 -0
  25. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_runtime/execution_context.py +0 -0
  26. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_runtime/execution_context.pyi +0 -0
  27. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_runtime/gpu_memory_snapshot.py +0 -0
  28. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_runtime/telemetry.py +0 -0
  29. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_runtime/user_code_imports.py +0 -0
  30. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_serialization.py +0 -0
  31. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_traceback.py +0 -0
  32. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_tunnel.py +0 -0
  33. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_tunnel.pyi +0 -0
  34. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_type_manager.py +0 -0
  35. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_utils/__init__.py +0 -0
  36. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_utils/app_utils.py +0 -0
  37. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_utils/async_utils.py +0 -0
  38. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_utils/blob_utils.py +0 -0
  39. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_utils/bytes_io_segment_payload.py +0 -0
  40. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_utils/deprecation.py +0 -0
  41. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_utils/docker_utils.py +0 -0
  42. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_utils/function_utils.py +0 -0
  43. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_utils/git_utils.py +0 -0
  44. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_utils/grpc_testing.py +0 -0
  45. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_utils/grpc_utils.py +0 -0
  46. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_utils/hash_utils.py +0 -0
  47. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_utils/http_utils.py +0 -0
  48. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_utils/jwt_utils.py +0 -0
  49. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_utils/logger.py +0 -0
  50. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_utils/mount_utils.py +0 -0
  51. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_utils/name_utils.py +0 -0
  52. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_utils/package_utils.py +0 -0
  53. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_utils/pattern_utils.py +0 -0
  54. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_utils/rand_pb_testing.py +0 -0
  55. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_utils/shell_utils.py +0 -0
  56. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_utils/time_utils.py +0 -0
  57. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_vendor/__init__.py +0 -0
  58. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_vendor/a2wsgi_wsgi.py +0 -0
  59. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_vendor/cloudpickle.py +0 -0
  60. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_vendor/tblib.py +0 -0
  61. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/_watcher.py +0 -0
  62. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/app.py +0 -0
  63. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/app.pyi +0 -0
  64. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/call_graph.py +0 -0
  65. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/cli/__init__.py +0 -0
  66. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/cli/_download.py +0 -0
  67. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/cli/_traceback.py +0 -0
  68. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/cli/app.py +0 -0
  69. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/cli/cluster.py +0 -0
  70. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/cli/config.py +0 -0
  71. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/cli/container.py +0 -0
  72. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/cli/dict.py +0 -0
  73. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/cli/entry_point.py +0 -0
  74. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/cli/environment.py +0 -0
  75. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/cli/import_refs.py +0 -0
  76. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/cli/launch.py +0 -0
  77. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/cli/network_file_system.py +0 -0
  78. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/cli/profile.py +0 -0
  79. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/cli/programs/__init__.py +0 -0
  80. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/cli/programs/run_jupyter.py +0 -0
  81. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/cli/programs/vscode.py +0 -0
  82. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/cli/queues.py +0 -0
  83. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/cli/run.py +0 -0
  84. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/cli/secret.py +0 -0
  85. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/cli/token.py +0 -0
  86. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/cli/utils.py +0 -0
  87. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/cli/volume.py +0 -0
  88. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/client.py +0 -0
  89. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/cloud_bucket_mount.py +0 -0
  90. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/cloud_bucket_mount.pyi +0 -0
  91. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/cls.py +0 -0
  92. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/cls.pyi +0 -0
  93. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/config.py +0 -0
  94. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/container_process.py +0 -0
  95. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/container_process.pyi +0 -0
  96. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/dict.py +0 -0
  97. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/dict.pyi +0 -0
  98. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/environments.py +0 -0
  99. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/environments.pyi +0 -0
  100. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/exception.py +0 -0
  101. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/experimental/__init__.py +0 -0
  102. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/experimental/ipython.py +0 -0
  103. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/file_io.py +0 -0
  104. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/file_io.pyi +0 -0
  105. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/file_pattern_matcher.py +0 -0
  106. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/functions.py +0 -0
  107. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/functions.pyi +0 -0
  108. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/gpu.py +0 -0
  109. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/image.py +0 -0
  110. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/image.pyi +0 -0
  111. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/io_streams.py +0 -0
  112. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/io_streams.pyi +0 -0
  113. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/mount.py +0 -0
  114. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/mount.pyi +0 -0
  115. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/network_file_system.py +0 -0
  116. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/network_file_system.pyi +0 -0
  117. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/object.py +0 -0
  118. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/object.pyi +0 -0
  119. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/output.py +0 -0
  120. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/parallel_map.py +0 -0
  121. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/parallel_map.pyi +0 -0
  122. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/partial_function.py +0 -0
  123. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/partial_function.pyi +0 -0
  124. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/proxy.py +0 -0
  125. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/proxy.pyi +0 -0
  126. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/py.typed +0 -0
  127. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/queue.py +0 -0
  128. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/queue.pyi +0 -0
  129. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/requirements/2023.12.312.txt +0 -0
  130. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/requirements/2023.12.txt +0 -0
  131. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/requirements/2024.04.txt +0 -0
  132. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/requirements/2024.10.txt +0 -0
  133. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/requirements/PREVIEW.txt +0 -0
  134. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/requirements/README.md +0 -0
  135. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/requirements/base-images.json +0 -0
  136. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/retries.py +0 -0
  137. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/runner.py +0 -0
  138. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/runner.pyi +0 -0
  139. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/running_app.py +0 -0
  140. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/sandbox.py +0 -0
  141. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/sandbox.pyi +0 -0
  142. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/schedule.py +0 -0
  143. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/scheduler_placement.py +0 -0
  144. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/secret.py +0 -0
  145. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/secret.pyi +0 -0
  146. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/serving.py +0 -0
  147. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/serving.pyi +0 -0
  148. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/snapshot.py +0 -0
  149. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/snapshot.pyi +0 -0
  150. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/stream_type.py +0 -0
  151. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/token_flow.py +0 -0
  152. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/token_flow.pyi +0 -0
  153. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/volume.py +0 -0
  154. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal/volume.pyi +0 -0
  155. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal.egg-info/SOURCES.txt +0 -0
  156. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal.egg-info/dependency_links.txt +0 -0
  157. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal.egg-info/entry_points.txt +0 -0
  158. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal.egg-info/requires.txt +0 -0
  159. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal.egg-info/top_level.txt +0 -0
  160. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal_docs/__init__.py +0 -0
  161. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal_docs/gen_cli_docs.py +0 -0
  162. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal_docs/gen_reference_docs.py +0 -0
  163. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal_docs/mdmd/__init__.py +0 -0
  164. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal_docs/mdmd/mdmd.py +0 -0
  165. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal_docs/mdmd/signatures.py +0 -0
  166. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal_proto/__init__.py +0 -0
  167. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal_proto/api.proto +0 -0
  168. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal_proto/api_grpc.py +0 -0
  169. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal_proto/api_pb2.py +0 -0
  170. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal_proto/api_pb2.pyi +0 -0
  171. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal_proto/api_pb2_grpc.py +0 -0
  172. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal_proto/api_pb2_grpc.pyi +0 -0
  173. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal_proto/modal_api_grpc.py +0 -0
  174. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal_proto/modal_options_grpc.py +0 -0
  175. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal_proto/options.proto +0 -0
  176. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal_proto/options_grpc.py +0 -0
  177. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal_proto/options_pb2.py +0 -0
  178. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal_proto/options_pb2.pyi +0 -0
  179. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal_proto/options_pb2_grpc.py +0 -0
  180. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal_proto/options_pb2_grpc.pyi +0 -0
  181. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal_proto/py.typed +0 -0
  182. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/modal_version/__main__.py +0 -0
  183. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/pyproject.toml +0 -0
  184. {modal-1.0.1.dev5 → modal-1.0.2.dev0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.0.1.dev5
3
+ Version: 1.0.2.dev0
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -99,6 +99,7 @@ if TYPE_CHECKING:
99
99
  import modal.cls
100
100
  import modal.partial_function
101
101
 
102
+ MAX_INTERNAL_FAILURE_COUNT = 8
102
103
 
103
104
  @dataclasses.dataclass
104
105
  class _RetryContext:
@@ -348,10 +349,14 @@ class _InputPlaneInvocation:
348
349
  stub: ModalClientModal,
349
350
  attempt_token: str,
350
351
  client: _Client,
352
+ input_item: api_pb2.FunctionPutInputsItem,
353
+ function_id: str,
351
354
  ):
352
355
  self.stub = stub
353
356
  self.client = client # Used by the deserializer.
354
357
  self.attempt_token = attempt_token
358
+ self.input_item = input_item
359
+ self.function_id = function_id
355
360
 
356
361
  @staticmethod
357
362
  async def create(
@@ -365,36 +370,55 @@ class _InputPlaneInvocation:
365
370
  stub = await client.get_stub(input_plane_url)
366
371
 
367
372
  function_id = function.object_id
368
- item = await _create_input(args, kwargs, stub, method_name=function._use_method_name)
373
+ input_item = await _create_input(args, kwargs, stub, method_name=function._use_method_name)
369
374
 
370
375
  request = api_pb2.AttemptStartRequest(
371
376
  function_id=function_id,
372
377
  parent_input_id=current_input_id() or "",
373
- input=item,
378
+ input=input_item,
374
379
  )
375
380
  response = await retry_transient_errors(stub.AttemptStart, request)
376
381
  attempt_token = response.attempt_token
377
382
 
378
- return _InputPlaneInvocation(stub, attempt_token, client)
383
+ return _InputPlaneInvocation(stub, attempt_token, client, input_item, function_id)
379
384
 
380
385
  async def run_function(self) -> Any:
381
- # TODO(nathan): add retry logic
386
+ # This will retry when the server returns GENERIC_STATUS_INTERNAL_FAILURE, i.e. lost inputs or worker preemption
387
+ # TODO(ryan): add logic to retry for user defined retry policy
388
+ internal_failure_count = 0
382
389
  while True:
383
- request = api_pb2.AttemptAwaitRequest(
390
+ await_request = api_pb2.AttemptAwaitRequest(
384
391
  attempt_token=self.attempt_token,
385
392
  timeout_secs=OUTPUTS_TIMEOUT,
386
393
  requested_at=time.time(),
387
394
  )
388
- response: api_pb2.AttemptAwaitResponse = await retry_transient_errors(
395
+ await_response: api_pb2.AttemptAwaitResponse = await retry_transient_errors(
389
396
  self.stub.AttemptAwait,
390
- request,
397
+ await_request,
391
398
  attempt_timeout=OUTPUTS_TIMEOUT + ATTEMPT_TIMEOUT_GRACE_PERIOD,
392
399
  )
393
400
 
394
- if response.HasField("output"):
395
- return await _process_result(
396
- response.output.result, response.output.data_format, self.stub, self.client
401
+ try:
402
+ if await_response.HasField("output"):
403
+ return await _process_result(
404
+ await_response.output.result, await_response.output.data_format, self.stub, self.client
405
+ )
406
+ except InternalFailure as e:
407
+ internal_failure_count += 1
408
+ # Limit the number of times we retry
409
+ if internal_failure_count >= MAX_INTERNAL_FAILURE_COUNT:
410
+ raise e
411
+ # For system failures on the server, we retry immediately,
412
+ # and the failure does not count towards the retry policy.
413
+ retry_request = api_pb2.AttemptRetryRequest(
414
+ function_id=self.function_id,
415
+ parent_input_id=current_input_id() or "",
416
+ input=self.input_item,
417
+ attempt_token=self.attempt_token,
397
418
  )
419
+ # TODO(ryan): Add exponential backoff?
420
+ retry_response = await retry_transient_errors(self.stub.AttemptRetry, retry_request)
421
+ self.attempt_token = retry_response.attempt_token
398
422
 
399
423
 
400
424
  # Wrapper type for api_pb2.FunctionStats
@@ -31,7 +31,7 @@ class _Client:
31
31
  server_url: str,
32
32
  client_type: int,
33
33
  credentials: typing.Optional[tuple[str, str]],
34
- version: str = "1.0.1.dev5",
34
+ version: str = "1.0.2.dev0",
35
35
  ): ...
36
36
  def is_closed(self) -> bool: ...
37
37
  @property
@@ -94,7 +94,7 @@ class Client:
94
94
  server_url: str,
95
95
  client_type: int,
96
96
  credentials: typing.Optional[tuple[str, str]],
97
- version: str = "1.0.1.dev5",
97
+ version: str = "1.0.2.dev0",
98
98
  ): ...
99
99
  def is_closed(self) -> bool: ...
100
100
  @property
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.0.1.dev5
3
+ Version: 1.0.2.dev0
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.0.1.dev5"
4
+ __version__ = "1.0.2.dev0"
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
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