modAL 1.0.5__tar.gz → 1.0.5.dev1__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.
- {modal-1.0.5 → modal-1.0.5.dev1}/PKG-INFO +2 -2
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_clustered_functions.pyi +3 -13
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_functions.py +46 -84
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_partial_function.py +1 -1
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_runtime/container_io_manager.pyi +40 -222
- modal-1.0.5.dev1/modal/_runtime/execution_context.pyi +24 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_serialization.py +2 -25
- modal-1.0.5.dev1/modal/_tunnel.pyi +37 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_utils/blob_utils.py +19 -56
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_utils/function_utils.py +7 -33
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_utils/grpc_utils.py +4 -11
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/app.py +5 -5
- modal-1.0.5.dev1/modal/app.pyi +510 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/cli/run.py +1 -2
- modal-1.0.5.dev1/modal/client.pyi +223 -0
- modal-1.0.5.dev1/modal/cloud_bucket_mount.pyi +51 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/cls.py +7 -7
- modal-1.0.5.dev1/modal/cls.pyi +308 -0
- modal-1.0.5.dev1/modal/container_process.pyi +86 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/dict.py +4 -4
- modal-1.0.5.dev1/modal/dict.pyi +209 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/environments.pyi +9 -41
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/exception.py +2 -6
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/experimental/__init__.py +0 -90
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/experimental/ipython.py +7 -11
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/file_io.pyi +45 -236
- modal-1.0.5.dev1/modal/functions.pyi +382 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/gpu.py +1 -1
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/image.py +1 -1
- modal-1.0.5.dev1/modal/image.pyi +610 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/io_streams.py +4 -8
- modal-1.0.5.dev1/modal/io_streams.pyi +124 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/mount.pyi +31 -261
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/network_file_system.py +3 -3
- modal-1.0.5.dev1/modal/network_file_system.pyi +222 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/object.pyi +9 -48
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/parallel_map.py +9 -80
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/parallel_map.pyi +15 -160
- modal-1.0.5.dev1/modal/partial_function.pyi +172 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/proxy.py +1 -1
- modal-1.0.5.dev1/modal/proxy.pyi +12 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/queue.py +4 -4
- modal-1.0.5.dev1/modal/queue.pyi +300 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/runner.pyi +22 -160
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/sandbox.py +7 -8
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/sandbox.pyi +50 -310
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/schedule.py +1 -1
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/secret.py +2 -2
- modal-1.0.5.dev1/modal/secret.pyi +93 -0
- modal-1.0.5.dev1/modal/snapshot.pyi +18 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/token_flow.pyi +8 -28
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/volume.py +4 -41
- modal-1.0.5.dev1/modal/volume.pyi +537 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal.egg-info/PKG-INFO +2 -2
- {modal-1.0.5 → modal-1.0.5.dev1}/modal.egg-info/requires.txt +1 -1
- {modal-1.0.5 → modal-1.0.5.dev1}/modal_proto/api.proto +0 -56
- {modal-1.0.5 → modal-1.0.5.dev1}/modal_proto/api_grpc.py +0 -48
- {modal-1.0.5 → modal-1.0.5.dev1}/modal_proto/api_pb2.py +780 -874
- {modal-1.0.5 → modal-1.0.5.dev1}/modal_proto/api_pb2.pyi +8 -194
- {modal-1.0.5 → modal-1.0.5.dev1}/modal_proto/api_pb2_grpc.py +0 -100
- {modal-1.0.5 → modal-1.0.5.dev1}/modal_proto/api_pb2_grpc.pyi +0 -32
- {modal-1.0.5 → modal-1.0.5.dev1}/modal_proto/modal_api_grpc.py +0 -3
- {modal-1.0.5 → modal-1.0.5.dev1}/modal_version/__init__.py +1 -1
- {modal-1.0.5 → modal-1.0.5.dev1}/pyproject.toml +1 -1
- modal-1.0.5/modal/_runtime/execution_context.pyi +0 -78
- modal-1.0.5/modal/_tunnel.pyi +0 -405
- modal-1.0.5/modal/app.pyi +0 -1120
- modal-1.0.5/modal/client.pyi +0 -411
- modal-1.0.5/modal/cloud_bucket_mount.pyi +0 -239
- modal-1.0.5/modal/cls.pyi +0 -715
- modal-1.0.5/modal/container_process.pyi +0 -175
- modal-1.0.5/modal/dict.pyi +0 -611
- modal-1.0.5/modal/functions.pyi +0 -890
- modal-1.0.5/modal/image.pyi +0 -1792
- modal-1.0.5/modal/io_streams.pyi +0 -434
- modal-1.0.5/modal/network_file_system.pyi +0 -503
- modal-1.0.5/modal/partial_function.pyi +0 -413
- modal-1.0.5/modal/proxy.pyi +0 -37
- modal-1.0.5/modal/queue.pyi +0 -717
- modal-1.0.5/modal/secret.pyi +0 -242
- modal-1.0.5/modal/snapshot.pyi +0 -39
- modal-1.0.5/modal/volume.pyi +0 -1171
- {modal-1.0.5 → modal-1.0.5.dev1}/LICENSE +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/README.md +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/__init__.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/__main__.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_clustered_functions.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_container_entrypoint.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_ipython.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_location.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_object.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_output.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_pty.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_resolver.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_resources.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_runtime/__init__.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_runtime/asgi.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_runtime/container_io_manager.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_runtime/execution_context.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_runtime/gpu_memory_snapshot.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_runtime/telemetry.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_runtime/user_code_imports.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_traceback.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_tunnel.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_type_manager.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_utils/__init__.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_utils/app_utils.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_utils/async_utils.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_utils/bytes_io_segment_payload.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_utils/deprecation.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_utils/docker_utils.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_utils/git_utils.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_utils/grpc_testing.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_utils/hash_utils.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_utils/http_utils.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_utils/jwt_utils.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_utils/logger.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_utils/mount_utils.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_utils/name_utils.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_utils/package_utils.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_utils/pattern_utils.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_utils/rand_pb_testing.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_utils/shell_utils.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_utils/time_utils.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_vendor/__init__.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_vendor/a2wsgi_wsgi.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_vendor/cloudpickle.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_vendor/tblib.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/_watcher.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/call_graph.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/cli/__init__.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/cli/_download.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/cli/_traceback.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/cli/app.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/cli/cluster.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/cli/config.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/cli/container.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/cli/dict.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/cli/entry_point.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/cli/environment.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/cli/import_refs.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/cli/launch.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/cli/network_file_system.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/cli/profile.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/cli/programs/__init__.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/cli/programs/run_jupyter.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/cli/programs/vscode.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/cli/queues.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/cli/secret.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/cli/token.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/cli/utils.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/cli/volume.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/client.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/cloud_bucket_mount.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/config.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/container_process.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/environments.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/file_io.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/file_pattern_matcher.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/functions.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/mount.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/object.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/output.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/partial_function.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/py.typed +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/requirements/2023.12.312.txt +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/requirements/2023.12.txt +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/requirements/2024.04.txt +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/requirements/2024.10.txt +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/requirements/PREVIEW.txt +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/requirements/README.md +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/requirements/base-images.json +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/retries.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/runner.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/running_app.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/scheduler_placement.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/serving.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/serving.pyi +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/snapshot.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/stream_type.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal/token_flow.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal.egg-info/SOURCES.txt +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal.egg-info/dependency_links.txt +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal.egg-info/entry_points.txt +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal.egg-info/top_level.txt +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal_docs/__init__.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal_docs/gen_cli_docs.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal_docs/gen_reference_docs.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal_docs/mdmd/__init__.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal_docs/mdmd/mdmd.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal_docs/mdmd/signatures.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal_proto/__init__.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal_proto/modal_options_grpc.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal_proto/options.proto +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal_proto/options_grpc.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal_proto/options_pb2.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal_proto/options_pb2.pyi +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal_proto/options_pb2_grpc.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal_proto/options_pb2_grpc.pyi +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal_proto/py.typed +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/modal_version/__main__.py +0 -0
- {modal-1.0.5 → modal-1.0.5.dev1}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: modal
|
|
3
|
-
Version: 1.0.5
|
|
3
|
+
Version: 1.0.5.dev1
|
|
4
4
|
Summary: Python client library for Modal
|
|
5
5
|
Author-email: Modal Labs <support@modal.com>
|
|
6
6
|
License: Apache-2.0
|
|
@@ -19,7 +19,7 @@ License-File: LICENSE
|
|
|
19
19
|
Requires-Dist: aiohttp
|
|
20
20
|
Requires-Dist: certifi
|
|
21
21
|
Requires-Dist: click~=8.1.0
|
|
22
|
-
Requires-Dist: grpclib
|
|
22
|
+
Requires-Dist: grpclib==0.4.7
|
|
23
23
|
Requires-Dist: protobuf!=4.24.0,<7.0,>=3.19
|
|
24
24
|
Requires-Dist: rich>=12.0.0
|
|
25
25
|
Requires-Dist: synchronicity~=0.9.15
|
|
@@ -3,22 +3,12 @@ import typing
|
|
|
3
3
|
import typing_extensions
|
|
4
4
|
|
|
5
5
|
class ClusterInfo:
|
|
6
|
-
"""ClusterInfo(rank: int, container_ips: list[str])"""
|
|
7
|
-
|
|
8
6
|
rank: int
|
|
9
7
|
container_ips: list[str]
|
|
10
8
|
|
|
11
|
-
def __init__(self, rank: int, container_ips: list[str]) -> None:
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
def __repr__(self):
|
|
16
|
-
"""Return repr(self)."""
|
|
17
|
-
...
|
|
18
|
-
|
|
19
|
-
def __eq__(self, other):
|
|
20
|
-
"""Return self==value."""
|
|
21
|
-
...
|
|
9
|
+
def __init__(self, rank: int, container_ips: list[str]) -> None: ...
|
|
10
|
+
def __repr__(self): ...
|
|
11
|
+
def __eq__(self, other): ...
|
|
22
12
|
|
|
23
13
|
def get_cluster_info() -> ClusterInfo: ...
|
|
24
14
|
async def _initialize_clustered_function(client: modal.client._Client, task_id: str, world_size: int): ...
|
|
@@ -15,6 +15,7 @@ import typing_extensions
|
|
|
15
15
|
from google.protobuf.message import Message
|
|
16
16
|
from grpclib import GRPCError, Status
|
|
17
17
|
from synchronicity.combined_types import MethodWithAio
|
|
18
|
+
from synchronicity.exceptions import UserCodeException
|
|
18
19
|
|
|
19
20
|
from modal_proto import api_pb2
|
|
20
21
|
from modal_proto.modal_api_grpc import ModalClientModal
|
|
@@ -62,6 +63,8 @@ from .cloud_bucket_mount import _CloudBucketMount, cloud_bucket_mounts_to_proto
|
|
|
62
63
|
from .config import config
|
|
63
64
|
from .exception import (
|
|
64
65
|
ExecutionError,
|
|
66
|
+
FunctionTimeoutError,
|
|
67
|
+
InternalFailure,
|
|
65
68
|
InvalidError,
|
|
66
69
|
NotFoundError,
|
|
67
70
|
OutputExpiredError,
|
|
@@ -141,13 +144,7 @@ class _Invocation:
|
|
|
141
144
|
stub = client.stub
|
|
142
145
|
|
|
143
146
|
function_id = function.object_id
|
|
144
|
-
item = await _create_input(
|
|
145
|
-
args,
|
|
146
|
-
kwargs,
|
|
147
|
-
stub,
|
|
148
|
-
method_name=function._use_method_name,
|
|
149
|
-
function_call_invocation_type=function_call_invocation_type,
|
|
150
|
-
)
|
|
147
|
+
item = await _create_input(args, kwargs, stub, method_name=function._use_method_name)
|
|
151
148
|
|
|
152
149
|
request = api_pb2.FunctionMapRequest(
|
|
153
150
|
function_id=function_id,
|
|
@@ -260,7 +257,7 @@ class _Invocation:
|
|
|
260
257
|
request,
|
|
261
258
|
)
|
|
262
259
|
|
|
263
|
-
async def _get_single_output(self, expected_jwt: Optional[str] = None) ->
|
|
260
|
+
async def _get_single_output(self, expected_jwt: Optional[str] = None) -> Any:
|
|
264
261
|
# waits indefinitely for a single result for the function, and clear the outputs buffer after
|
|
265
262
|
item: api_pb2.FunctionGetOutputsItem = (
|
|
266
263
|
await self.pop_function_call_outputs(
|
|
@@ -269,7 +266,7 @@ class _Invocation:
|
|
|
269
266
|
input_jwts=[expected_jwt] if expected_jwt else None,
|
|
270
267
|
)
|
|
271
268
|
).outputs[0]
|
|
272
|
-
return item
|
|
269
|
+
return await _process_result(item.result, item.data_format, self.stub, self.client)
|
|
273
270
|
|
|
274
271
|
async def run_function(self) -> Any:
|
|
275
272
|
# Use retry logic only if retry policy is specified and
|
|
@@ -281,30 +278,23 @@ class _Invocation:
|
|
|
281
278
|
or ctx.function_call_invocation_type != api_pb2.FUNCTION_CALL_INVOCATION_TYPE_SYNC
|
|
282
279
|
or not ctx.sync_client_retries_enabled
|
|
283
280
|
):
|
|
284
|
-
|
|
285
|
-
return await _process_result(item.result, item.data_format, self.stub, self.client)
|
|
281
|
+
return await self._get_single_output()
|
|
286
282
|
|
|
287
283
|
# User errors including timeouts are managed by the user specified retry policy.
|
|
288
284
|
user_retry_manager = RetryManager(ctx.retry_policy)
|
|
289
285
|
|
|
290
286
|
while True:
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
api_pb2.GenericResult.GENERIC_STATUS_TERMINATED,
|
|
295
|
-
):
|
|
296
|
-
# success or cancellations are "final" results
|
|
297
|
-
return await _process_result(item.result, item.data_format, self.stub, self.client)
|
|
298
|
-
|
|
299
|
-
if item.result.status != api_pb2.GenericResult.GENERIC_STATUS_INTERNAL_FAILURE:
|
|
300
|
-
# non-internal failures get a delay before retrying
|
|
287
|
+
try:
|
|
288
|
+
return await self._get_single_output(ctx.input_jwt)
|
|
289
|
+
except (UserCodeException, FunctionTimeoutError) as exc:
|
|
301
290
|
delay_ms = user_retry_manager.get_delay_ms()
|
|
302
291
|
if delay_ms is None:
|
|
303
|
-
|
|
304
|
-
# to an exception:
|
|
305
|
-
return await _process_result(item.result, item.data_format, self.stub, self.client)
|
|
292
|
+
raise exc
|
|
306
293
|
await asyncio.sleep(delay_ms / 1000)
|
|
307
|
-
|
|
294
|
+
except InternalFailure:
|
|
295
|
+
# For system failures on the server, we retry immediately,
|
|
296
|
+
# and the failure does not count towards the retry policy.
|
|
297
|
+
pass
|
|
308
298
|
await self._retry_input()
|
|
309
299
|
|
|
310
300
|
async def poll_function(self, timeout: Optional[float] = None):
|
|
@@ -362,14 +352,12 @@ class _InputPlaneInvocation:
|
|
|
362
352
|
client: _Client,
|
|
363
353
|
input_item: api_pb2.FunctionPutInputsItem,
|
|
364
354
|
function_id: str,
|
|
365
|
-
input_plane_region: str,
|
|
366
355
|
):
|
|
367
356
|
self.stub = stub
|
|
368
357
|
self.client = client # Used by the deserializer.
|
|
369
358
|
self.attempt_token = attempt_token
|
|
370
359
|
self.input_item = input_item
|
|
371
360
|
self.function_id = function_id
|
|
372
|
-
self.input_plane_region = input_plane_region
|
|
373
361
|
|
|
374
362
|
@staticmethod
|
|
375
363
|
async def create(
|
|
@@ -379,27 +367,21 @@ class _InputPlaneInvocation:
|
|
|
379
367
|
*,
|
|
380
368
|
client: _Client,
|
|
381
369
|
input_plane_url: str,
|
|
382
|
-
input_plane_region: str,
|
|
383
370
|
) -> "_InputPlaneInvocation":
|
|
384
371
|
stub = await client.get_stub(input_plane_url)
|
|
385
372
|
|
|
386
373
|
function_id = function.object_id
|
|
387
|
-
|
|
388
|
-
# Note: Blob upload is done on the control plane stub, not the input plane stub!
|
|
389
|
-
input_item = await _create_input(args, kwargs, control_plane_stub, method_name=function._use_method_name)
|
|
374
|
+
input_item = await _create_input(args, kwargs, stub, method_name=function._use_method_name)
|
|
390
375
|
|
|
391
376
|
request = api_pb2.AttemptStartRequest(
|
|
392
377
|
function_id=function_id,
|
|
393
378
|
parent_input_id=current_input_id() or "",
|
|
394
379
|
input=input_item,
|
|
395
380
|
)
|
|
396
|
-
|
|
397
|
-
if input_plane_region and input_plane_region != "":
|
|
398
|
-
metadata.append(("x-modal-input-plane-region", input_plane_region))
|
|
399
|
-
response = await retry_transient_errors(stub.AttemptStart, request, metadata=metadata)
|
|
381
|
+
response = await retry_transient_errors(stub.AttemptStart, request)
|
|
400
382
|
attempt_token = response.attempt_token
|
|
401
383
|
|
|
402
|
-
return _InputPlaneInvocation(stub, attempt_token, client, input_item, function_id
|
|
384
|
+
return _InputPlaneInvocation(stub, attempt_token, client, input_item, function_id)
|
|
403
385
|
|
|
404
386
|
async def run_function(self) -> Any:
|
|
405
387
|
# This will retry when the server returns GENERIC_STATUS_INTERNAL_FAILURE, i.e. lost inputs or worker preemption
|
|
@@ -411,41 +393,33 @@ class _InputPlaneInvocation:
|
|
|
411
393
|
timeout_secs=OUTPUTS_TIMEOUT,
|
|
412
394
|
requested_at=time.time(),
|
|
413
395
|
)
|
|
414
|
-
metadata: list[tuple[str, str]] = []
|
|
415
|
-
if self.input_plane_region and self.input_plane_region != "":
|
|
416
|
-
metadata.append(("x-modal-input-plane-region", self.input_plane_region))
|
|
417
396
|
await_response: api_pb2.AttemptAwaitResponse = await retry_transient_errors(
|
|
418
397
|
self.stub.AttemptAwait,
|
|
419
398
|
await_request,
|
|
420
399
|
attempt_timeout=OUTPUTS_TIMEOUT + ATTEMPT_TIMEOUT_GRACE_PERIOD,
|
|
421
|
-
metadata=metadata,
|
|
422
400
|
)
|
|
423
401
|
|
|
424
|
-
|
|
425
|
-
if await_response.output
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
metadata=metadata,
|
|
442
|
-
)
|
|
443
|
-
self.attempt_token = retry_response.attempt_token
|
|
444
|
-
continue
|
|
445
|
-
|
|
446
|
-
return await _process_result(
|
|
447
|
-
await_response.output.result, await_response.output.data_format, self.stub, self.client
|
|
402
|
+
try:
|
|
403
|
+
if await_response.HasField("output"):
|
|
404
|
+
return await _process_result(
|
|
405
|
+
await_response.output.result, await_response.output.data_format, self.stub, self.client
|
|
406
|
+
)
|
|
407
|
+
except InternalFailure as e:
|
|
408
|
+
internal_failure_count += 1
|
|
409
|
+
# Limit the number of times we retry
|
|
410
|
+
if internal_failure_count >= MAX_INTERNAL_FAILURE_COUNT:
|
|
411
|
+
raise e
|
|
412
|
+
# For system failures on the server, we retry immediately,
|
|
413
|
+
# and the failure does not count towards the retry policy.
|
|
414
|
+
retry_request = api_pb2.AttemptRetryRequest(
|
|
415
|
+
function_id=self.function_id,
|
|
416
|
+
parent_input_id=current_input_id() or "",
|
|
417
|
+
input=self.input_item,
|
|
418
|
+
attempt_token=self.attempt_token,
|
|
448
419
|
)
|
|
420
|
+
# TODO(ryan): Add exponential backoff?
|
|
421
|
+
retry_response = await retry_transient_errors(self.stub.AttemptRetry, retry_request)
|
|
422
|
+
self.attempt_token = retry_response.attempt_token
|
|
449
423
|
|
|
450
424
|
|
|
451
425
|
# Wrapper type for api_pb2.FunctionStats
|
|
@@ -799,7 +773,6 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
|
|
|
799
773
|
req.method_definitions[method_name].CopyFrom(method_definition)
|
|
800
774
|
elif webhook_config:
|
|
801
775
|
req.webhook_config.CopyFrom(webhook_config)
|
|
802
|
-
|
|
803
776
|
response = await retry_transient_errors(resolver.client.stub.FunctionPrecreate, req)
|
|
804
777
|
self._hydrate(response.function_id, resolver.client, response.handle_metadata)
|
|
805
778
|
|
|
@@ -854,7 +827,6 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
|
|
|
854
827
|
mount_path=path,
|
|
855
828
|
volume_id=volume.object_id,
|
|
856
829
|
allow_background_commits=True,
|
|
857
|
-
read_only=volume._read_only,
|
|
858
830
|
)
|
|
859
831
|
for path, volume in validated_volumes_no_cloud_buckets
|
|
860
832
|
]
|
|
@@ -1108,7 +1080,6 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
|
|
|
1108
1080
|
mount_path=path,
|
|
1109
1081
|
volume_id=volume.object_id,
|
|
1110
1082
|
allow_background_commits=True,
|
|
1111
|
-
read_only=volume._read_only,
|
|
1112
1083
|
)
|
|
1113
1084
|
for path, volume in options.validated_volumes
|
|
1114
1085
|
]
|
|
@@ -1281,9 +1252,9 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
|
|
|
1281
1252
|
) -> "_Function":
|
|
1282
1253
|
"""Reference a Function from a deployed App by its name.
|
|
1283
1254
|
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
time it is actually used.
|
|
1255
|
+
In contrast to `modal.Function.lookup`, this is a lazy method
|
|
1256
|
+
that defers hydrating the local object with metadata from
|
|
1257
|
+
Modal servers until the first time it is actually used.
|
|
1287
1258
|
|
|
1288
1259
|
```python
|
|
1289
1260
|
f = modal.Function.from_name("other-app", "function")
|
|
@@ -1406,7 +1377,6 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
|
|
|
1406
1377
|
self._method_handle_metadata = dict(metadata.method_handle_metadata)
|
|
1407
1378
|
self._definition_id = metadata.definition_id
|
|
1408
1379
|
self._input_plane_url = metadata.input_plane_url
|
|
1409
|
-
self._input_plane_region = metadata.input_plane_region
|
|
1410
1380
|
|
|
1411
1381
|
def _get_metadata(self):
|
|
1412
1382
|
# Overridden concrete implementation of base class method
|
|
@@ -1422,7 +1392,6 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
|
|
|
1422
1392
|
method_handle_metadata=self._method_handle_metadata,
|
|
1423
1393
|
function_schema=self._metadata.function_schema if self._metadata else None,
|
|
1424
1394
|
input_plane_url=self._input_plane_url,
|
|
1425
|
-
input_plane_region=self._input_plane_region,
|
|
1426
1395
|
)
|
|
1427
1396
|
|
|
1428
1397
|
def _check_no_web_url(self, fn_name: str):
|
|
@@ -1469,11 +1438,7 @@ Use the `Function.get_web_url()` method instead.
|
|
|
1469
1438
|
|
|
1470
1439
|
@live_method_gen
|
|
1471
1440
|
async def _map(
|
|
1472
|
-
self,
|
|
1473
|
-
input_queue: _SynchronizedQueue,
|
|
1474
|
-
order_outputs: bool,
|
|
1475
|
-
return_exceptions: bool,
|
|
1476
|
-
wrap_returned_exceptions: bool,
|
|
1441
|
+
self, input_queue: _SynchronizedQueue, order_outputs: bool, return_exceptions: bool
|
|
1477
1442
|
) -> AsyncGenerator[Any, None]:
|
|
1478
1443
|
"""mdmd:hidden
|
|
1479
1444
|
|
|
@@ -1501,7 +1466,6 @@ Use the `Function.get_web_url()` method instead.
|
|
|
1501
1466
|
self.client,
|
|
1502
1467
|
order_outputs,
|
|
1503
1468
|
return_exceptions,
|
|
1504
|
-
wrap_returned_exceptions,
|
|
1505
1469
|
count_update_callback,
|
|
1506
1470
|
api_pb2.FUNCTION_CALL_INVOCATION_TYPE_SYNC,
|
|
1507
1471
|
)
|
|
@@ -1518,7 +1482,6 @@ Use the `Function.get_web_url()` method instead.
|
|
|
1518
1482
|
kwargs,
|
|
1519
1483
|
client=self.client,
|
|
1520
1484
|
input_plane_url=self._input_plane_url,
|
|
1521
|
-
input_plane_region=self._input_plane_region,
|
|
1522
1485
|
)
|
|
1523
1486
|
else:
|
|
1524
1487
|
invocation = await _Invocation.create(
|
|
@@ -1699,9 +1662,8 @@ Use the `Function.get_web_url()` method instead.
|
|
|
1699
1662
|
async def spawn(self, *args: P.args, **kwargs: P.kwargs) -> "_FunctionCall[ReturnType]":
|
|
1700
1663
|
"""Calls the function with the given arguments, without waiting for the results.
|
|
1701
1664
|
|
|
1702
|
-
Returns a [`modal.FunctionCall`](
|
|
1703
|
-
|
|
1704
|
-
[`.get(timeout=...)`](https://modal.com/docs/reference/modal.FunctionCall#get).
|
|
1665
|
+
Returns a [`modal.FunctionCall`](/docs/reference/modal.FunctionCall) object, that can later be polled or
|
|
1666
|
+
waited for using [`.get(timeout=...)`](/docs/reference/modal.FunctionCall#get).
|
|
1705
1667
|
Conceptually similar to `multiprocessing.pool.apply_async`, or a Future/Promise in other contexts.
|
|
1706
1668
|
"""
|
|
1707
1669
|
self._check_no_web_url("spawn")
|
|
@@ -1777,7 +1739,7 @@ class _FunctionCall(typing.Generic[ReturnType], _Object, type_prefix="fc"):
|
|
|
1777
1739
|
"""Returns a structure representing the call graph from a given root
|
|
1778
1740
|
call ID, along with the status of execution for each node.
|
|
1779
1741
|
|
|
1780
|
-
See [`modal.call_graph`](
|
|
1742
|
+
See [`modal.call_graph`](/docs/reference/modal.call_graph) reference page
|
|
1781
1743
|
for documentation on the structure of the returned `InputInfo` items.
|
|
1782
1744
|
"""
|
|
1783
1745
|
assert self._client and self._client.stub
|
|
@@ -1791,7 +1753,7 @@ class _FunctionCall(typing.Generic[ReturnType], _Object, type_prefix="fc"):
|
|
|
1791
1753
|
terminate_containers: bool = False,
|
|
1792
1754
|
):
|
|
1793
1755
|
"""Cancels the function call, which will stop its execution and mark its inputs as
|
|
1794
|
-
[`TERMINATED`](
|
|
1756
|
+
[`TERMINATED`](/docs/reference/modal.call_graph#modalcall_graphinputstatus).
|
|
1795
1757
|
|
|
1796
1758
|
If `terminate_containers=True` - the containers running the cancelled inputs are all terminated
|
|
1797
1759
|
causing any non-cancelled inputs on those containers to be rescheduled in new containers.
|
|
@@ -538,7 +538,7 @@ def _wsgi_app(
|
|
|
538
538
|
Web Server Gateway Interface (WSGI) is a standard for synchronous Python web apps.
|
|
539
539
|
It has been [succeeded by the ASGI interface](https://asgi.readthedocs.io/en/latest/introduction.html#wsgi-compatibility)
|
|
540
540
|
which is compatible with ASGI and supports additional functionality such as web sockets.
|
|
541
|
-
Modal supports ASGI via [`asgi_app`](
|
|
541
|
+
Modal supports ASGI via [`asgi_app`](/docs/reference/modal.asgi_app).
|
|
542
542
|
|
|
543
543
|
**Usage:**
|
|
544
544
|
|