modal 1.0.0.dev16__py3-none-any.whl → 1.0.0.dev17__py3-none-any.whl

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.
modal/_functions.py CHANGED
@@ -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 = 100
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,53 @@ 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
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"):
401
+ try:
395
402
  return await _process_result(
396
- response.output.result, response.output.data_format, self.stub, self.client
403
+ await_response.output.result, await_response.output.data_format, self.stub, self.client
404
+ )
405
+ except InternalFailure as e:
406
+ internal_failure_count += 1
407
+ # Limit the number of times we retry
408
+ if internal_failure_count >= MAX_INTERNAL_FAILURE_COUNT:
409
+ raise e
410
+ # For system failures on the server, we retry immediately,
411
+ # and the failure does not count towards the retry policy.
412
+ retry_request = api_pb2.AttemptRetryRequest(
413
+ function_id=self.function_id,
414
+ parent_input_id=current_input_id() or "",
415
+ input=self.input_item,
416
+ attempt_token=self.attempt_token
397
417
  )
418
+ retry_response = await retry_transient_errors(self.stub.AttemptRetry, retry_request)
419
+ self.attempt_token = retry_response.attempt_token
398
420
 
399
421
 
400
422
  # Wrapper type for api_pb2.FunctionStats
@@ -466,7 +466,10 @@ async def _process_result(result: api_pb2.GenericResult, data_format: int, stub,
466
466
 
467
467
  if result.status == api_pb2.GenericResult.GENERIC_STATUS_TIMEOUT:
468
468
  raise FunctionTimeoutError(result.exception)
469
- elif result.status == api_pb2.GenericResult.GENERIC_STATUS_INTERNAL_FAILURE:
469
+ elif result.status in [
470
+ api_pb2.GenericResult.GENERIC_STATUS_INTERNAL_FAILURE,
471
+ api_pb2.GenericResult.GENERIC_STATUS_TERMINATED,
472
+ ]:
470
473
  raise InternalFailure(result.exception)
471
474
  elif result.status != api_pb2.GenericResult.GENERIC_STATUS_SUCCESS:
472
475
  if data:
modal/client.pyi CHANGED
@@ -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.0.dev16",
34
+ version: str = "1.0.0.dev17",
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.0.dev16",
97
+ version: str = "1.0.0.dev17",
98
98
  ): ...
99
99
  def is_closed(self) -> bool: ...
100
100
  @property
modal/functions.pyi CHANGED
@@ -228,11 +228,11 @@ class Function(
228
228
 
229
229
  _call_generator: ___call_generator_spec[typing_extensions.Self]
230
230
 
231
- class __remote_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
231
+ class __remote_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER, SUPERSELF]):
232
232
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER: ...
233
233
  async def aio(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER: ...
234
234
 
235
- remote: __remote_spec[modal._functions.P, modal._functions.ReturnType, typing_extensions.Self]
235
+ remote: __remote_spec[modal._functions.ReturnType, modal._functions.P, typing_extensions.Self]
236
236
 
237
237
  class __remote_gen_spec(typing_extensions.Protocol[SUPERSELF]):
238
238
  def __call__(self, /, *args, **kwargs) -> typing.Generator[typing.Any, None, None]: ...
@@ -247,12 +247,12 @@ class Function(
247
247
  self, *args: modal._functions.P.args, **kwargs: modal._functions.P.kwargs
248
248
  ) -> modal._functions.OriginalReturnType: ...
249
249
 
250
- class ___experimental_spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
250
+ class ___experimental_spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER, SUPERSELF]):
251
251
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
252
252
  async def aio(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
253
253
 
254
254
  _experimental_spawn: ___experimental_spawn_spec[
255
- modal._functions.P, modal._functions.ReturnType, typing_extensions.Self
255
+ modal._functions.ReturnType, modal._functions.P, typing_extensions.Self
256
256
  ]
257
257
 
258
258
  class ___spawn_map_inner_spec(typing_extensions.Protocol[P_INNER, SUPERSELF]):
@@ -261,11 +261,11 @@ class Function(
261
261
 
262
262
  _spawn_map_inner: ___spawn_map_inner_spec[modal._functions.P, typing_extensions.Self]
263
263
 
264
- class __spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
264
+ class __spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER, SUPERSELF]):
265
265
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
266
266
  async def aio(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
267
267
 
268
- spawn: __spawn_spec[modal._functions.P, modal._functions.ReturnType, typing_extensions.Self]
268
+ spawn: __spawn_spec[modal._functions.ReturnType, modal._functions.P, typing_extensions.Self]
269
269
 
270
270
  def get_raw_f(self) -> collections.abc.Callable[..., typing.Any]: ...
271
271
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.0.0.dev16
3
+ Version: 1.0.0.dev17
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -3,7 +3,7 @@ modal/__main__.py,sha256=sTJcc9EbDuCKSwg3tL6ZckFw9WWdlkXW8mId1IvJCNc,2846
3
3
  modal/_clustered_functions.py,sha256=kTf-9YBXY88NutC1akI-gCbvf01RhMPCw-zoOI_YIUE,2700
4
4
  modal/_clustered_functions.pyi,sha256=2aWxN2v5WUnj-R-sk6BzJ-3AvggkQGQjwhtvbDH3pds,777
5
5
  modal/_container_entrypoint.py,sha256=2Zx9O_EMJg0H77EdnC2vGKs6uFMWwbP1NLFf-qYmWmU,28962
6
- modal/_functions.py,sha256=8ZHWZu2su2bbWb_QXjr9S2KfZemKxuMSxCansbVd0VY,77970
6
+ modal/_functions.py,sha256=kIyUjK1v6C8RWXSkkJI5kTO3mz--gkO-3aA9f40aaog,79212
7
7
  modal/_ipython.py,sha256=TW1fkVOmZL3YYqdS2YlM1hqpf654Yf8ZyybHdBnlhSw,301
8
8
  modal/_location.py,sha256=joiX-0ZeutEUDTrrqLF1GHXCdVLF-rHzstocbMcd_-k,366
9
9
  modal/_object.py,sha256=KzzzZoM41UQUiY9TKOrft9BtZKgjWG_ukdlyLGjB4UY,10758
@@ -22,7 +22,7 @@ modal/app.py,sha256=Wz9DIFzO2ByObuqoh3zk9B76WTWcPqYoQDuPU-yrLTU,47100
22
22
  modal/app.pyi,sha256=1dHHI6RgvJ1y5Ouzb1_S-wpjfjCL7QHz0gqE4BxMw10,23192
23
23
  modal/call_graph.py,sha256=1g2DGcMIJvRy-xKicuf63IVE98gJSnQsr8R_NVMptNc,2581
24
24
  modal/client.py,sha256=o-aQThHpvDHUzg_kUafyhWzACViUBhY2WLZ2EitnSHA,16787
25
- modal/client.pyi,sha256=e6ghxi754Z0WfJ_zMQ8mrthEitSVfS-QZ_AgzWWVUlc,8459
25
+ modal/client.pyi,sha256=Ddk29klkblcqrIS02IgWDkKgrLTgAXIqYTAF2PFmDSM,8459
26
26
  modal/cloud_bucket_mount.py,sha256=YOe9nnvSr4ZbeCn587d7_VhE9IioZYRvF9VYQTQux08,5914
27
27
  modal/cloud_bucket_mount.pyi,sha256=30T3K1a89l6wzmEJ_J9iWv9SknoGqaZDx59Xs-ZQcmk,1607
28
28
  modal/cls.py,sha256=dBbeARwOWftlKd1cwtM0cHFtQWSWkwVXwVmOV4w0SyI,37907
@@ -39,7 +39,7 @@ modal/file_io.py,sha256=lcMs_E9Xfm0YX1t9U2wNIBPnqHRxmImqjLW1GHqVmyg,20945
39
39
  modal/file_io.pyi,sha256=oB7x-rKq7bmm8cA7Z7W9C9yeko7KK9m9i5GidFnkGK4,9569
40
40
  modal/file_pattern_matcher.py,sha256=wov-otB5M1oTdrYDtR2_VgacYin2srdtAP4McA1Cqzw,6516
41
41
  modal/functions.py,sha256=kcNHvqeGBxPI7Cgd57NIBBghkfbeFJzXO44WW0jSmao,325
42
- modal/functions.pyi,sha256=cllJF89sCKlX82On69XG8XlETgI364xF7Hsj3kxJaeU,16304
42
+ modal/functions.pyi,sha256=YE2ZjUSY-sToZK0cRtmSrIp9fI3kr39-6EGhMLVy5pQ,16304
43
43
  modal/gpu.py,sha256=Kbhs_u49FaC2Zi0TjCdrpstpRtT5eZgecynmQi5IZVE,6752
44
44
  modal/image.py,sha256=glnu6LDf3iFq71CGVstHx40CKVN4rw8tukPLAy5JgTQ,92464
45
45
  modal/image.pyi,sha256=NbegOjy6QX_SL-eTxtJm1_4gOJHW04Ja449QHZIdKgU,25586
@@ -96,7 +96,7 @@ modal/_utils/blob_utils.py,sha256=IexC2Jbtqp_Tkmy62ayfgzTYte0UPCNufB_v-DO21g8,18
96
96
  modal/_utils/bytes_io_segment_payload.py,sha256=uunxVJS4PE1LojF_UpURMzVK9GuvmYWRqQo_bxEj5TU,3385
97
97
  modal/_utils/deprecation.py,sha256=EXP1beU4pmEqEzWMLw6E3kUfNfpmNA_VOp6i0EHi93g,4856
98
98
  modal/_utils/docker_utils.py,sha256=h1uETghR40mp_y3fSWuZAfbIASH1HMzuphJHghAL6DU,3722
99
- modal/_utils/function_utils.py,sha256=bhrjyOHPPXm6fAyJx3bzI1Yh56j6xh8eeMSFKdAWrHQ,26978
99
+ modal/_utils/function_utils.py,sha256=qi_ubD5jvOpksKvaxitJDXxfVl1R2Kph6eX8k3y5Hz4,27052
100
100
  modal/_utils/git_utils.py,sha256=qtUU6JAttF55ZxYq51y55OR58B0tDPZsZWK5dJe6W5g,3182
101
101
  modal/_utils/grpc_testing.py,sha256=H1zHqthv19eGPJz2HKXDyWXWGSqO4BRsxah3L5Xaa8A,8619
102
102
  modal/_utils/grpc_utils.py,sha256=xSFosSJYQ4m6cH9WtChcSXqsnyk6DMeVvOHI4N3914g,10922
@@ -146,7 +146,7 @@ modal/requirements/2024.10.txt,sha256=qD-5cVIVM9wXesJ6JC89Ew-3m2KjEElUz3jaw_MddR
146
146
  modal/requirements/PREVIEW.txt,sha256=qD-5cVIVM9wXesJ6JC89Ew-3m2KjEElUz3jaw_MddRo,296
147
147
  modal/requirements/README.md,sha256=9tK76KP0Uph7O0M5oUgsSwEZDj5y-dcUPsnpR0Sc-Ik,854
148
148
  modal/requirements/base-images.json,sha256=57vMSqzMbLBxw5tFWSaMiIkkVEps4JfX5PAtXGnkS4U,740
149
- modal-1.0.0.dev16.dist-info/licenses/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
149
+ modal-1.0.0.dev17.dist-info/licenses/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
150
150
  modal_docs/__init__.py,sha256=svYKtV8HDwDCN86zbdWqyq5T8sMdGDj0PVlzc2tIxDM,28
151
151
  modal_docs/gen_cli_docs.py,sha256=c1yfBS_x--gL5bs0N4ihMwqwX8l3IBWSkBAKNNIi6bQ,3801
152
152
  modal_docs/gen_reference_docs.py,sha256=d_CQUGQ0rfw28u75I2mov9AlS773z9rG40-yq5o7g2U,6359
@@ -169,10 +169,10 @@ modal_proto/options_pb2.pyi,sha256=l7DBrbLO7q3Ir-XDkWsajm0d0TQqqrfuX54i4BMpdQg,1
169
169
  modal_proto/options_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXHDCNMhZD2VXqocC9l_gk,159
170
170
  modal_proto/options_pb2_grpc.pyi,sha256=CImmhxHsYnF09iENPoe8S4J-n93jtgUYD2JPAc0yJSI,247
171
171
  modal_proto/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
172
- modal_version/__init__.py,sha256=-BSzjamBYi1bfz_PGPNWb6JtCWPr4i-Q5Txuq0wPwPs,121
172
+ modal_version/__init__.py,sha256=GHKCCzDIY8EaRLgeTTWDfXOXRlxYUKA7fhfqAieG_2M,121
173
173
  modal_version/__main__.py,sha256=2FO0yYQQwDTh6udt1h-cBnGd1c4ZyHnHSI4BksxzVac,105
174
- modal-1.0.0.dev16.dist-info/METADATA,sha256=0sLq92t_upACBNZHkXXnirRuo-15pDljGA8vKq21a8g,2455
175
- modal-1.0.0.dev16.dist-info/WHEEL,sha256=1tXe9gY0PYatrMPMDd6jXqjfpz_B-Wqm32CPfRC58XU,91
176
- modal-1.0.0.dev16.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
177
- modal-1.0.0.dev16.dist-info/top_level.txt,sha256=4BWzoKYREKUZ5iyPzZpjqx4G8uB5TWxXPDwibLcVa7k,43
178
- modal-1.0.0.dev16.dist-info/RECORD,,
174
+ modal-1.0.0.dev17.dist-info/METADATA,sha256=FKF7xQQABbtG_5NXNR-eXh7lsACZ0fmK0pAs_sWbWlE,2455
175
+ modal-1.0.0.dev17.dist-info/WHEEL,sha256=1tXe9gY0PYatrMPMDd6jXqjfpz_B-Wqm32CPfRC58XU,91
176
+ modal-1.0.0.dev17.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
177
+ modal-1.0.0.dev17.dist-info/top_level.txt,sha256=4BWzoKYREKUZ5iyPzZpjqx4G8uB5TWxXPDwibLcVa7k,43
178
+ modal-1.0.0.dev17.dist-info/RECORD,,
modal_version/__init__.py CHANGED
@@ -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.0.dev16"
4
+ __version__ = "1.0.0.dev17"