modal 0.71.3__py3-none-any.whl → 0.71.4__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.
@@ -17,7 +17,14 @@ from modal_proto import api_pb2
17
17
  from .._serialization import deserialize, deserialize_data_format, serialize
18
18
  from .._traceback import append_modal_tb
19
19
  from ..config import config, logger
20
- from ..exception import DeserializationError, ExecutionError, FunctionTimeoutError, InvalidError, RemoteError
20
+ from ..exception import (
21
+ DeserializationError,
22
+ ExecutionError,
23
+ FunctionTimeoutError,
24
+ InternalFailure,
25
+ InvalidError,
26
+ RemoteError,
27
+ )
21
28
  from ..mount import ROOT_DIR, _is_modal_path, _Mount
22
29
  from .blob_utils import MAX_OBJECT_SIZE_BYTES, blob_download, blob_upload
23
30
  from .grpc_utils import RETRYABLE_GRPC_STATUS_CODES
@@ -463,6 +470,8 @@ async def _process_result(result: api_pb2.GenericResult, data_format: int, stub,
463
470
 
464
471
  if result.status == api_pb2.GenericResult.GENERIC_STATUS_TIMEOUT:
465
472
  raise FunctionTimeoutError(result.exception)
473
+ elif result.status == api_pb2.GenericResult.GENERIC_STATUS_INTERNAL_FAILURE:
474
+ raise InternalFailure(result.exception)
466
475
  elif result.status != api_pb2.GenericResult.GENERIC_STATUS_SUCCESS:
467
476
  if data:
468
477
  try:
modal/client.pyi CHANGED
@@ -26,7 +26,7 @@ class _Client:
26
26
  _stub: typing.Optional[modal_proto.api_grpc.ModalClientStub]
27
27
 
28
28
  def __init__(
29
- self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.71.3"
29
+ self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.71.4"
30
30
  ): ...
31
31
  def is_closed(self) -> bool: ...
32
32
  @property
@@ -81,7 +81,7 @@ class Client:
81
81
  _stub: typing.Optional[modal_proto.api_grpc.ModalClientStub]
82
82
 
83
83
  def __init__(
84
- self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.71.3"
84
+ self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.71.4"
85
85
  ): ...
86
86
  def is_closed(self) -> bool: ...
87
87
  @property
modal/exception.py CHANGED
@@ -108,6 +108,12 @@ class ServerWarning(UserWarning):
108
108
  """Warning originating from the Modal server and re-issued in client code."""
109
109
 
110
110
 
111
+ class InternalFailure(Error):
112
+ """
113
+ Retriable internal error.
114
+ """
115
+
116
+
111
117
  class _CliUserExecutionError(Exception):
112
118
  """mdmd:hidden
113
119
  Private wrapper for exceptions during when importing or running stubs from the CLI.
modal/functions.py CHANGED
@@ -59,7 +59,14 @@ from .call_graph import InputInfo, _reconstruct_call_graph
59
59
  from .client import _Client
60
60
  from .cloud_bucket_mount import _CloudBucketMount, cloud_bucket_mounts_to_proto
61
61
  from .config import config
62
- from .exception import ExecutionError, FunctionTimeoutError, InvalidError, NotFoundError, OutputExpiredError
62
+ from .exception import (
63
+ ExecutionError,
64
+ FunctionTimeoutError,
65
+ InternalFailure,
66
+ InvalidError,
67
+ NotFoundError,
68
+ OutputExpiredError,
69
+ )
63
70
  from .gpu import GPU_T, parse_gpu_config
64
71
  from .image import _Image
65
72
  from .mount import _get_client_mount, _Mount, get_auto_mounts
@@ -174,7 +181,7 @@ class _Invocation:
174
181
  return _Invocation(client.stub, function_call_id, client, retry_context)
175
182
 
176
183
  async def pop_function_call_outputs(
177
- self, timeout: Optional[float], clear_on_success: bool
184
+ self, timeout: Optional[float], clear_on_success: bool, input_jwts: Optional[list[str]] = None
178
185
  ) -> api_pb2.FunctionGetOutputsResponse:
179
186
  t0 = time.time()
180
187
  if timeout is None:
@@ -190,6 +197,7 @@ class _Invocation:
190
197
  last_entry_id="0-0",
191
198
  clear_on_success=clear_on_success,
192
199
  requested_at=time.time(),
200
+ input_jwts=input_jwts,
193
201
  )
194
202
  response: api_pb2.FunctionGetOutputsResponse = await retry_transient_errors(
195
203
  self.stub.FunctionGetOutputs,
@@ -219,10 +227,14 @@ class _Invocation:
219
227
  request,
220
228
  )
221
229
 
222
- async def _get_single_output(self) -> Any:
230
+ async def _get_single_output(self, expected_jwt: Optional[str] = None) -> Any:
223
231
  # waits indefinitely for a single result for the function, and clear the outputs buffer after
224
232
  item: api_pb2.FunctionGetOutputsItem = (
225
- await self.pop_function_call_outputs(timeout=None, clear_on_success=True)
233
+ await self.pop_function_call_outputs(
234
+ timeout=None,
235
+ clear_on_success=True,
236
+ input_jwts=[expected_jwt] if expected_jwt else None,
237
+ )
226
238
  ).outputs[0]
227
239
  return await _process_result(item.result, item.data_format, self.stub, self.client)
228
240
 
@@ -242,9 +254,12 @@ class _Invocation:
242
254
 
243
255
  while True:
244
256
  try:
245
- return await self._get_single_output()
257
+ return await self._get_single_output(ctx.input_jwt)
246
258
  except (UserCodeException, FunctionTimeoutError) as exc:
247
259
  await user_retry_manager.raise_or_sleep(exc)
260
+ except InternalFailure:
261
+ # For system failures on the server, we retry immediately.
262
+ pass
248
263
  await self._retry_input()
249
264
 
250
265
  async def poll_function(self, timeout: Optional[float] = None):
modal/functions.pyi CHANGED
@@ -61,10 +61,10 @@ class _Invocation:
61
61
  function: _Function, args, kwargs, *, client: modal.client._Client, function_call_invocation_type: int
62
62
  ) -> _Invocation: ...
63
63
  async def pop_function_call_outputs(
64
- self, timeout: typing.Optional[float], clear_on_success: bool
64
+ self, timeout: typing.Optional[float], clear_on_success: bool, input_jwts: typing.Optional[list[str]] = None
65
65
  ) -> modal_proto.api_pb2.FunctionGetOutputsResponse: ...
66
66
  async def _retry_input(self) -> None: ...
67
- async def _get_single_output(self) -> typing.Any: ...
67
+ async def _get_single_output(self, expected_jwt: typing.Optional[str] = None) -> typing.Any: ...
68
68
  async def run_function(self) -> typing.Any: ...
69
69
  async def poll_function(self, timeout: typing.Optional[float] = None): ...
70
70
  def run_generator(self): ...
@@ -462,11 +462,11 @@ class Function(typing.Generic[P, ReturnType, OriginalReturnType], modal.object.O
462
462
 
463
463
  _call_generator_nowait: ___call_generator_nowait_spec
464
464
 
465
- class __remote_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
465
+ class __remote_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER]):
466
466
  def __call__(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER: ...
467
467
  async def aio(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER: ...
468
468
 
469
- remote: __remote_spec[ReturnType, P]
469
+ remote: __remote_spec[P, ReturnType]
470
470
 
471
471
  class __remote_gen_spec(typing_extensions.Protocol):
472
472
  def __call__(self, *args, **kwargs) -> typing.Generator[typing.Any, None, None]: ...
@@ -479,17 +479,17 @@ class Function(typing.Generic[P, ReturnType, OriginalReturnType], modal.object.O
479
479
  def _get_obj(self) -> typing.Optional[modal.cls.Obj]: ...
480
480
  def local(self, *args: P.args, **kwargs: P.kwargs) -> OriginalReturnType: ...
481
481
 
482
- class ___experimental_spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
482
+ class ___experimental_spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER]):
483
483
  def __call__(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
484
484
  async def aio(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
485
485
 
486
- _experimental_spawn: ___experimental_spawn_spec[ReturnType, P]
486
+ _experimental_spawn: ___experimental_spawn_spec[P, ReturnType]
487
487
 
488
- class __spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
488
+ class __spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER]):
489
489
  def __call__(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
490
490
  async def aio(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
491
491
 
492
- spawn: __spawn_spec[ReturnType, P]
492
+ spawn: __spawn_spec[P, ReturnType]
493
493
 
494
494
  def get_raw_f(self) -> typing.Callable[..., typing.Any]: ...
495
495
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: modal
3
- Version: 0.71.3
3
+ Version: 0.71.4
4
4
  Summary: Python client library for Modal
5
5
  Author: Modal Labs
6
6
  Author-email: support@modal.com
@@ -19,7 +19,7 @@ modal/app.py,sha256=vEE0cK5QPF6_cdW5AJvcuWxz5KmeprHwBEtlDkVRHgE,45582
19
19
  modal/app.pyi,sha256=Gx7gxjfQ70sxhbwfpx1VjvzEON-ZEMTJ_Vy8qt0oQvo,25302
20
20
  modal/call_graph.py,sha256=1g2DGcMIJvRy-xKicuf63IVE98gJSnQsr8R_NVMptNc,2581
21
21
  modal/client.py,sha256=JAnd4-GCN093BwkvOFAK5a6iy5ycxofjpUncMxlrIMw,15253
22
- modal/client.pyi,sha256=g36AUvqxWl-M3qym800n9bscsG3V5qM0scNEJ0nBWlk,7278
22
+ modal/client.pyi,sha256=4tCQvE-eS0ZqCco5-2LqQ3omg76GL-q4K8prnmzVfZ4,7278
23
23
  modal/cloud_bucket_mount.py,sha256=G7T7jWLD0QkmrfKR75mSTwdUZ2xNfj7pkVqb4ipmxmI,5735
24
24
  modal/cloud_bucket_mount.pyi,sha256=CEi7vrH3kDUF4LAy4qP6tfImy2UJuFRcRbsgRNM1wo8,1403
25
25
  modal/cls.py,sha256=3hjb0JcoPjxKZNeK22f5rR43bZRBjoRI7_EMZXY7YrE,31172
@@ -31,13 +31,13 @@ modal/dict.py,sha256=ei9jsA5iTj4UFGPJxTAed6vjd49W47ezDtj0koUmVts,12497
31
31
  modal/dict.pyi,sha256=VmbzxltA2vFlIHZCxpNGtd-ieXwcUwdw3iyy3WCweqU,7115
32
32
  modal/environments.py,sha256=wbv9ttFCbzATGfwcmvYiG608PfHovx0AQmawsg-jmic,6660
33
33
  modal/environments.pyi,sha256=rF7oaaELoSNuoD6qImGnIbuGPtgWwR5SlcExyYJ61hQ,3515
34
- modal/exception.py,sha256=GEV6xMnVnkle0gsFZVLB4B7cUMyw8HzVDvAvPr34ZV4,5185
34
+ modal/exception.py,sha256=4JyO-SACaLNDe2QC48EjsK8GMkZ8AgEurZ8j1YdRu8E,5263
35
35
  modal/experimental.py,sha256=npfKbyMpI41uZZs9HW_QiB3E4ykWfDXZbACXXbw6qeA,2385
36
36
  modal/file_io.py,sha256=ZR8VBCDsDt5uB9TNN9XbEh7sniJzM_5YL47m8WP0m5c,19617
37
37
  modal/file_io.pyi,sha256=79Fg75BjmMEeCX0Lx-Z8C4XSNPCotwNdK6ZLIDFm2f4,9770
38
38
  modal/file_pattern_matcher.py,sha256=LaI7Paxg0xR9D-D7Tgc60xR0w1KZee22LjGbFie1Vms,5571
39
- modal/functions.py,sha256=aXXXr3rk7BCeh5OWMvxGksGm8FQoYCyrBDGV74FPoPE,67827
40
- modal/functions.pyi,sha256=oMmcExtQxHwPej06jQ3uBe1tUlSR3VbAx7u3Vm-Ohhg,25317
39
+ modal/functions.py,sha256=3uJPbrEAWhpFfLfUnoRjGmvEUC-_wVh-8yNJBx8eVeM,68249
40
+ modal/functions.pyi,sha256=LiSDgH-X7jcZ56pAoLMwo3x9Dzdp_3Sd7W5MVAJPoCg,25407
41
41
  modal/gpu.py,sha256=MTxj6ql8EpgfBg8YmZ5a1cLznyuZFssX1qXbEX4LKVM,7503
42
42
  modal/image.py,sha256=Krvcsclomp9YsqSNwFj2FoAyg10OvU47RDnsNCwjGbQ,84550
43
43
  modal/image.pyi,sha256=1fgGvsL5Rb0Sa-_2OCgIyJ_QgHcL0_9MWD_oY7cyFFM,24937
@@ -90,7 +90,7 @@ modal/_utils/blob_utils.py,sha256=N66LtZI8PpCkZ7maA7GLW5CAmYUoNJdG-GjaAUR4_NQ,14
90
90
  modal/_utils/bytes_io_segment_payload.py,sha256=uunxVJS4PE1LojF_UpURMzVK9GuvmYWRqQo_bxEj5TU,3385
91
91
  modal/_utils/deprecation.py,sha256=dycySRBxyZf3ITzEqPNM6MxXTk9-0VVLA8oCPQ5j_Os,3426
92
92
  modal/_utils/docker_utils.py,sha256=FLz1q0YicL6i_Iq-4inkgDVFfEINVG6YPT2s_P6ly0o,2264
93
- modal/_utils/function_utils.py,sha256=4LYFbNY5aHc96QitwP4Ty-dBl45SD1HjfZrvBFUF-ko,25343
93
+ modal/_utils/function_utils.py,sha256=q68HhFH16MwhHRnGD8jvIgqDjduRQVp3a_qMWXPyrgU,25518
94
94
  modal/_utils/grpc_testing.py,sha256=H1zHqthv19eGPJz2HKXDyWXWGSqO4BRsxah3L5Xaa8A,8619
95
95
  modal/_utils/grpc_utils.py,sha256=PPB5ay-vXencXNIWPVw5modr3EH7gfq2QPcO5YJ1lMU,7737
96
96
  modal/_utils/hash_utils.py,sha256=zg3J6OGxTFGSFri1qQ12giDz90lWk8bzaxCTUCRtiX4,3034
@@ -166,10 +166,10 @@ modal_proto/options_pb2_grpc.pyi,sha256=CImmhxHsYnF09iENPoe8S4J-n93jtgUYD2JPAc0y
166
166
  modal_proto/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
167
167
  modal_version/__init__.py,sha256=BEBWj9tcbFUwzEjUrqly601rauw5cYsHdcmJHs3iu0s,470
168
168
  modal_version/__main__.py,sha256=2FO0yYQQwDTh6udt1h-cBnGd1c4ZyHnHSI4BksxzVac,105
169
- modal_version/_version_generated.py,sha256=GVYfkFxvwUpfzdmWO8cxk57L2ZM-JzQISmGvWDKjz_o,148
170
- modal-0.71.3.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
171
- modal-0.71.3.dist-info/METADATA,sha256=V79Ksg3YCSNCVVjx5Sn60NhaB0o4DMJ7BbnBtQ3lbzU,2328
172
- modal-0.71.3.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
173
- modal-0.71.3.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
174
- modal-0.71.3.dist-info/top_level.txt,sha256=1nvYbOSIKcmU50fNrpnQnrrOpj269ei3LzgB6j9xGqg,64
175
- modal-0.71.3.dist-info/RECORD,,
169
+ modal_version/_version_generated.py,sha256=3TvSmDcXd2TJWiBGF1oNLfcsxLy3TPqMQ4BxZiXpYB0,148
170
+ modal-0.71.4.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
171
+ modal-0.71.4.dist-info/METADATA,sha256=km6ecKksbjllgRq-Bk0JlnTFBf-EuP3wBOh6_nf5bVc,2328
172
+ modal-0.71.4.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
173
+ modal-0.71.4.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
174
+ modal-0.71.4.dist-info/top_level.txt,sha256=1nvYbOSIKcmU50fNrpnQnrrOpj269ei3LzgB6j9xGqg,64
175
+ modal-0.71.4.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  # Copyright Modal Labs 2025
2
2
 
3
3
  # Note: Reset this value to -1 whenever you make a minor `0.X` release of the client.
4
- build_number = 3 # git: a8a3103
4
+ build_number = 4 # git: 07e0100
File without changes