modal 1.1.5.dev66__py3-none-any.whl → 1.3.1.dev8__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.
Potentially problematic release.
This version of modal might be problematic. Click here for more details.
- modal/__init__.py +4 -4
- modal/__main__.py +4 -29
- modal/_billing.py +84 -0
- modal/_clustered_functions.py +1 -3
- modal/_container_entrypoint.py +33 -208
- modal/_functions.py +171 -138
- modal/_grpc_client.py +191 -0
- modal/_ipython.py +16 -6
- modal/_load_context.py +106 -0
- modal/_object.py +72 -21
- modal/_output.py +12 -14
- modal/_partial_function.py +31 -4
- modal/_resolver.py +44 -57
- modal/_runtime/container_io_manager.py +30 -28
- modal/_runtime/container_io_manager.pyi +42 -44
- modal/_runtime/gpu_memory_snapshot.py +9 -7
- modal/_runtime/user_code_event_loop.py +80 -0
- modal/_runtime/user_code_imports.py +236 -10
- modal/_serialization.py +2 -1
- modal/_traceback.py +4 -13
- modal/_tunnel.py +16 -11
- modal/_tunnel.pyi +25 -3
- modal/_utils/async_utils.py +337 -10
- modal/_utils/auth_token_manager.py +1 -4
- modal/_utils/blob_utils.py +29 -22
- modal/_utils/function_utils.py +20 -21
- modal/_utils/grpc_testing.py +6 -3
- modal/_utils/grpc_utils.py +223 -64
- modal/_utils/mount_utils.py +26 -1
- modal/_utils/name_utils.py +2 -3
- modal/_utils/package_utils.py +0 -1
- modal/_utils/rand_pb_testing.py +8 -1
- modal/_utils/task_command_router_client.py +524 -0
- modal/_vendor/cloudpickle.py +144 -48
- modal/app.py +285 -105
- modal/app.pyi +216 -53
- modal/billing.py +5 -0
- modal/builder/2025.06.txt +6 -3
- modal/builder/PREVIEW.txt +2 -1
- modal/builder/base-images.json +4 -2
- modal/cli/_download.py +19 -3
- modal/cli/cluster.py +4 -2
- modal/cli/config.py +3 -1
- modal/cli/container.py +5 -4
- modal/cli/dict.py +5 -2
- modal/cli/entry_point.py +26 -2
- modal/cli/environment.py +2 -16
- modal/cli/launch.py +1 -76
- modal/cli/network_file_system.py +5 -20
- modal/cli/programs/run_jupyter.py +1 -1
- modal/cli/programs/vscode.py +1 -1
- modal/cli/queues.py +5 -4
- modal/cli/run.py +24 -204
- modal/cli/secret.py +1 -2
- modal/cli/shell.py +375 -0
- modal/cli/utils.py +1 -13
- modal/cli/volume.py +11 -17
- modal/client.py +16 -125
- modal/client.pyi +94 -144
- modal/cloud_bucket_mount.py +3 -1
- modal/cloud_bucket_mount.pyi +4 -0
- modal/cls.py +101 -64
- modal/cls.pyi +9 -8
- modal/config.py +21 -1
- modal/container_process.py +288 -12
- modal/container_process.pyi +99 -38
- modal/dict.py +72 -33
- modal/dict.pyi +88 -57
- modal/environments.py +16 -8
- modal/environments.pyi +6 -2
- modal/exception.py +154 -16
- modal/experimental/__init__.py +24 -53
- modal/experimental/flash.py +161 -74
- modal/experimental/flash.pyi +97 -49
- modal/file_io.py +50 -92
- modal/file_io.pyi +117 -89
- modal/functions.pyi +70 -87
- modal/image.py +82 -47
- modal/image.pyi +51 -30
- modal/io_streams.py +500 -149
- modal/io_streams.pyi +279 -189
- modal/mount.py +60 -46
- modal/mount.pyi +41 -17
- modal/network_file_system.py +19 -11
- modal/network_file_system.pyi +72 -39
- modal/object.pyi +114 -22
- modal/parallel_map.py +42 -44
- modal/parallel_map.pyi +9 -17
- modal/partial_function.pyi +4 -2
- modal/proxy.py +14 -6
- modal/proxy.pyi +10 -2
- modal/queue.py +45 -38
- modal/queue.pyi +88 -52
- modal/runner.py +96 -96
- modal/runner.pyi +44 -27
- modal/sandbox.py +225 -107
- modal/sandbox.pyi +226 -60
- modal/secret.py +58 -56
- modal/secret.pyi +28 -13
- modal/serving.py +7 -11
- modal/serving.pyi +7 -8
- modal/snapshot.py +29 -15
- modal/snapshot.pyi +18 -10
- modal/token_flow.py +1 -1
- modal/token_flow.pyi +4 -6
- modal/volume.py +102 -55
- modal/volume.pyi +125 -66
- {modal-1.1.5.dev66.dist-info → modal-1.3.1.dev8.dist-info}/METADATA +10 -9
- modal-1.3.1.dev8.dist-info/RECORD +189 -0
- modal_proto/api.proto +141 -70
- modal_proto/api_grpc.py +42 -26
- modal_proto/api_pb2.py +1123 -1103
- modal_proto/api_pb2.pyi +331 -83
- modal_proto/api_pb2_grpc.py +80 -48
- modal_proto/api_pb2_grpc.pyi +26 -18
- modal_proto/modal_api_grpc.py +175 -174
- modal_proto/task_command_router.proto +164 -0
- modal_proto/task_command_router_grpc.py +138 -0
- modal_proto/task_command_router_pb2.py +180 -0
- modal_proto/{sandbox_router_pb2.pyi → task_command_router_pb2.pyi} +148 -57
- modal_proto/task_command_router_pb2_grpc.py +272 -0
- modal_proto/task_command_router_pb2_grpc.pyi +100 -0
- modal_version/__init__.py +1 -1
- modal_version/__main__.py +1 -1
- modal/cli/programs/launch_instance_ssh.py +0 -94
- modal/cli/programs/run_marimo.py +0 -95
- modal-1.1.5.dev66.dist-info/RECORD +0 -191
- modal_proto/modal_options_grpc.py +0 -3
- modal_proto/options.proto +0 -19
- modal_proto/options_grpc.py +0 -3
- modal_proto/options_pb2.py +0 -35
- modal_proto/options_pb2.pyi +0 -20
- modal_proto/options_pb2_grpc.py +0 -4
- modal_proto/options_pb2_grpc.pyi +0 -7
- modal_proto/sandbox_router.proto +0 -125
- modal_proto/sandbox_router_grpc.py +0 -89
- modal_proto/sandbox_router_pb2.py +0 -128
- modal_proto/sandbox_router_pb2_grpc.py +0 -169
- modal_proto/sandbox_router_pb2_grpc.pyi +0 -63
- {modal-1.1.5.dev66.dist-info → modal-1.3.1.dev8.dist-info}/WHEEL +0 -0
- {modal-1.1.5.dev66.dist-info → modal-1.3.1.dev8.dist-info}/entry_points.txt +0 -0
- {modal-1.1.5.dev66.dist-info → modal-1.3.1.dev8.dist-info}/licenses/LICENSE +0 -0
- {modal-1.1.5.dev66.dist-info → modal-1.3.1.dev8.dist-info}/top_level.txt +0 -0
modal/parallel_map.pyi
CHANGED
|
@@ -5,6 +5,7 @@ import collections.abc
|
|
|
5
5
|
import enum
|
|
6
6
|
import modal._functions
|
|
7
7
|
import modal._utils.async_utils
|
|
8
|
+
import modal._utils.grpc_utils
|
|
8
9
|
import modal.client
|
|
9
10
|
import modal.functions
|
|
10
11
|
import modal.retries
|
|
@@ -18,31 +19,29 @@ class _SynchronizedQueue:
|
|
|
18
19
|
async def put(self, item): ...
|
|
19
20
|
async def get(self): ...
|
|
20
21
|
|
|
21
|
-
SUPERSELF = typing.TypeVar("SUPERSELF", covariant=True)
|
|
22
|
-
|
|
23
22
|
class SynchronizedQueue:
|
|
24
23
|
"""mdmd:hidden"""
|
|
25
24
|
def __init__(self, /, *args, **kwargs):
|
|
26
25
|
"""Initialize self. See help(type(self)) for accurate signature."""
|
|
27
26
|
...
|
|
28
27
|
|
|
29
|
-
class __init_spec(typing_extensions.Protocol
|
|
28
|
+
class __init_spec(typing_extensions.Protocol):
|
|
30
29
|
def __call__(self, /): ...
|
|
31
30
|
async def aio(self, /): ...
|
|
32
31
|
|
|
33
|
-
init: __init_spec
|
|
32
|
+
init: __init_spec
|
|
34
33
|
|
|
35
|
-
class __put_spec(typing_extensions.Protocol
|
|
34
|
+
class __put_spec(typing_extensions.Protocol):
|
|
36
35
|
def __call__(self, /, item): ...
|
|
37
36
|
async def aio(self, /, item): ...
|
|
38
37
|
|
|
39
|
-
put: __put_spec
|
|
38
|
+
put: __put_spec
|
|
40
39
|
|
|
41
|
-
class __get_spec(typing_extensions.Protocol
|
|
40
|
+
class __get_spec(typing_extensions.Protocol):
|
|
42
41
|
def __call__(self, /): ...
|
|
43
42
|
async def aio(self, /): ...
|
|
44
43
|
|
|
45
|
-
get: __get_spec
|
|
44
|
+
get: __get_spec
|
|
46
45
|
|
|
47
46
|
class _OutputValue:
|
|
48
47
|
"""_OutputValue(value: Any)"""
|
|
@@ -96,15 +95,8 @@ class InputPumper:
|
|
|
96
95
|
...
|
|
97
96
|
|
|
98
97
|
def pump_inputs(self): ...
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
fn: modal.client.UnaryUnaryWrapper,
|
|
102
|
-
request: typing.Union[
|
|
103
|
-
modal_proto.api_pb2.FunctionPutInputsRequest, modal_proto.api_pb2.FunctionRetryInputsRequest
|
|
104
|
-
],
|
|
105
|
-
) -> typing.Union[
|
|
106
|
-
modal_proto.api_pb2.FunctionPutInputsResponse, modal_proto.api_pb2.FunctionRetryInputsResponse
|
|
107
|
-
]: ...
|
|
98
|
+
@property
|
|
99
|
+
def _function_inputs_retry(self) -> modal._utils.grpc_utils.Retry: ...
|
|
108
100
|
|
|
109
101
|
class SyncInputPumper(InputPumper):
|
|
110
102
|
"""Reads inputs from a queue of FunctionPutInputsItems, and sends them to the server."""
|
modal/partial_function.pyi
CHANGED
|
@@ -53,7 +53,6 @@ class PartialFunction(
|
|
|
53
53
|
) -> modal.functions.Function[
|
|
54
54
|
modal._partial_function.P, modal._partial_function.ReturnType, modal._partial_function.OriginalReturnType
|
|
55
55
|
]: ...
|
|
56
|
-
def __del__(self): ...
|
|
57
56
|
|
|
58
57
|
def method(
|
|
59
58
|
_warn_parentheses_missing=None, *, is_generator: typing.Optional[bool] = None
|
|
@@ -329,7 +328,10 @@ def batched(
|
|
|
329
328
|
...
|
|
330
329
|
|
|
331
330
|
def concurrent(
|
|
332
|
-
_warn_parentheses_missing=None,
|
|
331
|
+
_warn_parentheses_missing=None,
|
|
332
|
+
*,
|
|
333
|
+
max_inputs: typing.Optional[int] = None,
|
|
334
|
+
target_inputs: typing.Optional[int] = None,
|
|
333
335
|
) -> collections.abc.Callable[
|
|
334
336
|
[
|
|
335
337
|
typing.Union[
|
modal/proxy.py
CHANGED
|
@@ -3,9 +3,11 @@ from typing import Optional
|
|
|
3
3
|
|
|
4
4
|
from modal_proto import api_pb2
|
|
5
5
|
|
|
6
|
-
from .
|
|
6
|
+
from ._load_context import LoadContext
|
|
7
|
+
from ._object import _Object
|
|
7
8
|
from ._resolver import Resolver
|
|
8
9
|
from ._utils.async_utils import synchronize_api
|
|
10
|
+
from .client import _Client
|
|
9
11
|
|
|
10
12
|
|
|
11
13
|
class _Proxy(_Object, type_prefix="pr"):
|
|
@@ -20,6 +22,7 @@ class _Proxy(_Object, type_prefix="pr"):
|
|
|
20
22
|
name: str,
|
|
21
23
|
*,
|
|
22
24
|
environment_name: Optional[str] = None,
|
|
25
|
+
client: Optional[_Client] = None,
|
|
23
26
|
) -> "_Proxy":
|
|
24
27
|
"""Reference a Proxy by its name.
|
|
25
28
|
|
|
@@ -28,16 +31,21 @@ class _Proxy(_Object, type_prefix="pr"):
|
|
|
28
31
|
|
|
29
32
|
"""
|
|
30
33
|
|
|
31
|
-
async def _load(self: _Proxy, resolver: Resolver, existing_object_id: Optional[str]):
|
|
34
|
+
async def _load(self: _Proxy, resolver: Resolver, load_context: LoadContext, existing_object_id: Optional[str]):
|
|
32
35
|
req = api_pb2.ProxyGetRequest(
|
|
33
36
|
name=name,
|
|
34
|
-
environment_name=
|
|
37
|
+
environment_name=load_context.environment_name,
|
|
35
38
|
)
|
|
36
|
-
response: api_pb2.ProxyGetResponse = await
|
|
37
|
-
self._hydrate(response.proxy.proxy_id,
|
|
39
|
+
response: api_pb2.ProxyGetResponse = await load_context.client.stub.ProxyGet(req)
|
|
40
|
+
self._hydrate(response.proxy.proxy_id, load_context.client, None)
|
|
38
41
|
|
|
39
42
|
rep = _Proxy._repr(name, environment_name)
|
|
40
|
-
return _Proxy._from_loader(
|
|
43
|
+
return _Proxy._from_loader(
|
|
44
|
+
_load,
|
|
45
|
+
rep,
|
|
46
|
+
is_another_app=True,
|
|
47
|
+
load_context_overrides=LoadContext(client=client, environment_name=environment_name),
|
|
48
|
+
)
|
|
41
49
|
|
|
42
50
|
|
|
43
51
|
Proxy = synchronize_api(_Proxy, target_module=__name__)
|
modal/proxy.pyi
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import modal._object
|
|
2
|
+
import modal.client
|
|
2
3
|
import modal.object
|
|
3
4
|
import typing
|
|
4
5
|
|
|
@@ -9,7 +10,12 @@ class _Proxy(modal._object._Object):
|
|
|
9
10
|
a database. See [the guide](https://modal.com/docs/guide/proxy-ips) for more information.
|
|
10
11
|
"""
|
|
11
12
|
@staticmethod
|
|
12
|
-
def from_name(
|
|
13
|
+
def from_name(
|
|
14
|
+
name: str,
|
|
15
|
+
*,
|
|
16
|
+
environment_name: typing.Optional[str] = None,
|
|
17
|
+
client: typing.Optional[modal.client._Client] = None,
|
|
18
|
+
) -> _Proxy:
|
|
13
19
|
"""Reference a Proxy by its name.
|
|
14
20
|
|
|
15
21
|
In contrast to most other Modal objects, new Proxy objects must be
|
|
@@ -28,7 +34,9 @@ class Proxy(modal.object.Object):
|
|
|
28
34
|
...
|
|
29
35
|
|
|
30
36
|
@staticmethod
|
|
31
|
-
def from_name(
|
|
37
|
+
def from_name(
|
|
38
|
+
name: str, *, environment_name: typing.Optional[str] = None, client: typing.Optional[modal.client.Client] = None
|
|
39
|
+
) -> Proxy:
|
|
32
40
|
"""Reference a Proxy by its name.
|
|
33
41
|
|
|
34
42
|
In contrast to most other Modal objects, new Proxy objects must be
|
modal/queue.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# Copyright Modal Labs 2022
|
|
2
|
+
import builtins
|
|
2
3
|
import queue # The system library
|
|
3
4
|
import time
|
|
4
5
|
import warnings
|
|
@@ -8,12 +9,13 @@ from datetime import datetime
|
|
|
8
9
|
from typing import Any, Optional, Union
|
|
9
10
|
|
|
10
11
|
from google.protobuf.message import Message
|
|
11
|
-
from grpclib import
|
|
12
|
+
from grpclib import Status
|
|
12
13
|
from synchronicity import classproperty
|
|
13
14
|
from synchronicity.async_wrap import asynccontextmanager
|
|
14
15
|
|
|
15
16
|
from modal_proto import api_pb2
|
|
16
17
|
|
|
18
|
+
from ._load_context import LoadContext
|
|
17
19
|
from ._object import (
|
|
18
20
|
EPHEMERAL_OBJECT_HEARTBEAT_SLEEP,
|
|
19
21
|
_get_environment_name,
|
|
@@ -25,11 +27,11 @@ from ._resolver import Resolver
|
|
|
25
27
|
from ._serialization import deserialize, serialize
|
|
26
28
|
from ._utils.async_utils import TaskContext, synchronize_api, warn_if_generator_is_not_consumed
|
|
27
29
|
from ._utils.deprecation import deprecation_warning, warn_if_passing_namespace
|
|
28
|
-
from ._utils.grpc_utils import
|
|
30
|
+
from ._utils.grpc_utils import Retry
|
|
29
31
|
from ._utils.name_utils import check_object_name
|
|
30
32
|
from ._utils.time_utils import as_timestamp, timestamp_to_localized_dt
|
|
31
33
|
from .client import _Client
|
|
32
|
-
from .exception import AlreadyExistsError, InvalidError, NotFoundError, RequestSizeError
|
|
34
|
+
from .exception import AlreadyExistsError, Error, InvalidError, NotFoundError, RequestSizeError, ResourceExhaustedError
|
|
33
35
|
|
|
34
36
|
|
|
35
37
|
@dataclass
|
|
@@ -95,11 +97,9 @@ class _QueueManager:
|
|
|
95
97
|
object_creation_type=object_creation_type,
|
|
96
98
|
)
|
|
97
99
|
try:
|
|
98
|
-
await
|
|
99
|
-
except
|
|
100
|
-
if
|
|
101
|
-
raise AlreadyExistsError(exc.message)
|
|
102
|
-
else:
|
|
100
|
+
await client.stub.QueueGetOrCreate(req)
|
|
101
|
+
except AlreadyExistsError:
|
|
102
|
+
if not allow_existing:
|
|
103
103
|
raise
|
|
104
104
|
|
|
105
105
|
@staticmethod
|
|
@@ -109,7 +109,7 @@ class _QueueManager:
|
|
|
109
109
|
created_before: Optional[Union[datetime, str]] = None, # Limit based on creation date
|
|
110
110
|
environment_name: str = "", # Uses active environment if not specified
|
|
111
111
|
client: Optional[_Client] = None, # Optional client with Modal credentials
|
|
112
|
-
) -> list["_Queue"]:
|
|
112
|
+
) -> builtins.list["_Queue"]:
|
|
113
113
|
"""Return a list of hydrated Queue objects.
|
|
114
114
|
|
|
115
115
|
**Examples:**
|
|
@@ -147,7 +147,7 @@ class _QueueManager:
|
|
|
147
147
|
req = api_pb2.QueueListRequest(
|
|
148
148
|
environment_name=_get_environment_name(environment_name), pagination=pagination
|
|
149
149
|
)
|
|
150
|
-
resp = await
|
|
150
|
+
resp = await client.stub.QueueList(req)
|
|
151
151
|
items.extend(resp.queues)
|
|
152
152
|
finished = (len(resp.queues) < max_page_size) or (max_objects is not None and len(items) >= max_objects)
|
|
153
153
|
return finished
|
|
@@ -205,7 +205,7 @@ class _QueueManager:
|
|
|
205
205
|
raise
|
|
206
206
|
else:
|
|
207
207
|
req = api_pb2.QueueDeleteRequest(queue_id=obj.object_id)
|
|
208
|
-
await
|
|
208
|
+
await obj._client.stub.QueueDelete(req)
|
|
209
209
|
|
|
210
210
|
|
|
211
211
|
QueueManager = synchronize_api(_QueueManager)
|
|
@@ -361,6 +361,7 @@ class _Queue(_Object, type_prefix="qu"):
|
|
|
361
361
|
namespace=None, # mdmd:line-hidden
|
|
362
362
|
environment_name: Optional[str] = None,
|
|
363
363
|
create_if_missing: bool = False,
|
|
364
|
+
client: Optional[_Client] = None,
|
|
364
365
|
) -> "_Queue":
|
|
365
366
|
"""Reference a named Queue, creating if necessary.
|
|
366
367
|
|
|
@@ -376,17 +377,24 @@ class _Queue(_Object, type_prefix="qu"):
|
|
|
376
377
|
check_object_name(name, "Queue")
|
|
377
378
|
warn_if_passing_namespace(namespace, "modal.Queue.from_name")
|
|
378
379
|
|
|
379
|
-
async def _load(self: _Queue, resolver: Resolver, existing_object_id: Optional[str]):
|
|
380
|
+
async def _load(self: _Queue, resolver: Resolver, load_context: LoadContext, existing_object_id: Optional[str]):
|
|
380
381
|
req = api_pb2.QueueGetOrCreateRequest(
|
|
381
382
|
deployment_name=name,
|
|
382
|
-
environment_name=
|
|
383
|
+
environment_name=load_context.environment_name,
|
|
383
384
|
object_creation_type=(api_pb2.OBJECT_CREATION_TYPE_CREATE_IF_MISSING if create_if_missing else None),
|
|
384
385
|
)
|
|
385
|
-
response = await
|
|
386
|
-
self._hydrate(response.queue_id,
|
|
386
|
+
response = await load_context.client.stub.QueueGetOrCreate(req)
|
|
387
|
+
self._hydrate(response.queue_id, load_context.client, response.metadata)
|
|
387
388
|
|
|
388
389
|
rep = _Queue._repr(name, environment_name)
|
|
389
|
-
return _Queue._from_loader(
|
|
390
|
+
return _Queue._from_loader(
|
|
391
|
+
_load,
|
|
392
|
+
rep,
|
|
393
|
+
is_another_app=True,
|
|
394
|
+
hydrate_lazily=True,
|
|
395
|
+
name=name,
|
|
396
|
+
load_context_overrides=LoadContext(environment_name=environment_name, client=client),
|
|
397
|
+
)
|
|
390
398
|
|
|
391
399
|
@staticmethod
|
|
392
400
|
async def delete(name: str, *, client: Optional[_Client] = None, environment_name: Optional[str] = None):
|
|
@@ -424,7 +432,7 @@ class _Queue(_Object, type_prefix="qu"):
|
|
|
424
432
|
n_values=n_values,
|
|
425
433
|
)
|
|
426
434
|
|
|
427
|
-
response = await
|
|
435
|
+
response = await self._client.stub.QueueGet(request)
|
|
428
436
|
if response.values:
|
|
429
437
|
return [deserialize(value, self._client) for value in response.values]
|
|
430
438
|
else:
|
|
@@ -449,7 +457,7 @@ class _Queue(_Object, type_prefix="qu"):
|
|
|
449
457
|
n_values=n_values,
|
|
450
458
|
)
|
|
451
459
|
|
|
452
|
-
response = await
|
|
460
|
+
response = await self._client.stub.QueueGet(request)
|
|
453
461
|
|
|
454
462
|
if response.values:
|
|
455
463
|
return [deserialize(value, self._client) for value in response.values]
|
|
@@ -469,7 +477,7 @@ class _Queue(_Object, type_prefix="qu"):
|
|
|
469
477
|
partition_key=self.validate_partition_key(partition),
|
|
470
478
|
all_partitions=all,
|
|
471
479
|
)
|
|
472
|
-
await
|
|
480
|
+
await self._client.stub.QueueClear(request)
|
|
473
481
|
|
|
474
482
|
@live_method
|
|
475
483
|
async def get(
|
|
@@ -578,21 +586,22 @@ class _Queue(_Object, type_prefix="qu"):
|
|
|
578
586
|
partition_ttl_seconds=partition_ttl,
|
|
579
587
|
)
|
|
580
588
|
try:
|
|
581
|
-
await
|
|
582
|
-
self._client.stub.QueuePut,
|
|
589
|
+
await self._client.stub.QueuePut(
|
|
583
590
|
request,
|
|
584
591
|
# A full queue will return this status.
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
592
|
+
retry=Retry(
|
|
593
|
+
additional_status_codes=[Status.RESOURCE_EXHAUSTED],
|
|
594
|
+
max_delay=30.0,
|
|
595
|
+
max_retries=None,
|
|
596
|
+
total_timeout=timeout,
|
|
597
|
+
),
|
|
589
598
|
)
|
|
590
|
-
except
|
|
591
|
-
if
|
|
592
|
-
raise queue.Full(str(exc))
|
|
593
|
-
elif "status = '413'" in exc.message:
|
|
599
|
+
except Error as exc:
|
|
600
|
+
if "status = '413'" in str(exc):
|
|
594
601
|
method = "put_many" if len(vs) > 1 else "put"
|
|
595
602
|
raise RequestSizeError(f"Queue.{method} request is too large") from exc
|
|
603
|
+
elif isinstance(exc, ResourceExhaustedError):
|
|
604
|
+
raise queue.Full(str(exc))
|
|
596
605
|
else:
|
|
597
606
|
raise exc
|
|
598
607
|
|
|
@@ -605,13 +614,13 @@ class _Queue(_Object, type_prefix="qu"):
|
|
|
605
614
|
partition_ttl_seconds=partition_ttl,
|
|
606
615
|
)
|
|
607
616
|
try:
|
|
608
|
-
await
|
|
609
|
-
except
|
|
610
|
-
if
|
|
611
|
-
raise queue.Full(exc.message)
|
|
612
|
-
elif "status = '413'" in exc.message:
|
|
617
|
+
await self._client.stub.QueuePut(request)
|
|
618
|
+
except Error as exc:
|
|
619
|
+
if "status = '413'" in str(exc):
|
|
613
620
|
method = "put_many" if len(vs) > 1 else "put"
|
|
614
621
|
raise RequestSizeError(f"Queue.{method} request is too large") from exc
|
|
622
|
+
elif isinstance(exc, ResourceExhaustedError):
|
|
623
|
+
raise queue.Full(str(exc))
|
|
615
624
|
else:
|
|
616
625
|
raise exc
|
|
617
626
|
|
|
@@ -625,7 +634,7 @@ class _Queue(_Object, type_prefix="qu"):
|
|
|
625
634
|
partition_key=self.validate_partition_key(partition),
|
|
626
635
|
total=total,
|
|
627
636
|
)
|
|
628
|
-
response = await
|
|
637
|
+
response = await self._client.stub.QueueLen(request)
|
|
629
638
|
return response.len
|
|
630
639
|
|
|
631
640
|
@warn_if_generator_is_not_consumed()
|
|
@@ -651,9 +660,7 @@ class _Queue(_Object, type_prefix="qu"):
|
|
|
651
660
|
item_poll_timeout=poll_duration,
|
|
652
661
|
)
|
|
653
662
|
|
|
654
|
-
response: api_pb2.QueueNextItemsResponse = await
|
|
655
|
-
self._client.stub.QueueNextItems, request
|
|
656
|
-
)
|
|
663
|
+
response: api_pb2.QueueNextItemsResponse = await self._client.stub.QueueNextItems(request)
|
|
657
664
|
if response.items:
|
|
658
665
|
for item in response.items:
|
|
659
666
|
yield deserialize(item.value, self._client)
|
modal/queue.pyi
CHANGED
|
@@ -213,7 +213,7 @@ class QueueManager:
|
|
|
213
213
|
"""
|
|
214
214
|
...
|
|
215
215
|
|
|
216
|
-
create: __create_spec
|
|
216
|
+
create: typing.ClassVar[__create_spec]
|
|
217
217
|
|
|
218
218
|
class __list_spec(typing_extensions.Protocol):
|
|
219
219
|
def __call__(
|
|
@@ -286,7 +286,7 @@ class QueueManager:
|
|
|
286
286
|
"""
|
|
287
287
|
...
|
|
288
288
|
|
|
289
|
-
list: __list_spec
|
|
289
|
+
list: typing.ClassVar[__list_spec]
|
|
290
290
|
|
|
291
291
|
class __delete_spec(typing_extensions.Protocol):
|
|
292
292
|
def __call__(
|
|
@@ -349,7 +349,7 @@ class QueueManager:
|
|
|
349
349
|
"""
|
|
350
350
|
...
|
|
351
351
|
|
|
352
|
-
delete: __delete_spec
|
|
352
|
+
delete: typing.ClassVar[__delete_spec]
|
|
353
353
|
|
|
354
354
|
class _Queue(modal._object._Object):
|
|
355
355
|
"""Distributed, FIFO queue for data flow in Modal apps.
|
|
@@ -464,7 +464,12 @@ class _Queue(modal._object._Object):
|
|
|
464
464
|
|
|
465
465
|
@staticmethod
|
|
466
466
|
def from_name(
|
|
467
|
-
name: str,
|
|
467
|
+
name: str,
|
|
468
|
+
*,
|
|
469
|
+
namespace=None,
|
|
470
|
+
environment_name: typing.Optional[str] = None,
|
|
471
|
+
create_if_missing: bool = False,
|
|
472
|
+
client: typing.Optional[modal.client._Client] = None,
|
|
468
473
|
) -> _Queue:
|
|
469
474
|
"""Reference a named Queue, creating if necessary.
|
|
470
475
|
|
|
@@ -606,8 +611,6 @@ class _Queue(modal._object._Object):
|
|
|
606
611
|
"""
|
|
607
612
|
...
|
|
608
613
|
|
|
609
|
-
SUPERSELF = typing.TypeVar("SUPERSELF", covariant=True)
|
|
610
|
-
|
|
611
614
|
class Queue(modal.object.Object):
|
|
612
615
|
"""Distributed, FIFO queue for data flow in Modal apps.
|
|
613
616
|
|
|
@@ -695,33 +698,66 @@ class Queue(modal.object.Object):
|
|
|
695
698
|
def _get_metadata(self) -> modal_proto.api_pb2.QueueMetadata: ...
|
|
696
699
|
@staticmethod
|
|
697
700
|
def validate_partition_key(partition: typing.Optional[str]) -> bytes: ...
|
|
698
|
-
@classmethod
|
|
699
|
-
def ephemeral(
|
|
700
|
-
cls: type[Queue],
|
|
701
|
-
client: typing.Optional[modal.client.Client] = None,
|
|
702
|
-
environment_name: typing.Optional[str] = None,
|
|
703
|
-
_heartbeat_sleep: float = 300,
|
|
704
|
-
) -> synchronicity.combined_types.AsyncAndBlockingContextManager[Queue]:
|
|
705
|
-
"""Creates a new ephemeral queue within a context manager:
|
|
706
701
|
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
702
|
+
class __ephemeral_spec(typing_extensions.Protocol):
|
|
703
|
+
def __call__(
|
|
704
|
+
self,
|
|
705
|
+
/,
|
|
706
|
+
client: typing.Optional[modal.client.Client] = None,
|
|
707
|
+
environment_name: typing.Optional[str] = None,
|
|
708
|
+
_heartbeat_sleep: float = 300,
|
|
709
|
+
) -> synchronicity.combined_types.AsyncAndBlockingContextManager[Queue]:
|
|
710
|
+
"""Creates a new ephemeral queue within a context manager:
|
|
710
711
|
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
712
|
+
Usage:
|
|
713
|
+
```python
|
|
714
|
+
from modal import Queue
|
|
714
715
|
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
716
|
+
with Queue.ephemeral() as q:
|
|
717
|
+
q.put(123)
|
|
718
|
+
```
|
|
719
|
+
|
|
720
|
+
```python notest
|
|
721
|
+
async with Queue.ephemeral() as q:
|
|
722
|
+
await q.put.aio(123)
|
|
723
|
+
```
|
|
724
|
+
"""
|
|
725
|
+
...
|
|
726
|
+
|
|
727
|
+
def aio(
|
|
728
|
+
self,
|
|
729
|
+
/,
|
|
730
|
+
client: typing.Optional[modal.client.Client] = None,
|
|
731
|
+
environment_name: typing.Optional[str] = None,
|
|
732
|
+
_heartbeat_sleep: float = 300,
|
|
733
|
+
) -> typing.AsyncContextManager[Queue]:
|
|
734
|
+
"""Creates a new ephemeral queue within a context manager:
|
|
735
|
+
|
|
736
|
+
Usage:
|
|
737
|
+
```python
|
|
738
|
+
from modal import Queue
|
|
739
|
+
|
|
740
|
+
with Queue.ephemeral() as q:
|
|
741
|
+
q.put(123)
|
|
742
|
+
```
|
|
743
|
+
|
|
744
|
+
```python notest
|
|
745
|
+
async with Queue.ephemeral() as q:
|
|
746
|
+
await q.put.aio(123)
|
|
747
|
+
```
|
|
748
|
+
"""
|
|
749
|
+
...
|
|
750
|
+
|
|
751
|
+
ephemeral: typing.ClassVar[__ephemeral_spec]
|
|
721
752
|
|
|
722
753
|
@staticmethod
|
|
723
754
|
def from_name(
|
|
724
|
-
name: str,
|
|
755
|
+
name: str,
|
|
756
|
+
*,
|
|
757
|
+
namespace=None,
|
|
758
|
+
environment_name: typing.Optional[str] = None,
|
|
759
|
+
create_if_missing: bool = False,
|
|
760
|
+
client: typing.Optional[modal.client.Client] = None,
|
|
725
761
|
) -> Queue:
|
|
726
762
|
"""Reference a named Queue, creating if necessary.
|
|
727
763
|
|
|
@@ -773,9 +809,9 @@ class Queue(modal.object.Object):
|
|
|
773
809
|
"""
|
|
774
810
|
...
|
|
775
811
|
|
|
776
|
-
delete: __delete_spec
|
|
812
|
+
delete: typing.ClassVar[__delete_spec]
|
|
777
813
|
|
|
778
|
-
class __info_spec(typing_extensions.Protocol
|
|
814
|
+
class __info_spec(typing_extensions.Protocol):
|
|
779
815
|
def __call__(self, /) -> QueueInfo:
|
|
780
816
|
"""Return information about the Queue object."""
|
|
781
817
|
...
|
|
@@ -784,15 +820,15 @@ class Queue(modal.object.Object):
|
|
|
784
820
|
"""Return information about the Queue object."""
|
|
785
821
|
...
|
|
786
822
|
|
|
787
|
-
info: __info_spec
|
|
823
|
+
info: __info_spec
|
|
788
824
|
|
|
789
|
-
class ___get_nonblocking_spec(typing_extensions.Protocol
|
|
825
|
+
class ___get_nonblocking_spec(typing_extensions.Protocol):
|
|
790
826
|
def __call__(self, /, partition: typing.Optional[str], n_values: int) -> list[typing.Any]: ...
|
|
791
827
|
async def aio(self, /, partition: typing.Optional[str], n_values: int) -> list[typing.Any]: ...
|
|
792
828
|
|
|
793
|
-
_get_nonblocking: ___get_nonblocking_spec
|
|
829
|
+
_get_nonblocking: ___get_nonblocking_spec
|
|
794
830
|
|
|
795
|
-
class ___get_blocking_spec(typing_extensions.Protocol
|
|
831
|
+
class ___get_blocking_spec(typing_extensions.Protocol):
|
|
796
832
|
def __call__(
|
|
797
833
|
self, /, partition: typing.Optional[str], timeout: typing.Optional[float], n_values: int
|
|
798
834
|
) -> list[typing.Any]: ...
|
|
@@ -800,9 +836,9 @@ class Queue(modal.object.Object):
|
|
|
800
836
|
self, /, partition: typing.Optional[str], timeout: typing.Optional[float], n_values: int
|
|
801
837
|
) -> list[typing.Any]: ...
|
|
802
838
|
|
|
803
|
-
_get_blocking: ___get_blocking_spec
|
|
839
|
+
_get_blocking: ___get_blocking_spec
|
|
804
840
|
|
|
805
|
-
class __clear_spec(typing_extensions.Protocol
|
|
841
|
+
class __clear_spec(typing_extensions.Protocol):
|
|
806
842
|
def __call__(self, /, *, partition: typing.Optional[str] = None, all: bool = False) -> None:
|
|
807
843
|
"""Clear the contents of a single partition or all partitions."""
|
|
808
844
|
...
|
|
@@ -811,9 +847,9 @@ class Queue(modal.object.Object):
|
|
|
811
847
|
"""Clear the contents of a single partition or all partitions."""
|
|
812
848
|
...
|
|
813
849
|
|
|
814
|
-
clear: __clear_spec
|
|
850
|
+
clear: __clear_spec
|
|
815
851
|
|
|
816
|
-
class __get_spec(typing_extensions.Protocol
|
|
852
|
+
class __get_spec(typing_extensions.Protocol):
|
|
817
853
|
def __call__(
|
|
818
854
|
self,
|
|
819
855
|
/,
|
|
@@ -852,9 +888,9 @@ class Queue(modal.object.Object):
|
|
|
852
888
|
"""
|
|
853
889
|
...
|
|
854
890
|
|
|
855
|
-
get: __get_spec
|
|
891
|
+
get: __get_spec
|
|
856
892
|
|
|
857
|
-
class __get_many_spec(typing_extensions.Protocol
|
|
893
|
+
class __get_many_spec(typing_extensions.Protocol):
|
|
858
894
|
def __call__(
|
|
859
895
|
self,
|
|
860
896
|
/,
|
|
@@ -899,9 +935,9 @@ class Queue(modal.object.Object):
|
|
|
899
935
|
"""
|
|
900
936
|
...
|
|
901
937
|
|
|
902
|
-
get_many: __get_many_spec
|
|
938
|
+
get_many: __get_many_spec
|
|
903
939
|
|
|
904
|
-
class __put_spec(typing_extensions.Protocol
|
|
940
|
+
class __put_spec(typing_extensions.Protocol):
|
|
905
941
|
def __call__(
|
|
906
942
|
self,
|
|
907
943
|
/,
|
|
@@ -944,9 +980,9 @@ class Queue(modal.object.Object):
|
|
|
944
980
|
"""
|
|
945
981
|
...
|
|
946
982
|
|
|
947
|
-
put: __put_spec
|
|
983
|
+
put: __put_spec
|
|
948
984
|
|
|
949
|
-
class __put_many_spec(typing_extensions.Protocol
|
|
985
|
+
class __put_many_spec(typing_extensions.Protocol):
|
|
950
986
|
def __call__(
|
|
951
987
|
self,
|
|
952
988
|
/,
|
|
@@ -989,9 +1025,9 @@ class Queue(modal.object.Object):
|
|
|
989
1025
|
"""
|
|
990
1026
|
...
|
|
991
1027
|
|
|
992
|
-
put_many: __put_many_spec
|
|
1028
|
+
put_many: __put_many_spec
|
|
993
1029
|
|
|
994
|
-
class ___put_many_blocking_spec(typing_extensions.Protocol
|
|
1030
|
+
class ___put_many_blocking_spec(typing_extensions.Protocol):
|
|
995
1031
|
def __call__(
|
|
996
1032
|
self,
|
|
997
1033
|
/,
|
|
@@ -1009,15 +1045,15 @@ class Queue(modal.object.Object):
|
|
|
1009
1045
|
timeout: typing.Optional[float] = None,
|
|
1010
1046
|
): ...
|
|
1011
1047
|
|
|
1012
|
-
_put_many_blocking: ___put_many_blocking_spec
|
|
1048
|
+
_put_many_blocking: ___put_many_blocking_spec
|
|
1013
1049
|
|
|
1014
|
-
class ___put_many_nonblocking_spec(typing_extensions.Protocol
|
|
1050
|
+
class ___put_many_nonblocking_spec(typing_extensions.Protocol):
|
|
1015
1051
|
def __call__(self, /, partition: typing.Optional[str], partition_ttl: int, vs: list[typing.Any]): ...
|
|
1016
1052
|
async def aio(self, /, partition: typing.Optional[str], partition_ttl: int, vs: list[typing.Any]): ...
|
|
1017
1053
|
|
|
1018
|
-
_put_many_nonblocking: ___put_many_nonblocking_spec
|
|
1054
|
+
_put_many_nonblocking: ___put_many_nonblocking_spec
|
|
1019
1055
|
|
|
1020
|
-
class __len_spec(typing_extensions.Protocol
|
|
1056
|
+
class __len_spec(typing_extensions.Protocol):
|
|
1021
1057
|
def __call__(self, /, *, partition: typing.Optional[str] = None, total: bool = False) -> int:
|
|
1022
1058
|
"""Return the number of objects in the queue partition."""
|
|
1023
1059
|
...
|
|
@@ -1026,9 +1062,9 @@ class Queue(modal.object.Object):
|
|
|
1026
1062
|
"""Return the number of objects in the queue partition."""
|
|
1027
1063
|
...
|
|
1028
1064
|
|
|
1029
|
-
len: __len_spec
|
|
1065
|
+
len: __len_spec
|
|
1030
1066
|
|
|
1031
|
-
class __iterate_spec(typing_extensions.Protocol
|
|
1067
|
+
class __iterate_spec(typing_extensions.Protocol):
|
|
1032
1068
|
def __call__(
|
|
1033
1069
|
self, /, *, partition: typing.Optional[str] = None, item_poll_timeout: float = 0.0
|
|
1034
1070
|
) -> typing.Generator[typing.Any, None, None]:
|
|
@@ -1047,4 +1083,4 @@ class Queue(modal.object.Object):
|
|
|
1047
1083
|
"""
|
|
1048
1084
|
...
|
|
1049
1085
|
|
|
1050
|
-
iterate: __iterate_spec
|
|
1086
|
+
iterate: __iterate_spec
|