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.
- modal/_clustered_functions.pyi +13 -3
- modal/_functions.py +84 -46
- modal/_partial_function.py +1 -1
- modal/_runtime/container_io_manager.pyi +222 -40
- modal/_runtime/execution_context.pyi +60 -6
- modal/_serialization.py +25 -2
- modal/_tunnel.pyi +380 -12
- modal/_utils/async_utils.py +1 -1
- modal/_utils/blob_utils.py +56 -19
- modal/_utils/function_utils.py +33 -7
- modal/_utils/grpc_utils.py +11 -4
- modal/app.py +5 -5
- modal/app.pyi +658 -48
- modal/cli/run.py +2 -1
- modal/client.pyi +224 -36
- modal/cloud_bucket_mount.pyi +192 -4
- modal/cls.py +57 -16
- modal/cls.pyi +442 -34
- modal/container_process.pyi +103 -14
- modal/dict.py +4 -4
- modal/dict.pyi +453 -51
- modal/environments.pyi +41 -9
- modal/exception.py +6 -2
- modal/experimental/__init__.py +90 -0
- modal/experimental/ipython.py +11 -7
- modal/file_io.pyi +236 -45
- modal/functions.pyi +573 -65
- modal/gpu.py +1 -1
- modal/image.py +1 -1
- modal/image.pyi +1256 -74
- modal/io_streams.py +8 -4
- modal/io_streams.pyi +348 -38
- modal/mount.pyi +261 -31
- modal/network_file_system.py +3 -3
- modal/network_file_system.pyi +307 -26
- modal/object.pyi +48 -9
- modal/parallel_map.py +93 -19
- modal/parallel_map.pyi +160 -15
- modal/partial_function.pyi +255 -14
- modal/proxy.py +1 -1
- modal/proxy.pyi +28 -3
- modal/queue.py +4 -4
- modal/queue.pyi +447 -30
- modal/runner.pyi +160 -22
- modal/sandbox.py +8 -7
- modal/sandbox.pyi +310 -50
- modal/schedule.py +1 -1
- modal/secret.py +2 -2
- modal/secret.pyi +164 -15
- modal/snapshot.pyi +25 -4
- modal/token_flow.pyi +28 -8
- modal/volume.py +41 -4
- modal/volume.pyi +693 -59
- {modal-1.0.4.dev10.dist-info → modal-1.0.5.dist-info}/METADATA +3 -3
- {modal-1.0.4.dev10.dist-info → modal-1.0.5.dist-info}/RECORD +67 -67
- modal_proto/api.proto +57 -0
- modal_proto/api_grpc.py +48 -0
- modal_proto/api_pb2.py +874 -780
- modal_proto/api_pb2.pyi +198 -9
- modal_proto/api_pb2_grpc.py +100 -0
- modal_proto/api_pb2_grpc.pyi +32 -0
- modal_proto/modal_api_grpc.py +3 -0
- modal_version/__init__.py +1 -1
- {modal-1.0.4.dev10.dist-info → modal-1.0.5.dist-info}/WHEEL +0 -0
- {modal-1.0.4.dev10.dist-info → modal-1.0.5.dist-info}/entry_points.txt +0 -0
- {modal-1.0.4.dev10.dist-info → modal-1.0.5.dist-info}/licenses/LICENSE +0 -0
- {modal-1.0.4.dev10.dist-info → modal-1.0.5.dist-info}/top_level.txt +0 -0
modal/_utils/grpc_utils.py
CHANGED
@@ -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
|
-
"""
|
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
|
-
|
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
|
-
|
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=
|
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
|
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 `
|
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()`.")
|