modal 0.62.115__py3-none-any.whl → 0.72.13__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/__init__.py +13 -9
- modal/__main__.py +41 -3
- modal/_clustered_functions.py +80 -0
- modal/_clustered_functions.pyi +22 -0
- modal/_container_entrypoint.py +402 -398
- modal/_ipython.py +3 -13
- modal/_location.py +17 -10
- modal/_output.py +243 -99
- modal/_pty.py +2 -2
- modal/_resolver.py +55 -60
- modal/_resources.py +26 -7
- modal/_runtime/__init__.py +1 -0
- modal/_runtime/asgi.py +519 -0
- modal/_runtime/container_io_manager.py +1025 -0
- modal/{execution_context.py → _runtime/execution_context.py} +11 -2
- modal/_runtime/telemetry.py +169 -0
- modal/_runtime/user_code_imports.py +356 -0
- modal/_serialization.py +123 -6
- modal/_traceback.py +47 -187
- modal/_tunnel.py +50 -14
- modal/_tunnel.pyi +19 -36
- modal/_utils/app_utils.py +3 -17
- modal/_utils/async_utils.py +386 -104
- modal/_utils/blob_utils.py +157 -186
- modal/_utils/bytes_io_segment_payload.py +97 -0
- modal/_utils/deprecation.py +89 -0
- modal/_utils/docker_utils.py +98 -0
- modal/_utils/function_utils.py +299 -98
- modal/_utils/grpc_testing.py +47 -34
- modal/_utils/grpc_utils.py +54 -21
- modal/_utils/hash_utils.py +51 -10
- modal/_utils/http_utils.py +39 -9
- modal/_utils/logger.py +2 -1
- modal/_utils/mount_utils.py +34 -16
- modal/_utils/name_utils.py +58 -0
- modal/_utils/package_utils.py +14 -1
- modal/_utils/pattern_utils.py +205 -0
- modal/_utils/rand_pb_testing.py +3 -3
- modal/_utils/shell_utils.py +15 -49
- modal/_vendor/a2wsgi_wsgi.py +62 -72
- modal/_vendor/cloudpickle.py +1 -1
- modal/_watcher.py +12 -10
- modal/app.py +561 -323
- modal/app.pyi +474 -262
- modal/call_graph.py +7 -6
- modal/cli/_download.py +22 -6
- modal/cli/_traceback.py +200 -0
- modal/cli/app.py +203 -42
- modal/cli/config.py +12 -5
- modal/cli/container.py +61 -13
- modal/cli/dict.py +128 -0
- modal/cli/entry_point.py +26 -13
- modal/cli/environment.py +40 -9
- modal/cli/import_refs.py +21 -48
- modal/cli/launch.py +28 -14
- modal/cli/network_file_system.py +57 -21
- modal/cli/profile.py +1 -1
- modal/cli/programs/run_jupyter.py +34 -9
- modal/cli/programs/vscode.py +58 -8
- modal/cli/queues.py +131 -0
- modal/cli/run.py +199 -96
- modal/cli/secret.py +5 -4
- modal/cli/token.py +7 -2
- modal/cli/utils.py +74 -8
- modal/cli/volume.py +97 -56
- modal/client.py +248 -144
- modal/client.pyi +156 -124
- modal/cloud_bucket_mount.py +43 -30
- modal/cloud_bucket_mount.pyi +32 -25
- modal/cls.py +528 -141
- modal/cls.pyi +189 -145
- modal/config.py +32 -15
- modal/container_process.py +177 -0
- modal/container_process.pyi +82 -0
- modal/dict.py +50 -54
- modal/dict.pyi +120 -164
- modal/environments.py +106 -5
- modal/environments.pyi +77 -25
- modal/exception.py +30 -43
- modal/experimental.py +62 -2
- modal/file_io.py +537 -0
- modal/file_io.pyi +235 -0
- modal/file_pattern_matcher.py +196 -0
- modal/functions.py +846 -428
- modal/functions.pyi +446 -387
- modal/gpu.py +57 -44
- modal/image.py +943 -417
- modal/image.pyi +584 -245
- modal/io_streams.py +434 -0
- modal/io_streams.pyi +122 -0
- modal/mount.py +223 -90
- modal/mount.pyi +241 -243
- modal/network_file_system.py +85 -86
- modal/network_file_system.pyi +151 -110
- modal/object.py +66 -36
- modal/object.pyi +166 -143
- modal/output.py +63 -0
- modal/parallel_map.py +73 -47
- modal/parallel_map.pyi +51 -63
- modal/partial_function.py +272 -107
- modal/partial_function.pyi +219 -120
- modal/proxy.py +15 -12
- modal/proxy.pyi +3 -8
- modal/queue.py +96 -72
- modal/queue.pyi +210 -135
- modal/requirements/2024.04.txt +2 -1
- modal/requirements/2024.10.txt +16 -0
- modal/requirements/README.md +21 -0
- modal/requirements/base-images.json +22 -0
- modal/retries.py +45 -4
- modal/runner.py +325 -203
- modal/runner.pyi +124 -110
- modal/running_app.py +27 -4
- modal/sandbox.py +509 -231
- modal/sandbox.pyi +396 -169
- modal/schedule.py +2 -2
- modal/scheduler_placement.py +20 -3
- modal/secret.py +41 -25
- modal/secret.pyi +62 -42
- modal/serving.py +39 -49
- modal/serving.pyi +37 -43
- modal/stream_type.py +15 -0
- modal/token_flow.py +5 -3
- modal/token_flow.pyi +37 -32
- modal/volume.py +123 -137
- modal/volume.pyi +228 -221
- {modal-0.62.115.dist-info → modal-0.72.13.dist-info}/METADATA +5 -5
- modal-0.72.13.dist-info/RECORD +174 -0
- {modal-0.62.115.dist-info → modal-0.72.13.dist-info}/top_level.txt +0 -1
- modal_docs/gen_reference_docs.py +3 -1
- modal_docs/mdmd/mdmd.py +0 -1
- modal_docs/mdmd/signatures.py +1 -2
- modal_global_objects/images/base_images.py +28 -0
- modal_global_objects/mounts/python_standalone.py +2 -2
- modal_proto/__init__.py +1 -1
- modal_proto/api.proto +1231 -531
- modal_proto/api_grpc.py +750 -430
- modal_proto/api_pb2.py +2102 -1176
- modal_proto/api_pb2.pyi +8859 -0
- modal_proto/api_pb2_grpc.py +1329 -675
- modal_proto/api_pb2_grpc.pyi +1416 -0
- modal_proto/modal_api_grpc.py +149 -0
- modal_proto/modal_options_grpc.py +3 -0
- modal_proto/options_pb2.pyi +20 -0
- modal_proto/options_pb2_grpc.pyi +7 -0
- modal_proto/py.typed +0 -0
- modal_version/__init__.py +1 -1
- modal_version/_version_generated.py +2 -2
- modal/_asgi.py +0 -370
- modal/_container_exec.py +0 -128
- modal/_container_io_manager.py +0 -646
- modal/_container_io_manager.pyi +0 -412
- modal/_sandbox_shell.py +0 -49
- modal/app_utils.py +0 -20
- modal/app_utils.pyi +0 -17
- modal/execution_context.pyi +0 -37
- modal/shared_volume.py +0 -23
- modal/shared_volume.pyi +0 -24
- modal-0.62.115.dist-info/RECORD +0 -207
- modal_global_objects/images/conda.py +0 -15
- modal_global_objects/images/debian_slim.py +0 -15
- modal_global_objects/images/micromamba.py +0 -15
- test/__init__.py +0 -1
- test/aio_test.py +0 -12
- test/async_utils_test.py +0 -279
- test/blob_test.py +0 -67
- test/cli_imports_test.py +0 -149
- test/cli_test.py +0 -674
- test/client_test.py +0 -203
- test/cloud_bucket_mount_test.py +0 -22
- test/cls_test.py +0 -636
- test/config_test.py +0 -149
- test/conftest.py +0 -1485
- test/container_app_test.py +0 -50
- test/container_test.py +0 -1405
- test/cpu_test.py +0 -23
- test/decorator_test.py +0 -85
- test/deprecation_test.py +0 -34
- test/dict_test.py +0 -51
- test/e2e_test.py +0 -68
- test/error_test.py +0 -7
- test/function_serialization_test.py +0 -32
- test/function_test.py +0 -791
- test/function_utils_test.py +0 -101
- test/gpu_test.py +0 -159
- test/grpc_utils_test.py +0 -82
- test/helpers.py +0 -47
- test/image_test.py +0 -814
- test/live_reload_test.py +0 -80
- test/lookup_test.py +0 -70
- test/mdmd_test.py +0 -329
- test/mount_test.py +0 -162
- test/mounted_files_test.py +0 -327
- test/network_file_system_test.py +0 -188
- test/notebook_test.py +0 -66
- test/object_test.py +0 -41
- test/package_utils_test.py +0 -25
- test/queue_test.py +0 -115
- test/resolver_test.py +0 -59
- test/retries_test.py +0 -67
- test/runner_test.py +0 -85
- test/sandbox_test.py +0 -191
- test/schedule_test.py +0 -15
- test/scheduler_placement_test.py +0 -57
- test/secret_test.py +0 -89
- test/serialization_test.py +0 -50
- test/stub_composition_test.py +0 -10
- test/stub_test.py +0 -361
- test/test_asgi_wrapper.py +0 -234
- test/token_flow_test.py +0 -18
- test/traceback_test.py +0 -135
- test/tunnel_test.py +0 -29
- test/utils_test.py +0 -88
- test/version_test.py +0 -14
- test/volume_test.py +0 -397
- test/watcher_test.py +0 -58
- test/webhook_test.py +0 -145
- {modal-0.62.115.dist-info → modal-0.72.13.dist-info}/LICENSE +0 -0
- {modal-0.62.115.dist-info → modal-0.72.13.dist-info}/WHEEL +0 -0
- {modal-0.62.115.dist-info → modal-0.72.13.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,82 @@
|
|
1
|
+
import modal.client
|
2
|
+
import modal.io_streams
|
3
|
+
import modal.stream_type
|
4
|
+
import typing
|
5
|
+
import typing_extensions
|
6
|
+
|
7
|
+
T = typing.TypeVar("T")
|
8
|
+
|
9
|
+
class _ContainerProcess(typing.Generic[T]):
|
10
|
+
_process_id: typing.Optional[str]
|
11
|
+
_stdout: modal.io_streams._StreamReader[T]
|
12
|
+
_stderr: modal.io_streams._StreamReader[T]
|
13
|
+
_stdin: modal.io_streams._StreamWriter
|
14
|
+
_text: bool
|
15
|
+
_by_line: bool
|
16
|
+
_returncode: typing.Optional[int]
|
17
|
+
|
18
|
+
def __init__(
|
19
|
+
self,
|
20
|
+
process_id: str,
|
21
|
+
client: modal.client._Client,
|
22
|
+
stdout: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
23
|
+
stderr: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
24
|
+
text: bool = True,
|
25
|
+
by_line: bool = False,
|
26
|
+
) -> None: ...
|
27
|
+
@property
|
28
|
+
def stdout(self) -> modal.io_streams._StreamReader[T]: ...
|
29
|
+
@property
|
30
|
+
def stderr(self) -> modal.io_streams._StreamReader[T]: ...
|
31
|
+
@property
|
32
|
+
def stdin(self) -> modal.io_streams._StreamWriter: ...
|
33
|
+
@property
|
34
|
+
def returncode(self) -> int: ...
|
35
|
+
async def poll(self) -> typing.Optional[int]: ...
|
36
|
+
async def wait(self) -> int: ...
|
37
|
+
async def attach(self, *, pty: typing.Optional[bool] = None): ...
|
38
|
+
|
39
|
+
class ContainerProcess(typing.Generic[T]):
|
40
|
+
_process_id: typing.Optional[str]
|
41
|
+
_stdout: modal.io_streams.StreamReader[T]
|
42
|
+
_stderr: modal.io_streams.StreamReader[T]
|
43
|
+
_stdin: modal.io_streams.StreamWriter
|
44
|
+
_text: bool
|
45
|
+
_by_line: bool
|
46
|
+
_returncode: typing.Optional[int]
|
47
|
+
|
48
|
+
def __init__(
|
49
|
+
self,
|
50
|
+
process_id: str,
|
51
|
+
client: modal.client.Client,
|
52
|
+
stdout: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
53
|
+
stderr: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
54
|
+
text: bool = True,
|
55
|
+
by_line: bool = False,
|
56
|
+
) -> None: ...
|
57
|
+
@property
|
58
|
+
def stdout(self) -> modal.io_streams.StreamReader[T]: ...
|
59
|
+
@property
|
60
|
+
def stderr(self) -> modal.io_streams.StreamReader[T]: ...
|
61
|
+
@property
|
62
|
+
def stdin(self) -> modal.io_streams.StreamWriter: ...
|
63
|
+
@property
|
64
|
+
def returncode(self) -> int: ...
|
65
|
+
|
66
|
+
class __poll_spec(typing_extensions.Protocol):
|
67
|
+
def __call__(self) -> typing.Optional[int]: ...
|
68
|
+
async def aio(self) -> typing.Optional[int]: ...
|
69
|
+
|
70
|
+
poll: __poll_spec
|
71
|
+
|
72
|
+
class __wait_spec(typing_extensions.Protocol):
|
73
|
+
def __call__(self) -> int: ...
|
74
|
+
async def aio(self) -> int: ...
|
75
|
+
|
76
|
+
wait: __wait_spec
|
77
|
+
|
78
|
+
class __attach_spec(typing_extensions.Protocol):
|
79
|
+
def __call__(self, *, pty: typing.Optional[bool] = None): ...
|
80
|
+
async def aio(self, *, pty: typing.Optional[bool] = None): ...
|
81
|
+
|
82
|
+
attach: __attach_spec
|
modal/dict.py
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
# Copyright Modal Labs 2022
|
2
|
-
from
|
2
|
+
from collections.abc import AsyncIterator
|
3
|
+
from typing import Any, Optional
|
3
4
|
|
5
|
+
from grpclib import GRPCError
|
4
6
|
from synchronicity.async_wrap import asynccontextmanager
|
5
7
|
|
6
8
|
from modal_proto import api_pb2
|
@@ -8,10 +10,12 @@ from modal_proto import api_pb2
|
|
8
10
|
from ._resolver import Resolver
|
9
11
|
from ._serialization import deserialize, serialize
|
10
12
|
from ._utils.async_utils import TaskContext, synchronize_api
|
11
|
-
from ._utils.
|
13
|
+
from ._utils.deprecation import renamed_parameter
|
14
|
+
from ._utils.grpc_utils import retry_transient_errors
|
15
|
+
from ._utils.name_utils import check_object_name
|
12
16
|
from .client import _Client
|
13
17
|
from .config import logger
|
14
|
-
from .exception import
|
18
|
+
from .exception import RequestSizeError
|
15
19
|
from .object import EPHEMERAL_OBJECT_HEARTBEAT_SLEEP, _get_environment_name, _Object, live_method, live_method_gen
|
16
20
|
|
17
21
|
|
@@ -54,25 +58,6 @@ class _Dict(_Object, type_prefix="di"):
|
|
54
58
|
For more examples, see the [guide](/docs/guide/dicts-and-queues#modal-dicts).
|
55
59
|
"""
|
56
60
|
|
57
|
-
@staticmethod
|
58
|
-
def new(data: Optional[dict] = None) -> "_Dict":
|
59
|
-
"""`Dict.new` is deprecated.
|
60
|
-
|
61
|
-
Please use `Dict.from_name` (for persisted) or `Dict.ephemeral` (for ephemeral) dicts.
|
62
|
-
"""
|
63
|
-
deprecation_warning((2024, 3, 19), Dict.new.__doc__)
|
64
|
-
|
65
|
-
async def _load(self: _Dict, resolver: Resolver, existing_object_id: Optional[str]):
|
66
|
-
serialized = _serialize_dict(data if data is not None else {})
|
67
|
-
req = api_pb2.DictCreateRequest(
|
68
|
-
app_id=resolver.app_id, data=serialized, existing_dict_id=existing_object_id
|
69
|
-
)
|
70
|
-
response = await resolver.client.stub.DictCreate(req)
|
71
|
-
logger.debug(f"Created dict with id {response.dict_id}")
|
72
|
-
self._hydrate(response.dict_id, resolver.client, None)
|
73
|
-
|
74
|
-
return _Dict._from_loader(_load, "Dict()")
|
75
|
-
|
76
61
|
def __init__(self, data={}):
|
77
62
|
"""mdmd:hidden"""
|
78
63
|
raise RuntimeError(
|
@@ -82,7 +67,7 @@ class _Dict(_Object, type_prefix="di"):
|
|
82
67
|
@classmethod
|
83
68
|
@asynccontextmanager
|
84
69
|
async def ephemeral(
|
85
|
-
cls:
|
70
|
+
cls: type["_Dict"],
|
86
71
|
data: Optional[dict] = None,
|
87
72
|
client: Optional[_Client] = None,
|
88
73
|
environment_name: Optional[str] = None,
|
@@ -96,7 +81,9 @@ class _Dict(_Object, type_prefix="di"):
|
|
96
81
|
|
97
82
|
with Dict.ephemeral() as d:
|
98
83
|
d["foo"] = "bar"
|
84
|
+
```
|
99
85
|
|
86
|
+
```python notest
|
100
87
|
async with Dict.ephemeral() as d:
|
101
88
|
await d.put.aio("foo", "bar")
|
102
89
|
```
|
@@ -109,36 +96,38 @@ class _Dict(_Object, type_prefix="di"):
|
|
109
96
|
environment_name=_get_environment_name(environment_name),
|
110
97
|
data=serialized,
|
111
98
|
)
|
112
|
-
response = await client.stub.DictGetOrCreate
|
99
|
+
response = await retry_transient_errors(client.stub.DictGetOrCreate, request, total_timeout=10.0)
|
113
100
|
async with TaskContext() as tc:
|
114
101
|
request = api_pb2.DictHeartbeatRequest(dict_id=response.dict_id)
|
115
102
|
tc.infinite_loop(lambda: client.stub.DictHeartbeat(request), sleep=_heartbeat_sleep)
|
116
103
|
yield cls._new_hydrated(response.dict_id, client, None, is_another_app=True)
|
117
104
|
|
118
105
|
@staticmethod
|
106
|
+
@renamed_parameter((2024, 12, 18), "label", "name")
|
119
107
|
def from_name(
|
120
|
-
|
108
|
+
name: str,
|
121
109
|
data: Optional[dict] = None,
|
122
110
|
namespace=api_pb2.DEPLOYMENT_NAMESPACE_WORKSPACE,
|
123
111
|
environment_name: Optional[str] = None,
|
124
112
|
create_if_missing: bool = False,
|
125
113
|
) -> "_Dict":
|
126
|
-
"""
|
114
|
+
"""Reference a named Dict, creating if necessary.
|
127
115
|
|
128
|
-
|
116
|
+
In contrast to `modal.Dict.lookup`, this is a lazy method
|
117
|
+
that defers hydrating the local object with metadata from
|
118
|
+
Modal servers until the first time it is actually used.
|
129
119
|
|
130
120
|
```python
|
131
|
-
|
132
|
-
|
133
|
-
dict = Dict.from_name("my-dict", create_if_missing=True)
|
134
|
-
dict[123] = 456
|
121
|
+
d = modal.Dict.from_name("my-dict", create_if_missing=True)
|
122
|
+
d[123] = 456
|
135
123
|
```
|
136
124
|
"""
|
125
|
+
check_object_name(name, "Dict")
|
137
126
|
|
138
127
|
async def _load(self: _Dict, resolver: Resolver, existing_object_id: Optional[str]):
|
139
128
|
serialized = _serialize_dict(data if data is not None else {})
|
140
129
|
req = api_pb2.DictGetOrCreateRequest(
|
141
|
-
deployment_name=
|
130
|
+
deployment_name=name,
|
142
131
|
namespace=namespace,
|
143
132
|
environment_name=_get_environment_name(environment_name, resolver),
|
144
133
|
object_creation_type=(api_pb2.OBJECT_CREATION_TYPE_CREATE_IF_MISSING if create_if_missing else None),
|
@@ -151,33 +140,27 @@ class _Dict(_Object, type_prefix="di"):
|
|
151
140
|
return _Dict._from_loader(_load, "Dict()", is_another_app=True, hydrate_lazily=True)
|
152
141
|
|
153
142
|
@staticmethod
|
154
|
-
|
155
|
-
label: str, namespace=api_pb2.DEPLOYMENT_NAMESPACE_WORKSPACE, environment_name: Optional[str] = None
|
156
|
-
) -> "_Dict":
|
157
|
-
"""Deprecated! Use `Dict.from_name(name, create_if_missing=True)`."""
|
158
|
-
deprecation_warning((2024, 3, 1), _Dict.persisted.__doc__)
|
159
|
-
return _Dict.from_name(label, namespace, environment_name, create_if_missing=True)
|
160
|
-
|
161
|
-
@staticmethod
|
143
|
+
@renamed_parameter((2024, 12, 18), "label", "name")
|
162
144
|
async def lookup(
|
163
|
-
|
145
|
+
name: str,
|
164
146
|
data: Optional[dict] = None,
|
165
147
|
namespace=api_pb2.DEPLOYMENT_NAMESPACE_WORKSPACE,
|
166
148
|
client: Optional[_Client] = None,
|
167
149
|
environment_name: Optional[str] = None,
|
168
150
|
create_if_missing: bool = False,
|
169
151
|
) -> "_Dict":
|
170
|
-
"""Lookup a
|
152
|
+
"""Lookup a named Dict.
|
171
153
|
|
172
|
-
|
173
|
-
from
|
154
|
+
In contrast to `modal.Dict.from_name`, this is an eager method
|
155
|
+
that will hydrate the local object with metadata from Modal servers.
|
174
156
|
|
175
|
-
|
157
|
+
```python
|
158
|
+
d = modal.Dict.lookup("my-dict")
|
176
159
|
d["xyz"] = 123
|
177
160
|
```
|
178
161
|
"""
|
179
162
|
obj = _Dict.from_name(
|
180
|
-
|
163
|
+
name,
|
181
164
|
data=data,
|
182
165
|
namespace=namespace,
|
183
166
|
environment_name=environment_name,
|
@@ -190,13 +173,14 @@ class _Dict(_Object, type_prefix="di"):
|
|
190
173
|
return obj
|
191
174
|
|
192
175
|
@staticmethod
|
176
|
+
@renamed_parameter((2024, 12, 18), "label", "name")
|
193
177
|
async def delete(
|
194
|
-
|
178
|
+
name: str,
|
195
179
|
*,
|
196
180
|
client: Optional[_Client] = None,
|
197
181
|
environment_name: Optional[str] = None,
|
198
182
|
):
|
199
|
-
obj = await _Dict.lookup(
|
183
|
+
obj = await _Dict.lookup(name, client=client, environment_name=environment_name)
|
200
184
|
req = api_pb2.DictDeleteRequest(dict_id=obj.object_id)
|
201
185
|
await retry_transient_errors(obj._client.stub.DictDelete, req)
|
202
186
|
|
@@ -250,7 +234,13 @@ class _Dict(_Object, type_prefix="di"):
|
|
250
234
|
"""Update the dictionary with additional items."""
|
251
235
|
serialized = _serialize_dict(kwargs)
|
252
236
|
req = api_pb2.DictUpdateRequest(dict_id=self.object_id, updates=serialized)
|
253
|
-
|
237
|
+
try:
|
238
|
+
await retry_transient_errors(self._client.stub.DictUpdate, req)
|
239
|
+
except GRPCError as exc:
|
240
|
+
if "status = '413'" in exc.message:
|
241
|
+
raise RequestSizeError("Dict.update request is too large") from exc
|
242
|
+
else:
|
243
|
+
raise exc
|
254
244
|
|
255
245
|
@live_method
|
256
246
|
async def put(self, key: Any, value: Any) -> None:
|
@@ -258,7 +248,13 @@ class _Dict(_Object, type_prefix="di"):
|
|
258
248
|
updates = {key: value}
|
259
249
|
serialized = _serialize_dict(updates)
|
260
250
|
req = api_pb2.DictUpdateRequest(dict_id=self.object_id, updates=serialized)
|
261
|
-
|
251
|
+
try:
|
252
|
+
await retry_transient_errors(self._client.stub.DictUpdate, req)
|
253
|
+
except GRPCError as exc:
|
254
|
+
if "status = '413'" in exc.message:
|
255
|
+
raise RequestSizeError("Dict.put request is too large") from exc
|
256
|
+
else:
|
257
|
+
raise exc
|
262
258
|
|
263
259
|
@live_method
|
264
260
|
async def __setitem__(self, key: Any, value: Any) -> None:
|
@@ -301,7 +297,7 @@ class _Dict(_Object, type_prefix="di"):
|
|
301
297
|
and results are unordered.
|
302
298
|
"""
|
303
299
|
req = api_pb2.DictContentsRequest(dict_id=self.object_id, keys=True)
|
304
|
-
async for resp in
|
300
|
+
async for resp in self._client.stub.DictContents.unary_stream(req):
|
305
301
|
yield deserialize(resp.key, self._client)
|
306
302
|
|
307
303
|
@live_method_gen
|
@@ -312,18 +308,18 @@ class _Dict(_Object, type_prefix="di"):
|
|
312
308
|
and results are unordered.
|
313
309
|
"""
|
314
310
|
req = api_pb2.DictContentsRequest(dict_id=self.object_id, values=True)
|
315
|
-
async for resp in
|
311
|
+
async for resp in self._client.stub.DictContents.unary_stream(req):
|
316
312
|
yield deserialize(resp.value, self._client)
|
317
313
|
|
318
314
|
@live_method_gen
|
319
|
-
async def items(self) -> AsyncIterator[
|
315
|
+
async def items(self) -> AsyncIterator[tuple[Any, Any]]:
|
320
316
|
"""Return an iterator over the (key, value) tuples in this dictionary.
|
321
317
|
|
322
318
|
Note that (unlike with Python dicts) the return value is a simple iterator,
|
323
319
|
and results are unordered.
|
324
320
|
"""
|
325
321
|
req = api_pb2.DictContentsRequest(dict_id=self.object_id, keys=True, values=True)
|
326
|
-
async for resp in
|
322
|
+
async for resp in self._client.stub.DictContents.unary_stream(req):
|
327
323
|
yield (deserialize(resp.key, self._client), deserialize(resp.value, self._client))
|
328
324
|
|
329
325
|
|
modal/dict.pyi
CHANGED
@@ -1,244 +1,200 @@
|
|
1
|
+
import collections.abc
|
1
2
|
import modal.client
|
2
3
|
import modal.object
|
3
4
|
import synchronicity.combined_types
|
4
5
|
import typing
|
5
6
|
import typing_extensions
|
6
7
|
|
7
|
-
def _serialize_dict(data):
|
8
|
-
...
|
9
|
-
|
8
|
+
def _serialize_dict(data): ...
|
10
9
|
|
11
10
|
class _Dict(modal.object._Object):
|
12
|
-
|
13
|
-
def new(data: typing.Union[dict, None] = None) -> _Dict:
|
14
|
-
...
|
15
|
-
|
16
|
-
def __init__(self, data={}):
|
17
|
-
...
|
18
|
-
|
11
|
+
def __init__(self, data={}): ...
|
19
12
|
@classmethod
|
20
|
-
def ephemeral(
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
13
|
+
def ephemeral(
|
14
|
+
cls: type[_Dict],
|
15
|
+
data: typing.Optional[dict] = None,
|
16
|
+
client: typing.Optional[modal.client._Client] = None,
|
17
|
+
environment_name: typing.Optional[str] = None,
|
18
|
+
_heartbeat_sleep: float = 300,
|
19
|
+
) -> typing.AsyncContextManager[_Dict]: ...
|
27
20
|
@staticmethod
|
28
|
-
def
|
29
|
-
|
30
|
-
|
21
|
+
def from_name(
|
22
|
+
name: str,
|
23
|
+
data: typing.Optional[dict] = None,
|
24
|
+
namespace=1,
|
25
|
+
environment_name: typing.Optional[str] = None,
|
26
|
+
create_if_missing: bool = False,
|
27
|
+
) -> _Dict: ...
|
31
28
|
@staticmethod
|
32
|
-
async def lookup(
|
33
|
-
|
34
|
-
|
29
|
+
async def lookup(
|
30
|
+
name: str,
|
31
|
+
data: typing.Optional[dict] = None,
|
32
|
+
namespace=1,
|
33
|
+
client: typing.Optional[modal.client._Client] = None,
|
34
|
+
environment_name: typing.Optional[str] = None,
|
35
|
+
create_if_missing: bool = False,
|
36
|
+
) -> _Dict: ...
|
35
37
|
@staticmethod
|
36
|
-
async def delete(
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
async def
|
43
|
-
|
44
|
-
|
45
|
-
async def
|
46
|
-
|
47
|
-
|
48
|
-
async def
|
49
|
-
|
50
|
-
|
51
|
-
async def
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
async def put(self, key: typing.Any, value: typing.Any) -> None:
|
58
|
-
...
|
59
|
-
|
60
|
-
async def __setitem__(self, key: typing.Any, value: typing.Any) -> None:
|
61
|
-
...
|
62
|
-
|
63
|
-
async def pop(self, key: typing.Any) -> typing.Any:
|
64
|
-
...
|
65
|
-
|
66
|
-
async def __delitem__(self, key: typing.Any) -> typing.Any:
|
67
|
-
...
|
68
|
-
|
69
|
-
async def __contains__(self, key: typing.Any) -> bool:
|
70
|
-
...
|
71
|
-
|
72
|
-
def keys(self) -> typing.AsyncIterator[typing.Any]:
|
73
|
-
...
|
74
|
-
|
75
|
-
def values(self) -> typing.AsyncIterator[typing.Any]:
|
76
|
-
...
|
77
|
-
|
78
|
-
def items(self) -> typing.AsyncIterator[typing.Tuple[typing.Any, typing.Any]]:
|
79
|
-
...
|
80
|
-
|
38
|
+
async def delete(
|
39
|
+
name: str,
|
40
|
+
*,
|
41
|
+
client: typing.Optional[modal.client._Client] = None,
|
42
|
+
environment_name: typing.Optional[str] = None,
|
43
|
+
): ...
|
44
|
+
async def clear(self) -> None: ...
|
45
|
+
async def get(self, key: typing.Any, default: typing.Optional[typing.Any] = None) -> typing.Any: ...
|
46
|
+
async def contains(self, key: typing.Any) -> bool: ...
|
47
|
+
async def len(self) -> int: ...
|
48
|
+
async def __getitem__(self, key: typing.Any) -> typing.Any: ...
|
49
|
+
async def update(self, **kwargs) -> None: ...
|
50
|
+
async def put(self, key: typing.Any, value: typing.Any) -> None: ...
|
51
|
+
async def __setitem__(self, key: typing.Any, value: typing.Any) -> None: ...
|
52
|
+
async def pop(self, key: typing.Any) -> typing.Any: ...
|
53
|
+
async def __delitem__(self, key: typing.Any) -> typing.Any: ...
|
54
|
+
async def __contains__(self, key: typing.Any) -> bool: ...
|
55
|
+
def keys(self) -> collections.abc.AsyncIterator[typing.Any]: ...
|
56
|
+
def values(self) -> collections.abc.AsyncIterator[typing.Any]: ...
|
57
|
+
def items(self) -> collections.abc.AsyncIterator[tuple[typing.Any, typing.Any]]: ...
|
81
58
|
|
82
59
|
class Dict(modal.object.Object):
|
83
|
-
def __init__(self, data={}):
|
84
|
-
...
|
85
|
-
|
86
|
-
@staticmethod
|
87
|
-
def new(data: typing.Union[dict, None] = None) -> Dict:
|
88
|
-
...
|
89
|
-
|
60
|
+
def __init__(self, data={}): ...
|
90
61
|
@classmethod
|
91
|
-
def ephemeral(
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
62
|
+
def ephemeral(
|
63
|
+
cls: type[Dict],
|
64
|
+
data: typing.Optional[dict] = None,
|
65
|
+
client: typing.Optional[modal.client.Client] = None,
|
66
|
+
environment_name: typing.Optional[str] = None,
|
67
|
+
_heartbeat_sleep: float = 300,
|
68
|
+
) -> synchronicity.combined_types.AsyncAndBlockingContextManager[Dict]: ...
|
98
69
|
@staticmethod
|
99
|
-
def
|
100
|
-
|
70
|
+
def from_name(
|
71
|
+
name: str,
|
72
|
+
data: typing.Optional[dict] = None,
|
73
|
+
namespace=1,
|
74
|
+
environment_name: typing.Optional[str] = None,
|
75
|
+
create_if_missing: bool = False,
|
76
|
+
) -> Dict: ...
|
101
77
|
|
102
78
|
class __lookup_spec(typing_extensions.Protocol):
|
103
|
-
def __call__(
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
79
|
+
def __call__(
|
80
|
+
self,
|
81
|
+
name: str,
|
82
|
+
data: typing.Optional[dict] = None,
|
83
|
+
namespace=1,
|
84
|
+
client: typing.Optional[modal.client.Client] = None,
|
85
|
+
environment_name: typing.Optional[str] = None,
|
86
|
+
create_if_missing: bool = False,
|
87
|
+
) -> Dict: ...
|
88
|
+
async def aio(
|
89
|
+
self,
|
90
|
+
name: str,
|
91
|
+
data: typing.Optional[dict] = None,
|
92
|
+
namespace=1,
|
93
|
+
client: typing.Optional[modal.client.Client] = None,
|
94
|
+
environment_name: typing.Optional[str] = None,
|
95
|
+
create_if_missing: bool = False,
|
96
|
+
) -> Dict: ...
|
108
97
|
|
109
98
|
lookup: __lookup_spec
|
110
99
|
|
111
100
|
class __delete_spec(typing_extensions.Protocol):
|
112
|
-
def __call__(
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
101
|
+
def __call__(
|
102
|
+
self,
|
103
|
+
name: str,
|
104
|
+
*,
|
105
|
+
client: typing.Optional[modal.client.Client] = None,
|
106
|
+
environment_name: typing.Optional[str] = None,
|
107
|
+
): ...
|
108
|
+
async def aio(
|
109
|
+
self,
|
110
|
+
name: str,
|
111
|
+
*,
|
112
|
+
client: typing.Optional[modal.client.Client] = None,
|
113
|
+
environment_name: typing.Optional[str] = None,
|
114
|
+
): ...
|
117
115
|
|
118
116
|
delete: __delete_spec
|
119
117
|
|
120
118
|
class __clear_spec(typing_extensions.Protocol):
|
121
|
-
def __call__(self) -> None:
|
122
|
-
|
123
|
-
|
124
|
-
async def aio(self, *args, **kwargs) -> None:
|
125
|
-
...
|
119
|
+
def __call__(self) -> None: ...
|
120
|
+
async def aio(self) -> None: ...
|
126
121
|
|
127
122
|
clear: __clear_spec
|
128
123
|
|
129
124
|
class __get_spec(typing_extensions.Protocol):
|
130
|
-
def __call__(self, key: typing.Any, default: typing.
|
131
|
-
|
132
|
-
|
133
|
-
async def aio(self, *args, **kwargs) -> typing.Any:
|
134
|
-
...
|
125
|
+
def __call__(self, key: typing.Any, default: typing.Optional[typing.Any] = None) -> typing.Any: ...
|
126
|
+
async def aio(self, key: typing.Any, default: typing.Optional[typing.Any] = None) -> typing.Any: ...
|
135
127
|
|
136
128
|
get: __get_spec
|
137
129
|
|
138
130
|
class __contains_spec(typing_extensions.Protocol):
|
139
|
-
def __call__(self, key: typing.Any) -> bool:
|
140
|
-
|
141
|
-
|
142
|
-
async def aio(self, *args, **kwargs) -> bool:
|
143
|
-
...
|
131
|
+
def __call__(self, key: typing.Any) -> bool: ...
|
132
|
+
async def aio(self, key: typing.Any) -> bool: ...
|
144
133
|
|
145
134
|
contains: __contains_spec
|
146
135
|
|
147
136
|
class __len_spec(typing_extensions.Protocol):
|
148
|
-
def __call__(self) -> int:
|
149
|
-
|
150
|
-
|
151
|
-
async def aio(self, *args, **kwargs) -> int:
|
152
|
-
...
|
137
|
+
def __call__(self) -> int: ...
|
138
|
+
async def aio(self) -> int: ...
|
153
139
|
|
154
140
|
len: __len_spec
|
155
141
|
|
156
142
|
class ____getitem___spec(typing_extensions.Protocol):
|
157
|
-
def __call__(self, key: typing.Any) -> typing.Any:
|
158
|
-
|
159
|
-
|
160
|
-
async def aio(self, *args, **kwargs) -> typing.Any:
|
161
|
-
...
|
143
|
+
def __call__(self, key: typing.Any) -> typing.Any: ...
|
144
|
+
async def aio(self, key: typing.Any) -> typing.Any: ...
|
162
145
|
|
163
146
|
__getitem__: ____getitem___spec
|
164
147
|
|
165
148
|
class __update_spec(typing_extensions.Protocol):
|
166
|
-
def __call__(self, **kwargs) -> None:
|
167
|
-
|
168
|
-
|
169
|
-
async def aio(self, *args, **kwargs) -> None:
|
170
|
-
...
|
149
|
+
def __call__(self, **kwargs) -> None: ...
|
150
|
+
async def aio(self, **kwargs) -> None: ...
|
171
151
|
|
172
152
|
update: __update_spec
|
173
153
|
|
174
154
|
class __put_spec(typing_extensions.Protocol):
|
175
|
-
def __call__(self, key: typing.Any, value: typing.Any) -> None:
|
176
|
-
|
177
|
-
|
178
|
-
async def aio(self, *args, **kwargs) -> None:
|
179
|
-
...
|
155
|
+
def __call__(self, key: typing.Any, value: typing.Any) -> None: ...
|
156
|
+
async def aio(self, key: typing.Any, value: typing.Any) -> None: ...
|
180
157
|
|
181
158
|
put: __put_spec
|
182
159
|
|
183
160
|
class ____setitem___spec(typing_extensions.Protocol):
|
184
|
-
def __call__(self, key: typing.Any, value: typing.Any) -> None:
|
185
|
-
|
186
|
-
|
187
|
-
async def aio(self, *args, **kwargs) -> None:
|
188
|
-
...
|
161
|
+
def __call__(self, key: typing.Any, value: typing.Any) -> None: ...
|
162
|
+
async def aio(self, key: typing.Any, value: typing.Any) -> None: ...
|
189
163
|
|
190
164
|
__setitem__: ____setitem___spec
|
191
165
|
|
192
166
|
class __pop_spec(typing_extensions.Protocol):
|
193
|
-
def __call__(self, key: typing.Any) -> typing.Any:
|
194
|
-
|
195
|
-
|
196
|
-
async def aio(self, *args, **kwargs) -> typing.Any:
|
197
|
-
...
|
167
|
+
def __call__(self, key: typing.Any) -> typing.Any: ...
|
168
|
+
async def aio(self, key: typing.Any) -> typing.Any: ...
|
198
169
|
|
199
170
|
pop: __pop_spec
|
200
171
|
|
201
172
|
class ____delitem___spec(typing_extensions.Protocol):
|
202
|
-
def __call__(self, key: typing.Any) -> typing.Any:
|
203
|
-
|
204
|
-
|
205
|
-
async def aio(self, *args, **kwargs) -> typing.Any:
|
206
|
-
...
|
173
|
+
def __call__(self, key: typing.Any) -> typing.Any: ...
|
174
|
+
async def aio(self, key: typing.Any) -> typing.Any: ...
|
207
175
|
|
208
176
|
__delitem__: ____delitem___spec
|
209
177
|
|
210
178
|
class ____contains___spec(typing_extensions.Protocol):
|
211
|
-
def __call__(self, key: typing.Any) -> bool:
|
212
|
-
|
213
|
-
|
214
|
-
async def aio(self, *args, **kwargs) -> bool:
|
215
|
-
...
|
179
|
+
def __call__(self, key: typing.Any) -> bool: ...
|
180
|
+
async def aio(self, key: typing.Any) -> bool: ...
|
216
181
|
|
217
182
|
__contains__: ____contains___spec
|
218
183
|
|
219
184
|
class __keys_spec(typing_extensions.Protocol):
|
220
|
-
def __call__(self) -> typing.Iterator[typing.Any]:
|
221
|
-
|
222
|
-
|
223
|
-
def aio(self) -> typing.AsyncIterator[typing.Any]:
|
224
|
-
...
|
185
|
+
def __call__(self) -> typing.Iterator[typing.Any]: ...
|
186
|
+
def aio(self) -> collections.abc.AsyncIterator[typing.Any]: ...
|
225
187
|
|
226
188
|
keys: __keys_spec
|
227
189
|
|
228
190
|
class __values_spec(typing_extensions.Protocol):
|
229
|
-
def __call__(self) -> typing.Iterator[typing.Any]:
|
230
|
-
|
231
|
-
|
232
|
-
def aio(self) -> typing.AsyncIterator[typing.Any]:
|
233
|
-
...
|
191
|
+
def __call__(self) -> typing.Iterator[typing.Any]: ...
|
192
|
+
def aio(self) -> collections.abc.AsyncIterator[typing.Any]: ...
|
234
193
|
|
235
194
|
values: __values_spec
|
236
195
|
|
237
196
|
class __items_spec(typing_extensions.Protocol):
|
238
|
-
def __call__(self) -> typing.Iterator[
|
239
|
-
|
240
|
-
|
241
|
-
def aio(self) -> typing.AsyncIterator[typing.Tuple[typing.Any, typing.Any]]:
|
242
|
-
...
|
197
|
+
def __call__(self) -> typing.Iterator[tuple[typing.Any, typing.Any]]: ...
|
198
|
+
def aio(self) -> collections.abc.AsyncIterator[tuple[typing.Any, typing.Any]]: ...
|
243
199
|
|
244
200
|
items: __items_spec
|