modal 0.67.0__py3-none-any.whl → 0.67.22__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.py +2 -2
- modal/_clustered_functions.pyi +2 -2
- modal/_container_entrypoint.py +5 -4
- modal/_output.py +29 -28
- modal/_pty.py +2 -2
- modal/_resolver.py +6 -5
- modal/_resources.py +3 -3
- modal/_runtime/asgi.py +46 -6
- modal/_runtime/container_io_manager.py +22 -26
- modal/_runtime/execution_context.py +2 -2
- modal/_runtime/telemetry.py +1 -2
- modal/_runtime/user_code_imports.py +12 -14
- modal/_serialization.py +3 -7
- modal/_traceback.py +5 -5
- modal/_tunnel.py +5 -4
- modal/_tunnel.pyi +2 -2
- modal/_utils/async_utils.py +53 -17
- modal/_utils/blob_utils.py +22 -7
- modal/_utils/function_utils.py +14 -10
- modal/_utils/grpc_testing.py +7 -6
- modal/_utils/grpc_utils.py +2 -3
- modal/_utils/hash_utils.py +2 -2
- modal/_utils/mount_utils.py +5 -4
- modal/_utils/package_utils.py +2 -3
- modal/_utils/pattern_matcher.py +6 -6
- modal/_utils/rand_pb_testing.py +3 -3
- modal/_utils/shell_utils.py +2 -1
- modal/_vendor/a2wsgi_wsgi.py +62 -72
- modal/_vendor/cloudpickle.py +1 -1
- modal/_watcher.py +8 -7
- modal/app.py +81 -69
- modal/app.pyi +104 -99
- modal/call_graph.py +6 -6
- modal/cli/_download.py +3 -2
- modal/cli/_traceback.py +4 -4
- modal/cli/app.py +4 -4
- modal/cli/container.py +4 -4
- modal/cli/dict.py +1 -1
- modal/cli/environment.py +2 -3
- modal/cli/import_refs.py +1 -1
- modal/cli/launch.py +2 -2
- modal/cli/network_file_system.py +1 -1
- modal/cli/profile.py +1 -1
- modal/cli/programs/run_jupyter.py +2 -2
- modal/cli/programs/vscode.py +3 -3
- modal/cli/queues.py +1 -1
- modal/cli/run.py +6 -6
- modal/cli/secret.py +3 -3
- modal/cli/utils.py +2 -1
- modal/cli/volume.py +3 -3
- modal/client.py +6 -11
- modal/client.pyi +18 -27
- modal/cloud_bucket_mount.py +3 -3
- modal/cloud_bucket_mount.pyi +2 -2
- modal/cls.py +32 -32
- modal/cls.pyi +35 -34
- modal/config.py +3 -2
- modal/container_process.py +6 -2
- modal/dict.py +6 -3
- modal/dict.pyi +10 -9
- modal/environments.py +3 -3
- modal/environments.pyi +3 -3
- modal/exception.py +2 -3
- modal/functions.py +111 -40
- modal/functions.pyi +71 -48
- modal/image.py +46 -49
- modal/image.pyi +102 -101
- modal/io_streams.py +20 -12
- modal/io_streams.pyi +24 -14
- modal/mount.py +24 -24
- modal/mount.pyi +28 -29
- modal/network_file_system.py +14 -11
- modal/network_file_system.pyi +12 -11
- modal/object.py +9 -8
- modal/object.pyi +47 -34
- modal/output.py +2 -1
- modal/parallel_map.py +4 -4
- modal/partial_function.py +10 -14
- modal/partial_function.pyi +17 -18
- modal/queue.py +11 -8
- modal/queue.pyi +23 -22
- modal/retries.py +38 -0
- modal/runner.py +8 -7
- modal/runner.pyi +8 -14
- modal/running_app.py +3 -3
- modal/sandbox.py +20 -13
- modal/sandbox.pyi +73 -72
- modal/scheduler_placement.py +2 -1
- modal/secret.py +7 -7
- modal/secret.pyi +12 -12
- modal/serving.py +4 -3
- modal/serving.pyi +5 -4
- modal/token_flow.py +3 -2
- modal/token_flow.pyi +3 -3
- modal/volume.py +16 -23
- modal/volume.pyi +17 -16
- {modal-0.67.0.dist-info → modal-0.67.22.dist-info}/METADATA +2 -2
- modal-0.67.22.dist-info/RECORD +168 -0
- modal_docs/mdmd/signatures.py +1 -2
- modal_global_objects/mounts/python_standalone.py +1 -1
- modal_proto/api.proto +13 -0
- modal_proto/api_grpc.py +16 -0
- modal_proto/api_pb2.py +241 -221
- modal_proto/api_pb2.pyi +41 -0
- modal_proto/api_pb2_grpc.py +33 -0
- modal_proto/api_pb2_grpc.pyi +10 -0
- modal_proto/modal_api_grpc.py +1 -0
- modal_version/_version_generated.py +1 -1
- modal-0.67.0.dist-info/RECORD +0 -168
- {modal-0.67.0.dist-info → modal-0.67.22.dist-info}/LICENSE +0 -0
- {modal-0.67.0.dist-info → modal-0.67.22.dist-info}/WHEEL +0 -0
- {modal-0.67.0.dist-info → modal-0.67.22.dist-info}/entry_points.txt +0 -0
- {modal-0.67.0.dist-info → modal-0.67.22.dist-info}/top_level.txt +0 -0
modal/object.pyi
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
import collections.abc
|
1
2
|
import google.protobuf.message
|
2
3
|
import modal._resolver
|
3
4
|
import modal.client
|
@@ -14,16 +15,18 @@ def _get_environment_name(
|
|
14
15
|
|
15
16
|
class _Object:
|
16
17
|
_type_prefix: typing.ClassVar[typing.Optional[str]]
|
17
|
-
_prefix_to_type: typing.ClassVar[
|
18
|
-
_load: typing.Optional[
|
18
|
+
_prefix_to_type: typing.ClassVar[dict[str, type]]
|
19
|
+
_load: typing.Optional[
|
20
|
+
typing.Callable[[O, modal._resolver.Resolver, typing.Optional[str]], collections.abc.Awaitable[None]]
|
21
|
+
]
|
19
22
|
_preload: typing.Optional[
|
20
|
-
typing.Callable[[O, modal._resolver.Resolver, typing.Optional[str]],
|
23
|
+
typing.Callable[[O, modal._resolver.Resolver, typing.Optional[str]], collections.abc.Awaitable[None]]
|
21
24
|
]
|
22
25
|
_rep: str
|
23
26
|
_is_another_app: bool
|
24
27
|
_hydrate_lazily: bool
|
25
|
-
_deps: typing.Optional[typing.Callable[...,
|
26
|
-
_deduplication_key: typing.Optional[typing.Callable[[],
|
28
|
+
_deps: typing.Optional[typing.Callable[..., list[_Object]]]
|
29
|
+
_deduplication_key: typing.Optional[typing.Callable[[], collections.abc.Awaitable[collections.abc.Hashable]]]
|
27
30
|
_object_id: str
|
28
31
|
_client: modal.client._Client
|
29
32
|
_is_hydrated: bool
|
@@ -36,15 +39,17 @@ class _Object:
|
|
36
39
|
self,
|
37
40
|
rep: str,
|
38
41
|
load: typing.Optional[
|
39
|
-
typing.Callable[[O, modal._resolver.Resolver, typing.Optional[str]],
|
42
|
+
typing.Callable[[O, modal._resolver.Resolver, typing.Optional[str]], collections.abc.Awaitable[None]]
|
40
43
|
] = None,
|
41
44
|
is_another_app: bool = False,
|
42
45
|
preload: typing.Optional[
|
43
|
-
typing.Callable[[O, modal._resolver.Resolver, typing.Optional[str]],
|
46
|
+
typing.Callable[[O, modal._resolver.Resolver, typing.Optional[str]], collections.abc.Awaitable[None]]
|
44
47
|
] = None,
|
45
48
|
hydrate_lazily: bool = False,
|
46
|
-
deps: typing.Optional[typing.Callable[...,
|
47
|
-
deduplication_key: typing.Optional[
|
49
|
+
deps: typing.Optional[typing.Callable[..., list[_Object]]] = None,
|
50
|
+
deduplication_key: typing.Optional[
|
51
|
+
typing.Callable[[], collections.abc.Awaitable[collections.abc.Hashable]]
|
52
|
+
] = None,
|
48
53
|
): ...
|
49
54
|
def _unhydrate(self): ...
|
50
55
|
def _initialize_from_empty(self): ...
|
@@ -59,23 +64,25 @@ class _Object:
|
|
59
64
|
@classmethod
|
60
65
|
def _from_loader(
|
61
66
|
cls,
|
62
|
-
load: typing.Callable[[O, modal._resolver.Resolver, typing.Optional[str]],
|
67
|
+
load: typing.Callable[[O, modal._resolver.Resolver, typing.Optional[str]], collections.abc.Awaitable[None]],
|
63
68
|
rep: str,
|
64
69
|
is_another_app: bool = False,
|
65
70
|
preload: typing.Optional[
|
66
|
-
typing.Callable[[O, modal._resolver.Resolver, typing.Optional[str]],
|
71
|
+
typing.Callable[[O, modal._resolver.Resolver, typing.Optional[str]], collections.abc.Awaitable[None]]
|
67
72
|
] = None,
|
68
73
|
hydrate_lazily: bool = False,
|
69
|
-
deps: typing.Optional[typing.Callable[...,
|
70
|
-
deduplication_key: typing.Optional[
|
74
|
+
deps: typing.Optional[typing.Callable[..., collections.abc.Sequence[_Object]]] = None,
|
75
|
+
deduplication_key: typing.Optional[
|
76
|
+
typing.Callable[[], collections.abc.Awaitable[collections.abc.Hashable]]
|
77
|
+
] = None,
|
71
78
|
): ...
|
72
79
|
@classmethod
|
73
|
-
def _get_type_from_id(cls:
|
80
|
+
def _get_type_from_id(cls: type[O], object_id: str) -> type[O]: ...
|
74
81
|
@classmethod
|
75
|
-
def _is_id_type(cls:
|
82
|
+
def _is_id_type(cls: type[O], object_id) -> bool: ...
|
76
83
|
@classmethod
|
77
84
|
def _new_hydrated(
|
78
|
-
cls:
|
85
|
+
cls: type[O],
|
79
86
|
object_id: str,
|
80
87
|
client: modal.client._Client,
|
81
88
|
handle_metadata: typing.Optional[google.protobuf.message.Message],
|
@@ -90,23 +97,23 @@ class _Object:
|
|
90
97
|
@property
|
91
98
|
def is_hydrated(self) -> bool: ...
|
92
99
|
@property
|
93
|
-
def deps(self) -> typing.Callable[...,
|
100
|
+
def deps(self) -> typing.Callable[..., list[_Object]]: ...
|
94
101
|
async def resolve(self, client: typing.Optional[modal.client._Client] = None): ...
|
95
102
|
|
96
103
|
class Object:
|
97
104
|
_type_prefix: typing.ClassVar[typing.Optional[str]]
|
98
|
-
_prefix_to_type: typing.ClassVar[
|
105
|
+
_prefix_to_type: typing.ClassVar[dict[str, type]]
|
99
106
|
_load: typing.Optional[
|
100
|
-
typing.Callable[[_BLOCKING_O, modal._resolver.Resolver, typing.Optional[str]],
|
107
|
+
typing.Callable[[_BLOCKING_O, modal._resolver.Resolver, typing.Optional[str]], collections.abc.Awaitable[None]]
|
101
108
|
]
|
102
109
|
_preload: typing.Optional[
|
103
|
-
typing.Callable[[_BLOCKING_O, modal._resolver.Resolver, typing.Optional[str]],
|
110
|
+
typing.Callable[[_BLOCKING_O, modal._resolver.Resolver, typing.Optional[str]], collections.abc.Awaitable[None]]
|
104
111
|
]
|
105
112
|
_rep: str
|
106
113
|
_is_another_app: bool
|
107
114
|
_hydrate_lazily: bool
|
108
|
-
_deps: typing.Optional[typing.Callable[...,
|
109
|
-
_deduplication_key: typing.Optional[typing.Callable[[],
|
115
|
+
_deps: typing.Optional[typing.Callable[..., list[Object]]]
|
116
|
+
_deduplication_key: typing.Optional[typing.Callable[[], collections.abc.Awaitable[collections.abc.Hashable]]]
|
110
117
|
_object_id: str
|
111
118
|
_client: modal.client.Client
|
112
119
|
_is_hydrated: bool
|
@@ -128,22 +135,28 @@ class Object:
|
|
128
135
|
typing.Callable[[_BLOCKING_O, modal._resolver.Resolver, typing.Optional[str]], None]
|
129
136
|
] = None,
|
130
137
|
hydrate_lazily: bool = False,
|
131
|
-
deps: typing.Optional[typing.Callable[...,
|
132
|
-
deduplication_key: typing.Optional[typing.Callable[[],
|
138
|
+
deps: typing.Optional[typing.Callable[..., list[Object]]] = None,
|
139
|
+
deduplication_key: typing.Optional[typing.Callable[[], collections.abc.Hashable]] = None,
|
133
140
|
): ...
|
134
141
|
def aio(
|
135
142
|
self,
|
136
143
|
rep: str,
|
137
144
|
load: typing.Optional[
|
138
|
-
typing.Callable[
|
145
|
+
typing.Callable[
|
146
|
+
[_BLOCKING_O, modal._resolver.Resolver, typing.Optional[str]], collections.abc.Awaitable[None]
|
147
|
+
]
|
139
148
|
] = None,
|
140
149
|
is_another_app: bool = False,
|
141
150
|
preload: typing.Optional[
|
142
|
-
typing.Callable[
|
151
|
+
typing.Callable[
|
152
|
+
[_BLOCKING_O, modal._resolver.Resolver, typing.Optional[str]], collections.abc.Awaitable[None]
|
153
|
+
]
|
143
154
|
] = None,
|
144
155
|
hydrate_lazily: bool = False,
|
145
|
-
deps: typing.Optional[typing.Callable[...,
|
146
|
-
deduplication_key: typing.Optional[
|
156
|
+
deps: typing.Optional[typing.Callable[..., list[Object]]] = None,
|
157
|
+
deduplication_key: typing.Optional[
|
158
|
+
typing.Callable[[], collections.abc.Awaitable[collections.abc.Hashable]]
|
159
|
+
] = None,
|
147
160
|
): ...
|
148
161
|
|
149
162
|
_init: ___init_spec
|
@@ -168,16 +181,16 @@ class Object:
|
|
168
181
|
typing.Callable[[_BLOCKING_O, modal._resolver.Resolver, typing.Optional[str]], None]
|
169
182
|
] = None,
|
170
183
|
hydrate_lazily: bool = False,
|
171
|
-
deps: typing.Optional[typing.Callable[...,
|
172
|
-
deduplication_key: typing.Optional[typing.Callable[[],
|
184
|
+
deps: typing.Optional[typing.Callable[..., collections.abc.Sequence[Object]]] = None,
|
185
|
+
deduplication_key: typing.Optional[typing.Callable[[], collections.abc.Hashable]] = None,
|
173
186
|
): ...
|
174
187
|
@classmethod
|
175
|
-
def _get_type_from_id(cls:
|
188
|
+
def _get_type_from_id(cls: type[_BLOCKING_O], object_id: str) -> type[_BLOCKING_O]: ...
|
176
189
|
@classmethod
|
177
|
-
def _is_id_type(cls:
|
190
|
+
def _is_id_type(cls: type[_BLOCKING_O], object_id) -> bool: ...
|
178
191
|
@classmethod
|
179
192
|
def _new_hydrated(
|
180
|
-
cls:
|
193
|
+
cls: type[_BLOCKING_O],
|
181
194
|
object_id: str,
|
182
195
|
client: modal.client.Client,
|
183
196
|
handle_metadata: typing.Optional[google.protobuf.message.Message],
|
@@ -192,7 +205,7 @@ class Object:
|
|
192
205
|
@property
|
193
206
|
def is_hydrated(self) -> bool: ...
|
194
207
|
@property
|
195
|
-
def deps(self) -> typing.Callable[...,
|
208
|
+
def deps(self) -> typing.Callable[..., list[Object]]: ...
|
196
209
|
|
197
210
|
class __resolve_spec(typing_extensions.Protocol):
|
198
211
|
def __call__(self, client: typing.Optional[modal.client.Client] = None): ...
|
modal/output.py
CHANGED
@@ -7,7 +7,8 @@ us to avoid importing Rich for client code that runs in the container environmen
|
|
7
7
|
|
8
8
|
"""
|
9
9
|
import contextlib
|
10
|
-
from
|
10
|
+
from collections.abc import Generator
|
11
|
+
from typing import TYPE_CHECKING, Optional
|
11
12
|
|
12
13
|
if TYPE_CHECKING:
|
13
14
|
from ._output import OutputManager
|
modal/parallel_map.py
CHANGED
@@ -3,7 +3,7 @@ import asyncio
|
|
3
3
|
import time
|
4
4
|
import typing
|
5
5
|
from dataclasses import dataclass
|
6
|
-
from typing import Any, Callable,
|
6
|
+
from typing import Any, Callable, Optional
|
7
7
|
|
8
8
|
from grpclib import GRPCError, Status
|
9
9
|
|
@@ -95,8 +95,8 @@ async def _map_invocation(
|
|
95
95
|
if count_update_callback is not None:
|
96
96
|
count_update_callback(num_outputs, num_inputs)
|
97
97
|
|
98
|
-
pending_outputs:
|
99
|
-
completed_outputs:
|
98
|
+
pending_outputs: dict[str, int] = {} # Map input_id -> next expected gen_index value
|
99
|
+
completed_outputs: set[str] = set() # Set of input_ids whose outputs are complete (expecting no more values)
|
100
100
|
|
101
101
|
input_queue: asyncio.Queue = asyncio.Queue()
|
102
102
|
|
@@ -216,7 +216,7 @@ async def _map_invocation(
|
|
216
216
|
)
|
217
217
|
await retry_transient_errors(client.stub.FunctionGetOutputs, request)
|
218
218
|
|
219
|
-
async def fetch_output(item: api_pb2.FunctionGetOutputsItem) ->
|
219
|
+
async def fetch_output(item: api_pb2.FunctionGetOutputsItem) -> tuple[int, Any]:
|
220
220
|
try:
|
221
221
|
output = await _process_result(item.result, item.data_format, client.stub, client)
|
222
222
|
except Exception as e:
|
modal/partial_function.py
CHANGED
@@ -2,15 +2,11 @@
|
|
2
2
|
import enum
|
3
3
|
import inspect
|
4
4
|
import typing
|
5
|
+
from collections.abc import Coroutine, Iterable
|
5
6
|
from typing import (
|
6
7
|
Any,
|
7
8
|
Callable,
|
8
|
-
Coroutine,
|
9
|
-
Dict,
|
10
|
-
Iterable,
|
11
|
-
List,
|
12
9
|
Optional,
|
13
|
-
Type,
|
14
10
|
Union,
|
15
11
|
)
|
16
12
|
|
@@ -132,11 +128,11 @@ class _PartialFunction(typing.Generic[P, ReturnType, OriginalReturnType]):
|
|
132
128
|
PartialFunction = synchronize_api(_PartialFunction)
|
133
129
|
|
134
130
|
|
135
|
-
def _find_partial_methods_for_user_cls(user_cls:
|
131
|
+
def _find_partial_methods_for_user_cls(user_cls: type[Any], flags: int) -> dict[str, _PartialFunction]:
|
136
132
|
"""Grabs all method on a user class, and returns partials. Includes legacy methods."""
|
137
133
|
|
138
134
|
# Build up a list of legacy attributes to check
|
139
|
-
check_attrs:
|
135
|
+
check_attrs: list[str] = []
|
140
136
|
if flags & _PartialFunctionFlags.BUILD:
|
141
137
|
check_attrs += ["__build__", "__abuild__"]
|
142
138
|
if flags & _PartialFunctionFlags.ENTER_POST_SNAPSHOT:
|
@@ -158,8 +154,8 @@ def _find_partial_methods_for_user_cls(user_cls: Type[Any], flags: int) -> Dict[
|
|
158
154
|
)
|
159
155
|
deprecation_error((2024, 2, 21), message)
|
160
156
|
|
161
|
-
partial_functions:
|
162
|
-
for parent_cls in user_cls.mro():
|
157
|
+
partial_functions: dict[str, PartialFunction] = {}
|
158
|
+
for parent_cls in reversed(user_cls.mro()):
|
163
159
|
if parent_cls is not object:
|
164
160
|
for k, v in parent_cls.__dict__.items():
|
165
161
|
if isinstance(v, PartialFunction):
|
@@ -170,9 +166,9 @@ def _find_partial_methods_for_user_cls(user_cls: Type[Any], flags: int) -> Dict[
|
|
170
166
|
return partial_functions
|
171
167
|
|
172
168
|
|
173
|
-
def _find_callables_for_obj(user_obj: Any, flags: int) ->
|
169
|
+
def _find_callables_for_obj(user_obj: Any, flags: int) -> dict[str, Callable[..., Any]]:
|
174
170
|
"""Grabs all methods for an object, and binds them to the class"""
|
175
|
-
user_cls:
|
171
|
+
user_cls: type = type(user_obj)
|
176
172
|
return {k: pf.raw_f.__get__(user_obj) for k, pf in _find_partial_methods_for_user_cls(user_cls, flags).items()}
|
177
173
|
|
178
174
|
|
@@ -256,9 +252,9 @@ def _method(
|
|
256
252
|
return wrapper
|
257
253
|
|
258
254
|
|
259
|
-
def _parse_custom_domains(custom_domains: Optional[Iterable[str]] = None) ->
|
255
|
+
def _parse_custom_domains(custom_domains: Optional[Iterable[str]] = None) -> list[api_pb2.CustomDomainConfig]:
|
260
256
|
assert not isinstance(custom_domains, str), "custom_domains must be `Iterable[str]` but is `str` instead."
|
261
|
-
_custom_domains:
|
257
|
+
_custom_domains: list[api_pb2.CustomDomainConfig] = []
|
262
258
|
if custom_domains is not None:
|
263
259
|
for custom_domain in custom_domains:
|
264
260
|
_custom_domains.append(api_pb2.CustomDomainConfig(name=custom_domain))
|
@@ -608,7 +604,7 @@ ExitHandlerType = Union[
|
|
608
604
|
# NOTE: return types of these callables should be `Union[None, Awaitable[None]]` but
|
609
605
|
# synchronicity type stubs would strip Awaitable so we use Any for now
|
610
606
|
# Original, __exit__ style method signature (now deprecated)
|
611
|
-
Callable[[Any, Optional[
|
607
|
+
Callable[[Any, Optional[type[BaseException]], Optional[BaseException], Any], Any],
|
612
608
|
# Forward-looking unparameterized method
|
613
609
|
Callable[[Any], Any],
|
614
610
|
]
|
modal/partial_function.pyi
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
import collections.abc
|
1
2
|
import enum
|
2
3
|
import modal.functions
|
3
4
|
import modal_proto.api_pb2
|
@@ -81,10 +82,8 @@ class PartialFunction(typing.Generic[P, ReturnType, OriginalReturnType]):
|
|
81
82
|
def __del__(self): ...
|
82
83
|
def add_flags(self, flags) -> PartialFunction: ...
|
83
84
|
|
84
|
-
def _find_partial_methods_for_user_cls(
|
85
|
-
|
86
|
-
) -> typing.Dict[str, _PartialFunction]: ...
|
87
|
-
def _find_callables_for_obj(user_obj: typing.Any, flags: int) -> typing.Dict[str, typing.Callable[..., typing.Any]]: ...
|
85
|
+
def _find_partial_methods_for_user_cls(user_cls: type[typing.Any], flags: int) -> dict[str, _PartialFunction]: ...
|
86
|
+
def _find_callables_for_obj(user_obj: typing.Any, flags: int) -> dict[str, typing.Callable[..., typing.Any]]: ...
|
88
87
|
|
89
88
|
class _MethodDecoratorType:
|
90
89
|
@typing.overload
|
@@ -95,9 +94,9 @@ class _MethodDecoratorType:
|
|
95
94
|
def __call__(
|
96
95
|
self,
|
97
96
|
func: typing.Callable[
|
98
|
-
typing_extensions.Concatenate[typing.Any, P],
|
97
|
+
typing_extensions.Concatenate[typing.Any, P], collections.abc.Coroutine[typing.Any, typing.Any, ReturnType]
|
99
98
|
],
|
100
|
-
) -> PartialFunction[P, ReturnType,
|
99
|
+
) -> PartialFunction[P, ReturnType, collections.abc.Coroutine[typing.Any, typing.Any, ReturnType]]: ...
|
101
100
|
@typing.overload
|
102
101
|
def __call__(
|
103
102
|
self, func: typing.Callable[typing_extensions.Concatenate[typing.Any, P], ReturnType]
|
@@ -110,29 +109,29 @@ def _method(
|
|
110
109
|
keep_warm: typing.Optional[int] = None,
|
111
110
|
) -> _MethodDecoratorType: ...
|
112
111
|
def _parse_custom_domains(
|
113
|
-
custom_domains: typing.Optional[
|
114
|
-
) ->
|
112
|
+
custom_domains: typing.Optional[collections.abc.Iterable[str]] = None,
|
113
|
+
) -> list[modal_proto.api_pb2.CustomDomainConfig]: ...
|
115
114
|
def _web_endpoint(
|
116
115
|
_warn_parentheses_missing=None,
|
117
116
|
*,
|
118
117
|
method: str = "GET",
|
119
118
|
label: typing.Optional[str] = None,
|
120
119
|
docs: bool = False,
|
121
|
-
custom_domains: typing.Optional[
|
120
|
+
custom_domains: typing.Optional[collections.abc.Iterable[str]] = None,
|
122
121
|
wait_for_response: bool = True,
|
123
122
|
) -> typing.Callable[[typing.Callable[P, ReturnType]], _PartialFunction[P, ReturnType, ReturnType]]: ...
|
124
123
|
def _asgi_app(
|
125
124
|
_warn_parentheses_missing=None,
|
126
125
|
*,
|
127
126
|
label: typing.Optional[str] = None,
|
128
|
-
custom_domains: typing.Optional[
|
127
|
+
custom_domains: typing.Optional[collections.abc.Iterable[str]] = None,
|
129
128
|
wait_for_response: bool = True,
|
130
129
|
) -> typing.Callable[[typing.Callable[..., typing.Any]], _PartialFunction]: ...
|
131
130
|
def _wsgi_app(
|
132
131
|
_warn_parentheses_missing=None,
|
133
132
|
*,
|
134
133
|
label: typing.Optional[str] = None,
|
135
|
-
custom_domains: typing.Optional[
|
134
|
+
custom_domains: typing.Optional[collections.abc.Iterable[str]] = None,
|
136
135
|
wait_for_response: bool = True,
|
137
136
|
) -> typing.Callable[[typing.Callable[..., typing.Any]], _PartialFunction]: ...
|
138
137
|
def _web_server(
|
@@ -140,7 +139,7 @@ def _web_server(
|
|
140
139
|
*,
|
141
140
|
startup_timeout: float = 5.0,
|
142
141
|
label: typing.Optional[str] = None,
|
143
|
-
custom_domains: typing.Optional[
|
142
|
+
custom_domains: typing.Optional[collections.abc.Iterable[str]] = None,
|
144
143
|
) -> typing.Callable[[typing.Callable[..., typing.Any]], _PartialFunction]: ...
|
145
144
|
def _disallow_wrapping_method(f: _PartialFunction, wrapper: str) -> None: ...
|
146
145
|
def _build(
|
@@ -155,7 +154,7 @@ def _exit(
|
|
155
154
|
[
|
156
155
|
typing.Union[
|
157
156
|
typing.Callable[
|
158
|
-
[typing.Any, typing.Optional[
|
157
|
+
[typing.Any, typing.Optional[type[BaseException]], typing.Optional[BaseException], typing.Any],
|
159
158
|
typing.Any,
|
160
159
|
],
|
161
160
|
typing.Callable[[typing.Any], typing.Any],
|
@@ -178,21 +177,21 @@ def web_endpoint(
|
|
178
177
|
method: str = "GET",
|
179
178
|
label: typing.Optional[str] = None,
|
180
179
|
docs: bool = False,
|
181
|
-
custom_domains: typing.Optional[
|
180
|
+
custom_domains: typing.Optional[collections.abc.Iterable[str]] = None,
|
182
181
|
wait_for_response: bool = True,
|
183
182
|
) -> typing.Callable[[typing.Callable[P, ReturnType]], PartialFunction[P, ReturnType, ReturnType]]: ...
|
184
183
|
def asgi_app(
|
185
184
|
_warn_parentheses_missing=None,
|
186
185
|
*,
|
187
186
|
label: typing.Optional[str] = None,
|
188
|
-
custom_domains: typing.Optional[
|
187
|
+
custom_domains: typing.Optional[collections.abc.Iterable[str]] = None,
|
189
188
|
wait_for_response: bool = True,
|
190
189
|
) -> typing.Callable[[typing.Callable[..., typing.Any]], PartialFunction]: ...
|
191
190
|
def wsgi_app(
|
192
191
|
_warn_parentheses_missing=None,
|
193
192
|
*,
|
194
193
|
label: typing.Optional[str] = None,
|
195
|
-
custom_domains: typing.Optional[
|
194
|
+
custom_domains: typing.Optional[collections.abc.Iterable[str]] = None,
|
196
195
|
wait_for_response: bool = True,
|
197
196
|
) -> typing.Callable[[typing.Callable[..., typing.Any]], PartialFunction]: ...
|
198
197
|
def web_server(
|
@@ -200,7 +199,7 @@ def web_server(
|
|
200
199
|
*,
|
201
200
|
startup_timeout: float = 5.0,
|
202
201
|
label: typing.Optional[str] = None,
|
203
|
-
custom_domains: typing.Optional[
|
202
|
+
custom_domains: typing.Optional[collections.abc.Iterable[str]] = None,
|
204
203
|
) -> typing.Callable[[typing.Callable[..., typing.Any]], PartialFunction]: ...
|
205
204
|
def build(
|
206
205
|
_warn_parentheses_missing=None, *, force: bool = False, timeout: int = 86400
|
@@ -214,7 +213,7 @@ def exit(
|
|
214
213
|
[
|
215
214
|
typing.Union[
|
216
215
|
typing.Callable[
|
217
|
-
[typing.Any, typing.Optional[
|
216
|
+
[typing.Any, typing.Optional[type[BaseException]], typing.Optional[BaseException], typing.Any],
|
218
217
|
typing.Any,
|
219
218
|
],
|
220
219
|
typing.Callable[[typing.Any], typing.Any],
|
modal/queue.py
CHANGED
@@ -2,7 +2,8 @@
|
|
2
2
|
import queue # The system library
|
3
3
|
import time
|
4
4
|
import warnings
|
5
|
-
from
|
5
|
+
from collections.abc import AsyncGenerator, AsyncIterator
|
6
|
+
from typing import Any, Optional
|
6
7
|
|
7
8
|
from grpclib import GRPCError, Status
|
8
9
|
from synchronicity.async_wrap import asynccontextmanager
|
@@ -113,7 +114,7 @@ class _Queue(_Object, type_prefix="qu"):
|
|
113
114
|
@classmethod
|
114
115
|
@asynccontextmanager
|
115
116
|
async def ephemeral(
|
116
|
-
cls:
|
117
|
+
cls: type["_Queue"],
|
117
118
|
client: Optional[_Client] = None,
|
118
119
|
environment_name: Optional[str] = None,
|
119
120
|
_heartbeat_sleep: float = EPHEMERAL_OBJECT_HEARTBEAT_SLEEP,
|
@@ -126,7 +127,9 @@ class _Queue(_Object, type_prefix="qu"):
|
|
126
127
|
|
127
128
|
with Queue.ephemeral() as q:
|
128
129
|
q.put(123)
|
130
|
+
```
|
129
131
|
|
132
|
+
```python notest
|
130
133
|
async with Queue.ephemeral() as q:
|
131
134
|
await q.put.aio(123)
|
132
135
|
```
|
@@ -208,7 +211,7 @@ class _Queue(_Object, type_prefix="qu"):
|
|
208
211
|
req = api_pb2.QueueDeleteRequest(queue_id=obj.object_id)
|
209
212
|
await retry_transient_errors(obj._client.stub.QueueDelete, req)
|
210
213
|
|
211
|
-
async def _get_nonblocking(self, partition: Optional[str], n_values: int) ->
|
214
|
+
async def _get_nonblocking(self, partition: Optional[str], n_values: int) -> list[Any]:
|
212
215
|
request = api_pb2.QueueGetRequest(
|
213
216
|
queue_id=self.object_id,
|
214
217
|
partition_key=self.validate_partition_key(partition),
|
@@ -222,7 +225,7 @@ class _Queue(_Object, type_prefix="qu"):
|
|
222
225
|
else:
|
223
226
|
return []
|
224
227
|
|
225
|
-
async def _get_blocking(self, partition: Optional[str], timeout: Optional[float], n_values: int) ->
|
228
|
+
async def _get_blocking(self, partition: Optional[str], timeout: Optional[float], n_values: int) -> list[Any]:
|
226
229
|
if timeout is not None:
|
227
230
|
deadline = time.time() + timeout
|
228
231
|
else:
|
@@ -292,7 +295,7 @@ class _Queue(_Object, type_prefix="qu"):
|
|
292
295
|
@live_method
|
293
296
|
async def get_many(
|
294
297
|
self, n_values: int, block: bool = True, timeout: Optional[float] = None, *, partition: Optional[str] = None
|
295
|
-
) ->
|
298
|
+
) -> list[Any]:
|
296
299
|
"""Remove and return up to `n_values` objects from the queue.
|
297
300
|
|
298
301
|
If there are fewer than `n_values` items in the queue, return all of them.
|
@@ -335,7 +338,7 @@ class _Queue(_Object, type_prefix="qu"):
|
|
335
338
|
@live_method
|
336
339
|
async def put_many(
|
337
340
|
self,
|
338
|
-
vs:
|
341
|
+
vs: list[Any],
|
339
342
|
block: bool = True,
|
340
343
|
timeout: Optional[float] = None,
|
341
344
|
*,
|
@@ -359,7 +362,7 @@ class _Queue(_Object, type_prefix="qu"):
|
|
359
362
|
await self._put_many_nonblocking(partition, partition_ttl, vs)
|
360
363
|
|
361
364
|
async def _put_many_blocking(
|
362
|
-
self, partition: Optional[str], partition_ttl: int, vs:
|
365
|
+
self, partition: Optional[str], partition_ttl: int, vs: list[Any], timeout: Optional[float] = None
|
363
366
|
):
|
364
367
|
vs_encoded = [serialize(v) for v in vs]
|
365
368
|
|
@@ -388,7 +391,7 @@ class _Queue(_Object, type_prefix="qu"):
|
|
388
391
|
else:
|
389
392
|
raise exc
|
390
393
|
|
391
|
-
async def _put_many_nonblocking(self, partition: Optional[str], partition_ttl: int, vs:
|
394
|
+
async def _put_many_nonblocking(self, partition: Optional[str], partition_ttl: int, vs: list[Any]):
|
392
395
|
vs_encoded = [serialize(v) for v in vs]
|
393
396
|
request = api_pb2.QueuePutRequest(
|
394
397
|
queue_id=self.object_id,
|
modal/queue.pyi
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
import collections.abc
|
1
2
|
import modal.client
|
2
3
|
import modal.object
|
3
4
|
import synchronicity.combined_types
|
@@ -12,7 +13,7 @@ class _Queue(modal.object._Object):
|
|
12
13
|
def validate_partition_key(partition: typing.Optional[str]) -> bytes: ...
|
13
14
|
@classmethod
|
14
15
|
def ephemeral(
|
15
|
-
cls:
|
16
|
+
cls: type[_Queue],
|
16
17
|
client: typing.Optional[modal.client._Client] = None,
|
17
18
|
environment_name: typing.Optional[str] = None,
|
18
19
|
_heartbeat_sleep: float = 300,
|
@@ -36,10 +37,10 @@ class _Queue(modal.object._Object):
|
|
36
37
|
client: typing.Optional[modal.client._Client] = None,
|
37
38
|
environment_name: typing.Optional[str] = None,
|
38
39
|
): ...
|
39
|
-
async def _get_nonblocking(self, partition: typing.Optional[str], n_values: int) ->
|
40
|
+
async def _get_nonblocking(self, partition: typing.Optional[str], n_values: int) -> list[typing.Any]: ...
|
40
41
|
async def _get_blocking(
|
41
42
|
self, partition: typing.Optional[str], timeout: typing.Optional[float], n_values: int
|
42
|
-
) ->
|
43
|
+
) -> list[typing.Any]: ...
|
43
44
|
async def clear(self, *, partition: typing.Optional[str] = None, all: bool = False) -> None: ...
|
44
45
|
async def get(
|
45
46
|
self, block: bool = True, timeout: typing.Optional[float] = None, *, partition: typing.Optional[str] = None
|
@@ -51,7 +52,7 @@ class _Queue(modal.object._Object):
|
|
51
52
|
timeout: typing.Optional[float] = None,
|
52
53
|
*,
|
53
54
|
partition: typing.Optional[str] = None,
|
54
|
-
) ->
|
55
|
+
) -> list[typing.Any]: ...
|
55
56
|
async def put(
|
56
57
|
self,
|
57
58
|
v: typing.Any,
|
@@ -63,7 +64,7 @@ class _Queue(modal.object._Object):
|
|
63
64
|
) -> None: ...
|
64
65
|
async def put_many(
|
65
66
|
self,
|
66
|
-
vs:
|
67
|
+
vs: list[typing.Any],
|
67
68
|
block: bool = True,
|
68
69
|
timeout: typing.Optional[float] = None,
|
69
70
|
*,
|
@@ -74,16 +75,16 @@ class _Queue(modal.object._Object):
|
|
74
75
|
self,
|
75
76
|
partition: typing.Optional[str],
|
76
77
|
partition_ttl: int,
|
77
|
-
vs:
|
78
|
+
vs: list[typing.Any],
|
78
79
|
timeout: typing.Optional[float] = None,
|
79
80
|
): ...
|
80
81
|
async def _put_many_nonblocking(
|
81
|
-
self, partition: typing.Optional[str], partition_ttl: int, vs:
|
82
|
+
self, partition: typing.Optional[str], partition_ttl: int, vs: list[typing.Any]
|
82
83
|
): ...
|
83
84
|
async def len(self, *, partition: typing.Optional[str] = None, total: bool = False) -> int: ...
|
84
85
|
def iterate(
|
85
86
|
self, *, partition: typing.Optional[str] = None, item_poll_timeout: float = 0.0
|
86
|
-
) ->
|
87
|
+
) -> collections.abc.AsyncGenerator[typing.Any, None]: ...
|
87
88
|
|
88
89
|
class Queue(modal.object.Object):
|
89
90
|
def __init__(self): ...
|
@@ -93,7 +94,7 @@ class Queue(modal.object.Object):
|
|
93
94
|
def validate_partition_key(partition: typing.Optional[str]) -> bytes: ...
|
94
95
|
@classmethod
|
95
96
|
def ephemeral(
|
96
|
-
cls:
|
97
|
+
cls: type[Queue],
|
97
98
|
client: typing.Optional[modal.client.Client] = None,
|
98
99
|
environment_name: typing.Optional[str] = None,
|
99
100
|
_heartbeat_sleep: float = 300,
|
@@ -142,18 +143,18 @@ class Queue(modal.object.Object):
|
|
142
143
|
delete: __delete_spec
|
143
144
|
|
144
145
|
class ___get_nonblocking_spec(typing_extensions.Protocol):
|
145
|
-
def __call__(self, partition: typing.Optional[str], n_values: int) ->
|
146
|
-
async def aio(self, partition: typing.Optional[str], n_values: int) ->
|
146
|
+
def __call__(self, partition: typing.Optional[str], n_values: int) -> list[typing.Any]: ...
|
147
|
+
async def aio(self, partition: typing.Optional[str], n_values: int) -> list[typing.Any]: ...
|
147
148
|
|
148
149
|
_get_nonblocking: ___get_nonblocking_spec
|
149
150
|
|
150
151
|
class ___get_blocking_spec(typing_extensions.Protocol):
|
151
152
|
def __call__(
|
152
153
|
self, partition: typing.Optional[str], timeout: typing.Optional[float], n_values: int
|
153
|
-
) ->
|
154
|
+
) -> list[typing.Any]: ...
|
154
155
|
async def aio(
|
155
156
|
self, partition: typing.Optional[str], timeout: typing.Optional[float], n_values: int
|
156
|
-
) ->
|
157
|
+
) -> list[typing.Any]: ...
|
157
158
|
|
158
159
|
_get_blocking: ___get_blocking_spec
|
159
160
|
|
@@ -181,7 +182,7 @@ class Queue(modal.object.Object):
|
|
181
182
|
timeout: typing.Optional[float] = None,
|
182
183
|
*,
|
183
184
|
partition: typing.Optional[str] = None,
|
184
|
-
) ->
|
185
|
+
) -> list[typing.Any]: ...
|
185
186
|
async def aio(
|
186
187
|
self,
|
187
188
|
n_values: int,
|
@@ -189,7 +190,7 @@ class Queue(modal.object.Object):
|
|
189
190
|
timeout: typing.Optional[float] = None,
|
190
191
|
*,
|
191
192
|
partition: typing.Optional[str] = None,
|
192
|
-
) ->
|
193
|
+
) -> list[typing.Any]: ...
|
193
194
|
|
194
195
|
get_many: __get_many_spec
|
195
196
|
|
@@ -218,7 +219,7 @@ class Queue(modal.object.Object):
|
|
218
219
|
class __put_many_spec(typing_extensions.Protocol):
|
219
220
|
def __call__(
|
220
221
|
self,
|
221
|
-
vs:
|
222
|
+
vs: list[typing.Any],
|
222
223
|
block: bool = True,
|
223
224
|
timeout: typing.Optional[float] = None,
|
224
225
|
*,
|
@@ -227,7 +228,7 @@ class Queue(modal.object.Object):
|
|
227
228
|
) -> None: ...
|
228
229
|
async def aio(
|
229
230
|
self,
|
230
|
-
vs:
|
231
|
+
vs: list[typing.Any],
|
231
232
|
block: bool = True,
|
232
233
|
timeout: typing.Optional[float] = None,
|
233
234
|
*,
|
@@ -242,22 +243,22 @@ class Queue(modal.object.Object):
|
|
242
243
|
self,
|
243
244
|
partition: typing.Optional[str],
|
244
245
|
partition_ttl: int,
|
245
|
-
vs:
|
246
|
+
vs: list[typing.Any],
|
246
247
|
timeout: typing.Optional[float] = None,
|
247
248
|
): ...
|
248
249
|
async def aio(
|
249
250
|
self,
|
250
251
|
partition: typing.Optional[str],
|
251
252
|
partition_ttl: int,
|
252
|
-
vs:
|
253
|
+
vs: list[typing.Any],
|
253
254
|
timeout: typing.Optional[float] = None,
|
254
255
|
): ...
|
255
256
|
|
256
257
|
_put_many_blocking: ___put_many_blocking_spec
|
257
258
|
|
258
259
|
class ___put_many_nonblocking_spec(typing_extensions.Protocol):
|
259
|
-
def __call__(self, partition: typing.Optional[str], partition_ttl: int, vs:
|
260
|
-
async def aio(self, partition: typing.Optional[str], partition_ttl: int, vs:
|
260
|
+
def __call__(self, partition: typing.Optional[str], partition_ttl: int, vs: list[typing.Any]): ...
|
261
|
+
async def aio(self, partition: typing.Optional[str], partition_ttl: int, vs: list[typing.Any]): ...
|
261
262
|
|
262
263
|
_put_many_nonblocking: ___put_many_nonblocking_spec
|
263
264
|
|
@@ -273,6 +274,6 @@ class Queue(modal.object.Object):
|
|
273
274
|
) -> typing.Generator[typing.Any, None, None]: ...
|
274
275
|
def aio(
|
275
276
|
self, *, partition: typing.Optional[str] = None, item_poll_timeout: float = 0.0
|
276
|
-
) ->
|
277
|
+
) -> collections.abc.AsyncGenerator[typing.Any, None]: ...
|
277
278
|
|
278
279
|
iterate: __iterate_spec
|