modal 1.0.4.dev10__py3-none-any.whl → 1.0.5__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.
Files changed (67) hide show
  1. modal/_clustered_functions.pyi +13 -3
  2. modal/_functions.py +84 -46
  3. modal/_partial_function.py +1 -1
  4. modal/_runtime/container_io_manager.pyi +222 -40
  5. modal/_runtime/execution_context.pyi +60 -6
  6. modal/_serialization.py +25 -2
  7. modal/_tunnel.pyi +380 -12
  8. modal/_utils/async_utils.py +1 -1
  9. modal/_utils/blob_utils.py +56 -19
  10. modal/_utils/function_utils.py +33 -7
  11. modal/_utils/grpc_utils.py +11 -4
  12. modal/app.py +5 -5
  13. modal/app.pyi +658 -48
  14. modal/cli/run.py +2 -1
  15. modal/client.pyi +224 -36
  16. modal/cloud_bucket_mount.pyi +192 -4
  17. modal/cls.py +57 -16
  18. modal/cls.pyi +442 -34
  19. modal/container_process.pyi +103 -14
  20. modal/dict.py +4 -4
  21. modal/dict.pyi +453 -51
  22. modal/environments.pyi +41 -9
  23. modal/exception.py +6 -2
  24. modal/experimental/__init__.py +90 -0
  25. modal/experimental/ipython.py +11 -7
  26. modal/file_io.pyi +236 -45
  27. modal/functions.pyi +573 -65
  28. modal/gpu.py +1 -1
  29. modal/image.py +1 -1
  30. modal/image.pyi +1256 -74
  31. modal/io_streams.py +8 -4
  32. modal/io_streams.pyi +348 -38
  33. modal/mount.pyi +261 -31
  34. modal/network_file_system.py +3 -3
  35. modal/network_file_system.pyi +307 -26
  36. modal/object.pyi +48 -9
  37. modal/parallel_map.py +93 -19
  38. modal/parallel_map.pyi +160 -15
  39. modal/partial_function.pyi +255 -14
  40. modal/proxy.py +1 -1
  41. modal/proxy.pyi +28 -3
  42. modal/queue.py +4 -4
  43. modal/queue.pyi +447 -30
  44. modal/runner.pyi +160 -22
  45. modal/sandbox.py +8 -7
  46. modal/sandbox.pyi +310 -50
  47. modal/schedule.py +1 -1
  48. modal/secret.py +2 -2
  49. modal/secret.pyi +164 -15
  50. modal/snapshot.pyi +25 -4
  51. modal/token_flow.pyi +28 -8
  52. modal/volume.py +41 -4
  53. modal/volume.pyi +693 -59
  54. {modal-1.0.4.dev10.dist-info → modal-1.0.5.dist-info}/METADATA +3 -3
  55. {modal-1.0.4.dev10.dist-info → modal-1.0.5.dist-info}/RECORD +67 -67
  56. modal_proto/api.proto +57 -0
  57. modal_proto/api_grpc.py +48 -0
  58. modal_proto/api_pb2.py +874 -780
  59. modal_proto/api_pb2.pyi +198 -9
  60. modal_proto/api_pb2_grpc.py +100 -0
  61. modal_proto/api_pb2_grpc.pyi +32 -0
  62. modal_proto/modal_api_grpc.py +3 -0
  63. modal_version/__init__.py +1 -1
  64. {modal-1.0.4.dev10.dist-info → modal-1.0.5.dist-info}/WHEEL +0 -0
  65. {modal-1.0.4.dev10.dist-info → modal-1.0.5.dist-info}/entry_points.txt +0 -0
  66. {modal-1.0.4.dev10.dist-info → modal-1.0.5.dist-info}/licenses/LICENSE +0 -0
  67. {modal-1.0.4.dev10.dist-info → modal-1.0.5.dist-info}/top_level.txt +0 -0
@@ -28,6 +28,7 @@ from grpclib.protocol import H2Protocol
28
28
  from modal.exception import AuthError, ConnectionError
29
29
  from modal_version import __version__
30
30
 
31
+ from .async_utils import retry
31
32
  from .logger import logger
32
33
 
33
34
  RequestType = TypeVar("RequestType", bound=Message)
@@ -167,8 +168,9 @@ def create_channel(
167
168
  return channel
168
169
 
169
170
 
171
+ @retry(n_attempts=5, base_delay=0.1)
170
172
  async def connect_channel(channel: grpclib.client.Channel):
171
- """Connects socket (potentially raising errors raising to connectivity."""
173
+ """Connect to socket and raise exceptions when there is a connection issue."""
172
174
  await channel.__connect__()
173
175
 
174
176
 
@@ -198,6 +200,7 @@ async def retry_transient_errors(
198
200
  total_timeout: Optional[float] = None, # timeout for the entire function call
199
201
  attempt_timeout_floor=2.0, # always have at least this much timeout (only for total_timeout)
200
202
  retry_warning_message: Optional[RetryWarningMessage] = None,
203
+ metadata: list[tuple[str, str]] = [],
201
204
  ) -> ResponseType:
202
205
  """Retry on transient gRPC failures with back-off until max_retries is reached.
203
206
  If max_retries is None, retry forever."""
@@ -216,9 +219,13 @@ async def retry_transient_errors(
216
219
  total_deadline = None
217
220
 
218
221
  while True:
219
- metadata = [("x-idempotency-key", idempotency_key), ("x-retry-attempt", str(n_retries))]
222
+ attempt_metadata = [
223
+ ("x-idempotency-key", idempotency_key),
224
+ ("x-retry-attempt", str(n_retries)),
225
+ *metadata,
226
+ ]
220
227
  if n_retries > 0:
221
- metadata.append(("x-retry-delay", str(time.time() - t0)))
228
+ attempt_metadata.append(("x-retry-delay", str(time.time() - t0)))
222
229
  timeouts = []
223
230
  if attempt_timeout is not None:
224
231
  timeouts.append(attempt_timeout)
@@ -229,7 +236,7 @@ async def retry_transient_errors(
229
236
  else:
230
237
  timeout = None
231
238
  try:
232
- return await fn(*args, metadata=metadata, timeout=timeout)
239
+ return await fn(*args, metadata=attempt_metadata, timeout=timeout)
233
240
  except (StreamTerminatedError, GRPCError, OSError, asyncio.TimeoutError, AttributeError) as exc:
234
241
  if isinstance(exc, GRPCError) and exc.status not in status_codes:
235
242
  if exc.status == Status.UNAUTHENTICATED:
modal/app.py CHANGED
@@ -550,8 +550,8 @@ class _App:
550
550
  modal run app_module.py
551
551
  ```
552
552
 
553
- Note that an explicit [`app.run()`](/docs/reference/modal.App#run) is not needed, as an
554
- [app](/docs/guide/apps) is automatically created for you.
553
+ Note that an explicit [`app.run()`](https://modal.com/docs/reference/modal.App#run) is not needed, as an
554
+ [app](https://modal.com/docs/guide/apps) is automatically created for you.
555
555
 
556
556
  **Multiple Entrypoints**
557
557
 
@@ -657,7 +657,7 @@ class _App:
657
657
  _experimental_buffer_containers: Optional[int] = None, # Now stable API with `buffer_containers`
658
658
  allow_cross_region_volumes: Optional[bool] = None, # Always True on the Modal backend now
659
659
  ) -> _FunctionDecoratorType:
660
- """Decorator to register a new Modal [Function](/docs/reference/modal.Function) with this App."""
660
+ """Decorator to register a new Modal Function with this App."""
661
661
  if isinstance(_warn_parentheses_missing, _Image):
662
662
  # Handle edge case where maybe (?) some users passed image as a positional arg
663
663
  raise InvalidError("`image` needs to be a keyword argument: `@app.function(image=image)`.")
@@ -731,7 +731,7 @@ class _App:
731
731
  dedent(
732
732
  """
733
733
  The `@app.function` decorator must apply to functions in global scope,
734
- unless `serialize=True` is set.
734
+ unless `serialized=True` is set.
735
735
  If trying to apply additional decorators, they may need to use `functools.wraps`.
736
736
  """
737
737
  )
@@ -881,7 +881,7 @@ class _App:
881
881
  allow_cross_region_volumes: Optional[bool] = None, # Always True on the Modal backend now
882
882
  ) -> Callable[[Union[CLS_T, _PartialFunction]], CLS_T]:
883
883
  """
884
- Decorator to register a new Modal [Cls](/docs/reference/modal.Cls) with this App.
884
+ Decorator to register a new Modal [Cls](https://modal.com/docs/reference/modal.Cls) with this App.
885
885
  """
886
886
  if _warn_parentheses_missing:
887
887
  raise InvalidError("Did you forget parentheses? Suggestion: `@app.cls()`.")