modal 1.1.1.dev41__py3-none-any.whl → 1.1.2__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/__main__.py +1 -2
- modal/_container_entrypoint.py +18 -7
- modal/_functions.py +135 -13
- modal/_object.py +13 -2
- modal/_partial_function.py +8 -8
- modal/_runtime/asgi.py +3 -2
- modal/_runtime/container_io_manager.py +20 -14
- modal/_runtime/container_io_manager.pyi +38 -13
- modal/_runtime/execution_context.py +18 -2
- modal/_runtime/execution_context.pyi +4 -1
- modal/_runtime/gpu_memory_snapshot.py +158 -54
- modal/_utils/blob_utils.py +83 -24
- modal/_utils/function_utils.py +4 -3
- modal/_utils/time_utils.py +28 -4
- modal/app.py +8 -4
- modal/app.pyi +8 -8
- modal/cli/dict.py +14 -11
- modal/cli/entry_point.py +9 -3
- modal/cli/launch.py +102 -4
- modal/cli/profile.py +1 -0
- modal/cli/programs/launch_instance_ssh.py +94 -0
- modal/cli/programs/run_marimo.py +95 -0
- modal/cli/queues.py +49 -19
- modal/cli/secret.py +45 -18
- modal/cli/volume.py +14 -16
- modal/client.pyi +2 -10
- modal/cls.py +12 -2
- modal/cls.pyi +9 -1
- modal/config.py +7 -7
- modal/dict.py +206 -12
- modal/dict.pyi +358 -4
- modal/experimental/__init__.py +130 -0
- modal/file_io.py +1 -1
- modal/file_io.pyi +2 -2
- modal/file_pattern_matcher.py +25 -16
- modal/functions.pyi +111 -11
- modal/image.py +9 -3
- modal/image.pyi +7 -7
- modal/mount.py +20 -13
- modal/mount.pyi +16 -3
- modal/network_file_system.py +8 -2
- modal/object.pyi +3 -0
- modal/parallel_map.py +346 -101
- modal/parallel_map.pyi +108 -0
- modal/proxy.py +2 -1
- modal/queue.py +199 -9
- modal/queue.pyi +357 -3
- modal/sandbox.py +6 -5
- modal/sandbox.pyi +17 -14
- modal/secret.py +196 -3
- modal/secret.pyi +372 -0
- modal/volume.py +239 -23
- modal/volume.pyi +405 -10
- {modal-1.1.1.dev41.dist-info → modal-1.1.2.dist-info}/METADATA +2 -2
- {modal-1.1.1.dev41.dist-info → modal-1.1.2.dist-info}/RECORD +68 -66
- modal_docs/mdmd/mdmd.py +11 -1
- modal_proto/api.proto +37 -10
- modal_proto/api_grpc.py +32 -0
- modal_proto/api_pb2.py +627 -597
- modal_proto/api_pb2.pyi +107 -19
- modal_proto/api_pb2_grpc.py +67 -2
- modal_proto/api_pb2_grpc.pyi +24 -8
- modal_proto/modal_api_grpc.py +2 -0
- modal_version/__init__.py +1 -1
- {modal-1.1.1.dev41.dist-info → modal-1.1.2.dist-info}/WHEEL +0 -0
- {modal-1.1.1.dev41.dist-info → modal-1.1.2.dist-info}/entry_points.txt +0 -0
- {modal-1.1.1.dev41.dist-info → modal-1.1.2.dist-info}/licenses/LICENSE +0 -0
- {modal-1.1.1.dev41.dist-info → modal-1.1.2.dist-info}/top_level.txt +0 -0
modal/queue.py
CHANGED
|
@@ -5,24 +5,31 @@ import warnings
|
|
|
5
5
|
from collections.abc import AsyncGenerator, AsyncIterator
|
|
6
6
|
from dataclasses import dataclass
|
|
7
7
|
from datetime import datetime
|
|
8
|
-
from typing import Any, Optional
|
|
8
|
+
from typing import Any, Optional, Union
|
|
9
9
|
|
|
10
10
|
from google.protobuf.message import Message
|
|
11
11
|
from grpclib import GRPCError, Status
|
|
12
|
+
from synchronicity import classproperty
|
|
12
13
|
from synchronicity.async_wrap import asynccontextmanager
|
|
13
14
|
|
|
14
15
|
from modal_proto import api_pb2
|
|
15
16
|
|
|
16
|
-
from ._object import
|
|
17
|
+
from ._object import (
|
|
18
|
+
EPHEMERAL_OBJECT_HEARTBEAT_SLEEP,
|
|
19
|
+
_get_environment_name,
|
|
20
|
+
_Object,
|
|
21
|
+
live_method,
|
|
22
|
+
live_method_gen,
|
|
23
|
+
)
|
|
17
24
|
from ._resolver import Resolver
|
|
18
25
|
from ._serialization import deserialize, serialize
|
|
19
26
|
from ._utils.async_utils import TaskContext, synchronize_api, warn_if_generator_is_not_consumed
|
|
20
27
|
from ._utils.deprecation import deprecation_warning, warn_if_passing_namespace
|
|
21
28
|
from ._utils.grpc_utils import retry_transient_errors
|
|
22
29
|
from ._utils.name_utils import check_object_name
|
|
23
|
-
from ._utils.time_utils import timestamp_to_localized_dt
|
|
30
|
+
from ._utils.time_utils import as_timestamp, timestamp_to_localized_dt
|
|
24
31
|
from .client import _Client
|
|
25
|
-
from .exception import InvalidError, RequestSizeError
|
|
32
|
+
from .exception import AlreadyExistsError, InvalidError, NotFoundError, RequestSizeError
|
|
26
33
|
|
|
27
34
|
|
|
28
35
|
@dataclass
|
|
@@ -37,6 +44,173 @@ class QueueInfo:
|
|
|
37
44
|
created_by: Optional[str]
|
|
38
45
|
|
|
39
46
|
|
|
47
|
+
class _QueueManager:
|
|
48
|
+
"""Namespace with methods for managing named Queue objects."""
|
|
49
|
+
|
|
50
|
+
@staticmethod
|
|
51
|
+
async def create(
|
|
52
|
+
name: str, # Name to use for the new Queue
|
|
53
|
+
*,
|
|
54
|
+
allow_existing: bool = False, # If True, no-op when the Queue already exists
|
|
55
|
+
environment_name: Optional[str] = None, # Uses active environment if not specified
|
|
56
|
+
client: Optional[_Client] = None, # Optional client with Modal credentials
|
|
57
|
+
) -> None:
|
|
58
|
+
"""Create a new Queue object.
|
|
59
|
+
|
|
60
|
+
**Examples:**
|
|
61
|
+
|
|
62
|
+
```python notest
|
|
63
|
+
modal.Queue.objects.create("my-queue")
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Queues will be created in the active environment, or another one can be specified:
|
|
67
|
+
|
|
68
|
+
```python notest
|
|
69
|
+
modal.Queue.objects.create("my-queue", environment_name="dev")
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
By default, an error will be raised if the Queue already exists, but passing
|
|
73
|
+
`allow_existing=True` will make the creation attempt a no-op in this case.
|
|
74
|
+
|
|
75
|
+
```python notest
|
|
76
|
+
modal.Queue.objects.create("my-queue", allow_existing=True)
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Note that this method does not return a local instance of the Queue. You can use
|
|
80
|
+
`modal.Queue.from_name` to perform a lookup after creation.
|
|
81
|
+
|
|
82
|
+
Added in v1.1.2.
|
|
83
|
+
|
|
84
|
+
"""
|
|
85
|
+
check_object_name(name, "Queue")
|
|
86
|
+
client = await _Client.from_env() if client is None else client
|
|
87
|
+
object_creation_type = (
|
|
88
|
+
api_pb2.OBJECT_CREATION_TYPE_CREATE_IF_MISSING
|
|
89
|
+
if allow_existing
|
|
90
|
+
else api_pb2.OBJECT_CREATION_TYPE_CREATE_FAIL_IF_EXISTS
|
|
91
|
+
)
|
|
92
|
+
req = api_pb2.QueueGetOrCreateRequest(
|
|
93
|
+
deployment_name=name,
|
|
94
|
+
environment_name=_get_environment_name(environment_name),
|
|
95
|
+
object_creation_type=object_creation_type,
|
|
96
|
+
)
|
|
97
|
+
try:
|
|
98
|
+
await retry_transient_errors(client.stub.QueueGetOrCreate, req)
|
|
99
|
+
except GRPCError as exc:
|
|
100
|
+
if exc.status == Status.ALREADY_EXISTS and not allow_existing:
|
|
101
|
+
raise AlreadyExistsError(exc.message)
|
|
102
|
+
else:
|
|
103
|
+
raise
|
|
104
|
+
|
|
105
|
+
@staticmethod
|
|
106
|
+
async def list(
|
|
107
|
+
*,
|
|
108
|
+
max_objects: Optional[int] = None, # Limit results to this size
|
|
109
|
+
created_before: Optional[Union[datetime, str]] = None, # Limit based on creation date
|
|
110
|
+
environment_name: str = "", # Uses active environment if not specified
|
|
111
|
+
client: Optional[_Client] = None, # Optional client with Modal credentials
|
|
112
|
+
) -> list["_Queue"]:
|
|
113
|
+
"""Return a list of hydrated Queue objects.
|
|
114
|
+
|
|
115
|
+
**Examples:**
|
|
116
|
+
|
|
117
|
+
```python
|
|
118
|
+
queues = modal.Queue.objects.list()
|
|
119
|
+
print([q.name for q in queues])
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Queues will be retreived from the active environment, or another one can be specified:
|
|
123
|
+
|
|
124
|
+
```python notest
|
|
125
|
+
dev_queues = modal.Queue.objects.list(environment_name="dev")
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
By default, all named Queues are returned, newest to oldest. It's also possible to limit the
|
|
129
|
+
number of results and to filter by creation date:
|
|
130
|
+
|
|
131
|
+
```python
|
|
132
|
+
queues = modal.Queue.objects.list(max_objects=10, created_before="2025-01-01")
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Added in v1.1.2.
|
|
136
|
+
|
|
137
|
+
"""
|
|
138
|
+
client = await _Client.from_env() if client is None else client
|
|
139
|
+
if max_objects is not None and max_objects < 0:
|
|
140
|
+
raise InvalidError("max_objects cannot be negative")
|
|
141
|
+
|
|
142
|
+
items: list[api_pb2.QueueListResponse.QueueInfo] = []
|
|
143
|
+
|
|
144
|
+
async def retrieve_page(created_before: float) -> bool:
|
|
145
|
+
max_page_size = 100 if max_objects is None else min(100, max_objects - len(items))
|
|
146
|
+
pagination = api_pb2.ListPagination(max_objects=max_page_size, created_before=created_before)
|
|
147
|
+
req = api_pb2.QueueListRequest(
|
|
148
|
+
environment_name=_get_environment_name(environment_name), pagination=pagination
|
|
149
|
+
)
|
|
150
|
+
resp = await retry_transient_errors(client.stub.QueueList, req)
|
|
151
|
+
items.extend(resp.queues)
|
|
152
|
+
finished = (len(resp.queues) < max_page_size) or (max_objects is not None and len(items) >= max_objects)
|
|
153
|
+
return finished
|
|
154
|
+
|
|
155
|
+
finished = await retrieve_page(as_timestamp(created_before))
|
|
156
|
+
while True:
|
|
157
|
+
if finished:
|
|
158
|
+
break
|
|
159
|
+
finished = await retrieve_page(items[-1].metadata.creation_info.created_at)
|
|
160
|
+
|
|
161
|
+
queues = [
|
|
162
|
+
_Queue._new_hydrated(
|
|
163
|
+
item.queue_id,
|
|
164
|
+
client,
|
|
165
|
+
item.metadata,
|
|
166
|
+
is_another_app=True,
|
|
167
|
+
rep=_Queue._repr(item.name, environment_name),
|
|
168
|
+
)
|
|
169
|
+
for item in items
|
|
170
|
+
]
|
|
171
|
+
return queues[:max_objects] if max_objects is not None else queues
|
|
172
|
+
|
|
173
|
+
@staticmethod
|
|
174
|
+
async def delete(
|
|
175
|
+
name: str, # Name of the Queue to delete
|
|
176
|
+
*,
|
|
177
|
+
allow_missing: bool = False, # If True, don't raise an error if the Queue doesn't exist
|
|
178
|
+
environment_name: Optional[str] = None, # Uses active environment if not specified
|
|
179
|
+
client: Optional[_Client] = None, # Optional client with Modal credentials
|
|
180
|
+
):
|
|
181
|
+
"""Delete a named Queue.
|
|
182
|
+
|
|
183
|
+
Warning: This deletes an *entire Queue*, not just a specific entry or partition.
|
|
184
|
+
Deletion is irreversible and will affect any Apps currently using the Queue.
|
|
185
|
+
|
|
186
|
+
**Examples:**
|
|
187
|
+
|
|
188
|
+
```python notest
|
|
189
|
+
await modal.Queue.objects.delete("my-queue")
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Queues will be deleted from the active environment, or another one can be specified:
|
|
193
|
+
|
|
194
|
+
```python notest
|
|
195
|
+
await modal.Queue.objects.delete("my-queue", environment_name="dev")
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Added in v1.1.2.
|
|
199
|
+
|
|
200
|
+
"""
|
|
201
|
+
try:
|
|
202
|
+
obj = await _Queue.from_name(name, environment_name=environment_name).hydrate(client)
|
|
203
|
+
except NotFoundError:
|
|
204
|
+
if not allow_missing:
|
|
205
|
+
raise
|
|
206
|
+
else:
|
|
207
|
+
req = api_pb2.QueueDeleteRequest(queue_id=obj.object_id)
|
|
208
|
+
await retry_transient_errors(obj._client.stub.QueueDelete, req)
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
QueueManager = synchronize_api(_QueueManager)
|
|
212
|
+
|
|
213
|
+
|
|
40
214
|
class _Queue(_Object, type_prefix="qu"):
|
|
41
215
|
"""Distributed, FIFO queue for data flow in Modal apps.
|
|
42
216
|
|
|
@@ -116,6 +290,10 @@ class _Queue(_Object, type_prefix="qu"):
|
|
|
116
290
|
"""mdmd:hidden"""
|
|
117
291
|
raise RuntimeError("Queue() is not allowed. Please use `Queue.from_name(...)` or `Queue.ephemeral()` instead.")
|
|
118
292
|
|
|
293
|
+
@classproperty
|
|
294
|
+
def objects(cls) -> _QueueManager:
|
|
295
|
+
return _QueueManager
|
|
296
|
+
|
|
119
297
|
@property
|
|
120
298
|
def name(self) -> Optional[str]:
|
|
121
299
|
return self._name
|
|
@@ -147,7 +325,7 @@ class _Queue(_Object, type_prefix="qu"):
|
|
|
147
325
|
cls: type["_Queue"],
|
|
148
326
|
client: Optional[_Client] = None,
|
|
149
327
|
environment_name: Optional[str] = None,
|
|
150
|
-
_heartbeat_sleep: float = EPHEMERAL_OBJECT_HEARTBEAT_SLEEP,
|
|
328
|
+
_heartbeat_sleep: float = EPHEMERAL_OBJECT_HEARTBEAT_SLEEP, # mdmd:line-hidden
|
|
151
329
|
) -> AsyncIterator["_Queue"]:
|
|
152
330
|
"""Creates a new ephemeral queue within a context manager:
|
|
153
331
|
|
|
@@ -207,7 +385,8 @@ class _Queue(_Object, type_prefix="qu"):
|
|
|
207
385
|
response = await resolver.client.stub.QueueGetOrCreate(req)
|
|
208
386
|
self._hydrate(response.queue_id, resolver.client, response.metadata)
|
|
209
387
|
|
|
210
|
-
|
|
388
|
+
rep = _Queue._repr(name, environment_name)
|
|
389
|
+
return _Queue._from_loader(_load, rep, is_another_app=True, hydrate_lazily=True, name=name)
|
|
211
390
|
|
|
212
391
|
@staticmethod
|
|
213
392
|
async def lookup(
|
|
@@ -250,9 +429,20 @@ class _Queue(_Object, type_prefix="qu"):
|
|
|
250
429
|
|
|
251
430
|
@staticmethod
|
|
252
431
|
async def delete(name: str, *, client: Optional[_Client] = None, environment_name: Optional[str] = None):
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
432
|
+
"""mdmd:hidden
|
|
433
|
+
Delete a named Queue.
|
|
434
|
+
|
|
435
|
+
Warning: This deletes an *entire Queue*, not just a specific entry or partition.
|
|
436
|
+
Deletion is irreversible and will affect any Apps currently using the Queue.
|
|
437
|
+
|
|
438
|
+
DEPRECATED: This method is deprecated; we recommend using `modal.Queue.objects.delete` instead.
|
|
439
|
+
|
|
440
|
+
"""
|
|
441
|
+
deprecation_warning(
|
|
442
|
+
(2025, 8, 6),
|
|
443
|
+
"`modal.Queue.delete` is deprecated; we recommend using `modal.Queue.objects.delete` instead.",
|
|
444
|
+
)
|
|
445
|
+
await _Queue.objects.delete(name, environment_name=environment_name, client=client)
|
|
256
446
|
|
|
257
447
|
@live_method
|
|
258
448
|
async def info(self) -> QueueInfo:
|
modal/queue.pyi
CHANGED
|
@@ -5,6 +5,7 @@ import modal._object
|
|
|
5
5
|
import modal.client
|
|
6
6
|
import modal.object
|
|
7
7
|
import modal_proto.api_pb2
|
|
8
|
+
import synchronicity
|
|
8
9
|
import synchronicity.combined_types
|
|
9
10
|
import typing
|
|
10
11
|
import typing_extensions
|
|
@@ -30,6 +31,326 @@ class QueueInfo:
|
|
|
30
31
|
"""Return self==value."""
|
|
31
32
|
...
|
|
32
33
|
|
|
34
|
+
class _QueueManager:
|
|
35
|
+
"""Namespace with methods for managing named Queue objects."""
|
|
36
|
+
@staticmethod
|
|
37
|
+
async def create(
|
|
38
|
+
name: str,
|
|
39
|
+
*,
|
|
40
|
+
allow_existing: bool = False,
|
|
41
|
+
environment_name: typing.Optional[str] = None,
|
|
42
|
+
client: typing.Optional[modal.client._Client] = None,
|
|
43
|
+
) -> None:
|
|
44
|
+
"""Create a new Queue object.
|
|
45
|
+
|
|
46
|
+
**Examples:**
|
|
47
|
+
|
|
48
|
+
```python notest
|
|
49
|
+
modal.Queue.objects.create("my-queue")
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Queues will be created in the active environment, or another one can be specified:
|
|
53
|
+
|
|
54
|
+
```python notest
|
|
55
|
+
modal.Queue.objects.create("my-queue", environment_name="dev")
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
By default, an error will be raised if the Queue already exists, but passing
|
|
59
|
+
`allow_existing=True` will make the creation attempt a no-op in this case.
|
|
60
|
+
|
|
61
|
+
```python notest
|
|
62
|
+
modal.Queue.objects.create("my-queue", allow_existing=True)
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Note that this method does not return a local instance of the Queue. You can use
|
|
66
|
+
`modal.Queue.from_name` to perform a lookup after creation.
|
|
67
|
+
|
|
68
|
+
Added in v1.1.2.
|
|
69
|
+
"""
|
|
70
|
+
...
|
|
71
|
+
|
|
72
|
+
@staticmethod
|
|
73
|
+
async def list(
|
|
74
|
+
*,
|
|
75
|
+
max_objects: typing.Optional[int] = None,
|
|
76
|
+
created_before: typing.Union[datetime.datetime, str, None] = None,
|
|
77
|
+
environment_name: str = "",
|
|
78
|
+
client: typing.Optional[modal.client._Client] = None,
|
|
79
|
+
) -> list[_Queue]:
|
|
80
|
+
"""Return a list of hydrated Queue objects.
|
|
81
|
+
|
|
82
|
+
**Examples:**
|
|
83
|
+
|
|
84
|
+
```python
|
|
85
|
+
queues = modal.Queue.objects.list()
|
|
86
|
+
print([q.name for q in queues])
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Queues will be retreived from the active environment, or another one can be specified:
|
|
90
|
+
|
|
91
|
+
```python notest
|
|
92
|
+
dev_queues = modal.Queue.objects.list(environment_name="dev")
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
By default, all named Queues are returned, newest to oldest. It's also possible to limit the
|
|
96
|
+
number of results and to filter by creation date:
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
queues = modal.Queue.objects.list(max_objects=10, created_before="2025-01-01")
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Added in v1.1.2.
|
|
103
|
+
"""
|
|
104
|
+
...
|
|
105
|
+
|
|
106
|
+
@staticmethod
|
|
107
|
+
async def delete(
|
|
108
|
+
name: str,
|
|
109
|
+
*,
|
|
110
|
+
allow_missing: bool = False,
|
|
111
|
+
environment_name: typing.Optional[str] = None,
|
|
112
|
+
client: typing.Optional[modal.client._Client] = None,
|
|
113
|
+
):
|
|
114
|
+
"""Delete a named Queue.
|
|
115
|
+
|
|
116
|
+
Warning: This deletes an *entire Queue*, not just a specific entry or partition.
|
|
117
|
+
Deletion is irreversible and will affect any Apps currently using the Queue.
|
|
118
|
+
|
|
119
|
+
**Examples:**
|
|
120
|
+
|
|
121
|
+
```python notest
|
|
122
|
+
await modal.Queue.objects.delete("my-queue")
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Queues will be deleted from the active environment, or another one can be specified:
|
|
126
|
+
|
|
127
|
+
```python notest
|
|
128
|
+
await modal.Queue.objects.delete("my-queue", environment_name="dev")
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Added in v1.1.2.
|
|
132
|
+
"""
|
|
133
|
+
...
|
|
134
|
+
|
|
135
|
+
class QueueManager:
|
|
136
|
+
"""Namespace with methods for managing named Queue objects."""
|
|
137
|
+
def __init__(self, /, *args, **kwargs):
|
|
138
|
+
"""Initialize self. See help(type(self)) for accurate signature."""
|
|
139
|
+
...
|
|
140
|
+
|
|
141
|
+
class __create_spec(typing_extensions.Protocol):
|
|
142
|
+
def __call__(
|
|
143
|
+
self,
|
|
144
|
+
/,
|
|
145
|
+
name: str,
|
|
146
|
+
*,
|
|
147
|
+
allow_existing: bool = False,
|
|
148
|
+
environment_name: typing.Optional[str] = None,
|
|
149
|
+
client: typing.Optional[modal.client.Client] = None,
|
|
150
|
+
) -> None:
|
|
151
|
+
"""Create a new Queue object.
|
|
152
|
+
|
|
153
|
+
**Examples:**
|
|
154
|
+
|
|
155
|
+
```python notest
|
|
156
|
+
modal.Queue.objects.create("my-queue")
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Queues will be created in the active environment, or another one can be specified:
|
|
160
|
+
|
|
161
|
+
```python notest
|
|
162
|
+
modal.Queue.objects.create("my-queue", environment_name="dev")
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
By default, an error will be raised if the Queue already exists, but passing
|
|
166
|
+
`allow_existing=True` will make the creation attempt a no-op in this case.
|
|
167
|
+
|
|
168
|
+
```python notest
|
|
169
|
+
modal.Queue.objects.create("my-queue", allow_existing=True)
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Note that this method does not return a local instance of the Queue. You can use
|
|
173
|
+
`modal.Queue.from_name` to perform a lookup after creation.
|
|
174
|
+
|
|
175
|
+
Added in v1.1.2.
|
|
176
|
+
"""
|
|
177
|
+
...
|
|
178
|
+
|
|
179
|
+
async def aio(
|
|
180
|
+
self,
|
|
181
|
+
/,
|
|
182
|
+
name: str,
|
|
183
|
+
*,
|
|
184
|
+
allow_existing: bool = False,
|
|
185
|
+
environment_name: typing.Optional[str] = None,
|
|
186
|
+
client: typing.Optional[modal.client.Client] = None,
|
|
187
|
+
) -> None:
|
|
188
|
+
"""Create a new Queue object.
|
|
189
|
+
|
|
190
|
+
**Examples:**
|
|
191
|
+
|
|
192
|
+
```python notest
|
|
193
|
+
modal.Queue.objects.create("my-queue")
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Queues will be created in the active environment, or another one can be specified:
|
|
197
|
+
|
|
198
|
+
```python notest
|
|
199
|
+
modal.Queue.objects.create("my-queue", environment_name="dev")
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
By default, an error will be raised if the Queue already exists, but passing
|
|
203
|
+
`allow_existing=True` will make the creation attempt a no-op in this case.
|
|
204
|
+
|
|
205
|
+
```python notest
|
|
206
|
+
modal.Queue.objects.create("my-queue", allow_existing=True)
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
Note that this method does not return a local instance of the Queue. You can use
|
|
210
|
+
`modal.Queue.from_name` to perform a lookup after creation.
|
|
211
|
+
|
|
212
|
+
Added in v1.1.2.
|
|
213
|
+
"""
|
|
214
|
+
...
|
|
215
|
+
|
|
216
|
+
create: __create_spec
|
|
217
|
+
|
|
218
|
+
class __list_spec(typing_extensions.Protocol):
|
|
219
|
+
def __call__(
|
|
220
|
+
self,
|
|
221
|
+
/,
|
|
222
|
+
*,
|
|
223
|
+
max_objects: typing.Optional[int] = None,
|
|
224
|
+
created_before: typing.Union[datetime.datetime, str, None] = None,
|
|
225
|
+
environment_name: str = "",
|
|
226
|
+
client: typing.Optional[modal.client.Client] = None,
|
|
227
|
+
) -> list[Queue]:
|
|
228
|
+
"""Return a list of hydrated Queue objects.
|
|
229
|
+
|
|
230
|
+
**Examples:**
|
|
231
|
+
|
|
232
|
+
```python
|
|
233
|
+
queues = modal.Queue.objects.list()
|
|
234
|
+
print([q.name for q in queues])
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
Queues will be retreived from the active environment, or another one can be specified:
|
|
238
|
+
|
|
239
|
+
```python notest
|
|
240
|
+
dev_queues = modal.Queue.objects.list(environment_name="dev")
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
By default, all named Queues are returned, newest to oldest. It's also possible to limit the
|
|
244
|
+
number of results and to filter by creation date:
|
|
245
|
+
|
|
246
|
+
```python
|
|
247
|
+
queues = modal.Queue.objects.list(max_objects=10, created_before="2025-01-01")
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
Added in v1.1.2.
|
|
251
|
+
"""
|
|
252
|
+
...
|
|
253
|
+
|
|
254
|
+
async def aio(
|
|
255
|
+
self,
|
|
256
|
+
/,
|
|
257
|
+
*,
|
|
258
|
+
max_objects: typing.Optional[int] = None,
|
|
259
|
+
created_before: typing.Union[datetime.datetime, str, None] = None,
|
|
260
|
+
environment_name: str = "",
|
|
261
|
+
client: typing.Optional[modal.client.Client] = None,
|
|
262
|
+
) -> list[Queue]:
|
|
263
|
+
"""Return a list of hydrated Queue objects.
|
|
264
|
+
|
|
265
|
+
**Examples:**
|
|
266
|
+
|
|
267
|
+
```python
|
|
268
|
+
queues = modal.Queue.objects.list()
|
|
269
|
+
print([q.name for q in queues])
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
Queues will be retreived from the active environment, or another one can be specified:
|
|
273
|
+
|
|
274
|
+
```python notest
|
|
275
|
+
dev_queues = modal.Queue.objects.list(environment_name="dev")
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
By default, all named Queues are returned, newest to oldest. It's also possible to limit the
|
|
279
|
+
number of results and to filter by creation date:
|
|
280
|
+
|
|
281
|
+
```python
|
|
282
|
+
queues = modal.Queue.objects.list(max_objects=10, created_before="2025-01-01")
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
Added in v1.1.2.
|
|
286
|
+
"""
|
|
287
|
+
...
|
|
288
|
+
|
|
289
|
+
list: __list_spec
|
|
290
|
+
|
|
291
|
+
class __delete_spec(typing_extensions.Protocol):
|
|
292
|
+
def __call__(
|
|
293
|
+
self,
|
|
294
|
+
/,
|
|
295
|
+
name: str,
|
|
296
|
+
*,
|
|
297
|
+
allow_missing: bool = False,
|
|
298
|
+
environment_name: typing.Optional[str] = None,
|
|
299
|
+
client: typing.Optional[modal.client.Client] = None,
|
|
300
|
+
):
|
|
301
|
+
"""Delete a named Queue.
|
|
302
|
+
|
|
303
|
+
Warning: This deletes an *entire Queue*, not just a specific entry or partition.
|
|
304
|
+
Deletion is irreversible and will affect any Apps currently using the Queue.
|
|
305
|
+
|
|
306
|
+
**Examples:**
|
|
307
|
+
|
|
308
|
+
```python notest
|
|
309
|
+
await modal.Queue.objects.delete("my-queue")
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
Queues will be deleted from the active environment, or another one can be specified:
|
|
313
|
+
|
|
314
|
+
```python notest
|
|
315
|
+
await modal.Queue.objects.delete("my-queue", environment_name="dev")
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
Added in v1.1.2.
|
|
319
|
+
"""
|
|
320
|
+
...
|
|
321
|
+
|
|
322
|
+
async def aio(
|
|
323
|
+
self,
|
|
324
|
+
/,
|
|
325
|
+
name: str,
|
|
326
|
+
*,
|
|
327
|
+
allow_missing: bool = False,
|
|
328
|
+
environment_name: typing.Optional[str] = None,
|
|
329
|
+
client: typing.Optional[modal.client.Client] = None,
|
|
330
|
+
):
|
|
331
|
+
"""Delete a named Queue.
|
|
332
|
+
|
|
333
|
+
Warning: This deletes an *entire Queue*, not just a specific entry or partition.
|
|
334
|
+
Deletion is irreversible and will affect any Apps currently using the Queue.
|
|
335
|
+
|
|
336
|
+
**Examples:**
|
|
337
|
+
|
|
338
|
+
```python notest
|
|
339
|
+
await modal.Queue.objects.delete("my-queue")
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
Queues will be deleted from the active environment, or another one can be specified:
|
|
343
|
+
|
|
344
|
+
```python notest
|
|
345
|
+
await modal.Queue.objects.delete("my-queue", environment_name="dev")
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
Added in v1.1.2.
|
|
349
|
+
"""
|
|
350
|
+
...
|
|
351
|
+
|
|
352
|
+
delete: __delete_spec
|
|
353
|
+
|
|
33
354
|
class _Queue(modal._object._Object):
|
|
34
355
|
"""Distributed, FIFO queue for data flow in Modal apps.
|
|
35
356
|
|
|
@@ -109,6 +430,8 @@ class _Queue(modal._object._Object):
|
|
|
109
430
|
"""mdmd:hidden"""
|
|
110
431
|
...
|
|
111
432
|
|
|
433
|
+
@synchronicity.classproperty
|
|
434
|
+
def objects(cls) -> _QueueManager: ...
|
|
112
435
|
@property
|
|
113
436
|
def name(self) -> typing.Optional[str]: ...
|
|
114
437
|
def _hydrate_metadata(self, metadata: typing.Optional[google.protobuf.message.Message]): ...
|
|
@@ -185,7 +508,17 @@ class _Queue(modal._object._Object):
|
|
|
185
508
|
*,
|
|
186
509
|
client: typing.Optional[modal.client._Client] = None,
|
|
187
510
|
environment_name: typing.Optional[str] = None,
|
|
188
|
-
):
|
|
511
|
+
):
|
|
512
|
+
"""mdmd:hidden
|
|
513
|
+
Delete a named Queue.
|
|
514
|
+
|
|
515
|
+
Warning: This deletes an *entire Queue*, not just a specific entry or partition.
|
|
516
|
+
Deletion is irreversible and will affect any Apps currently using the Queue.
|
|
517
|
+
|
|
518
|
+
DEPRECATED: This method is deprecated; we recommend using `modal.Queue.objects.delete` instead.
|
|
519
|
+
"""
|
|
520
|
+
...
|
|
521
|
+
|
|
189
522
|
async def info(self) -> QueueInfo:
|
|
190
523
|
"""Return information about the Queue object."""
|
|
191
524
|
...
|
|
@@ -377,6 +710,8 @@ class Queue(modal.object.Object):
|
|
|
377
710
|
"""mdmd:hidden"""
|
|
378
711
|
...
|
|
379
712
|
|
|
713
|
+
@synchronicity.classproperty
|
|
714
|
+
def objects(cls) -> QueueManager: ...
|
|
380
715
|
@property
|
|
381
716
|
def name(self) -> typing.Optional[str]: ...
|
|
382
717
|
def _hydrate_metadata(self, metadata: typing.Optional[google.protobuf.message.Message]): ...
|
|
@@ -483,7 +818,17 @@ class Queue(modal.object.Object):
|
|
|
483
818
|
*,
|
|
484
819
|
client: typing.Optional[modal.client.Client] = None,
|
|
485
820
|
environment_name: typing.Optional[str] = None,
|
|
486
|
-
):
|
|
821
|
+
):
|
|
822
|
+
"""mdmd:hidden
|
|
823
|
+
Delete a named Queue.
|
|
824
|
+
|
|
825
|
+
Warning: This deletes an *entire Queue*, not just a specific entry or partition.
|
|
826
|
+
Deletion is irreversible and will affect any Apps currently using the Queue.
|
|
827
|
+
|
|
828
|
+
DEPRECATED: This method is deprecated; we recommend using `modal.Queue.objects.delete` instead.
|
|
829
|
+
"""
|
|
830
|
+
...
|
|
831
|
+
|
|
487
832
|
async def aio(
|
|
488
833
|
self,
|
|
489
834
|
/,
|
|
@@ -491,7 +836,16 @@ class Queue(modal.object.Object):
|
|
|
491
836
|
*,
|
|
492
837
|
client: typing.Optional[modal.client.Client] = None,
|
|
493
838
|
environment_name: typing.Optional[str] = None,
|
|
494
|
-
):
|
|
839
|
+
):
|
|
840
|
+
"""mdmd:hidden
|
|
841
|
+
Delete a named Queue.
|
|
842
|
+
|
|
843
|
+
Warning: This deletes an *entire Queue*, not just a specific entry or partition.
|
|
844
|
+
Deletion is irreversible and will affect any Apps currently using the Queue.
|
|
845
|
+
|
|
846
|
+
DEPRECATED: This method is deprecated; we recommend using `modal.Queue.objects.delete` instead.
|
|
847
|
+
"""
|
|
848
|
+
...
|
|
495
849
|
|
|
496
850
|
delete: __delete_spec
|
|
497
851
|
|
modal/sandbox.py
CHANGED
|
@@ -108,7 +108,7 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
108
108
|
image: _Image,
|
|
109
109
|
secrets: Sequence[_Secret],
|
|
110
110
|
name: Optional[str] = None,
|
|
111
|
-
timeout:
|
|
111
|
+
timeout: int = 300,
|
|
112
112
|
workdir: Optional[str] = None,
|
|
113
113
|
gpu: GPU_T = None,
|
|
114
114
|
cloud: Optional[str] = None,
|
|
@@ -257,7 +257,7 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
257
257
|
image: Optional[_Image] = None, # The image to run as the container for the sandbox.
|
|
258
258
|
secrets: Sequence[_Secret] = (), # Environment variables to inject into the sandbox.
|
|
259
259
|
network_file_systems: dict[Union[str, os.PathLike], _NetworkFileSystem] = {},
|
|
260
|
-
timeout:
|
|
260
|
+
timeout: int = 300, # Maximum execution time of the sandbox in seconds.
|
|
261
261
|
workdir: Optional[str] = None, # Working directory of the sandbox.
|
|
262
262
|
gpu: GPU_T = None,
|
|
263
263
|
cloud: Optional[str] = None,
|
|
@@ -296,8 +296,9 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
296
296
|
environment_name: Optional[str] = None, # *DEPRECATED* Optionally override the default environment
|
|
297
297
|
) -> "_Sandbox":
|
|
298
298
|
"""
|
|
299
|
-
Create a new Sandbox to run untrusted, arbitrary code.
|
|
300
|
-
|
|
299
|
+
Create a new Sandbox to run untrusted, arbitrary code.
|
|
300
|
+
|
|
301
|
+
The Sandbox's corresponding container will be created asynchronously.
|
|
301
302
|
|
|
302
303
|
**Usage**
|
|
303
304
|
|
|
@@ -354,7 +355,7 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
354
355
|
secrets: Sequence[_Secret] = (), # Environment variables to inject into the sandbox.
|
|
355
356
|
mounts: Sequence[_Mount] = (),
|
|
356
357
|
network_file_systems: dict[Union[str, os.PathLike], _NetworkFileSystem] = {},
|
|
357
|
-
timeout:
|
|
358
|
+
timeout: int = 300, # Maximum execution time of the sandbox in seconds.
|
|
358
359
|
workdir: Optional[str] = None, # Working directory of the sandbox.
|
|
359
360
|
gpu: GPU_T = None,
|
|
360
361
|
cloud: Optional[str] = None,
|