modal 0.67.1__py3-none-any.whl → 0.67.33__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 +8 -5
- 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 +20 -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 +68 -62
- 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 +100 -47
- modal/cls.pyi +40 -40
- 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 +112 -104
- modal/functions.pyi +77 -58
- modal/image.py +59 -57
- modal/image.pyi +104 -103
- 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.1.dist-info → modal-0.67.33.dist-info}/METADATA +2 -2
- modal-0.67.33.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 +15 -0
- modal_proto/api_grpc.py +32 -0
- modal_proto/api_pb2.py +674 -654
- modal_proto/api_pb2.pyi +45 -1
- modal_proto/api_pb2_grpc.py +66 -0
- modal_proto/api_pb2_grpc.pyi +20 -0
- modal_proto/modal_api_grpc.py +2 -0
- modal_version/_version_generated.py +1 -1
- modal-0.67.1.dist-info/RECORD +0 -168
- {modal-0.67.1.dist-info → modal-0.67.33.dist-info}/LICENSE +0 -0
- {modal-0.67.1.dist-info → modal-0.67.33.dist-info}/WHEEL +0 -0
- {modal-0.67.1.dist-info → modal-0.67.33.dist-info}/entry_points.txt +0 -0
- {modal-0.67.1.dist-info → modal-0.67.33.dist-info}/top_level.txt +0 -0
modal/retries.py
CHANGED
@@ -1,10 +1,14 @@
|
|
1
1
|
# Copyright Modal Labs 2022
|
2
|
+
import asyncio
|
2
3
|
from datetime import timedelta
|
3
4
|
|
4
5
|
from modal_proto import api_pb2
|
5
6
|
|
6
7
|
from .exception import InvalidError
|
7
8
|
|
9
|
+
MIN_INPUT_RETRY_DELAY_MS = 1000
|
10
|
+
MAX_INPUT_RETRY_DELAY_MS = 24 * 60 * 60 * 1000
|
11
|
+
|
8
12
|
|
9
13
|
class Retries:
|
10
14
|
"""Adds a retry policy to a Modal function.
|
@@ -103,3 +107,37 @@ class Retries:
|
|
103
107
|
initial_delay_ms=self.initial_delay // timedelta(milliseconds=1),
|
104
108
|
max_delay_ms=self.max_delay // timedelta(milliseconds=1),
|
105
109
|
)
|
110
|
+
|
111
|
+
|
112
|
+
class RetryManager:
|
113
|
+
"""
|
114
|
+
Helper class to apply the specified retry policy.
|
115
|
+
"""
|
116
|
+
|
117
|
+
def __init__(self, retry_policy: api_pb2.FunctionRetryPolicy):
|
118
|
+
self.retry_policy = retry_policy
|
119
|
+
self.attempt_count = 0
|
120
|
+
|
121
|
+
async def raise_or_sleep(self, exc: Exception):
|
122
|
+
"""
|
123
|
+
Raises an exception if the maximum retry count has been reached, otherwise sleeps for calculated delay.
|
124
|
+
"""
|
125
|
+
self.attempt_count += 1
|
126
|
+
if self.attempt_count > self.retry_policy.retries:
|
127
|
+
raise exc
|
128
|
+
delay_ms = self._retry_delay_ms(self.attempt_count, self.retry_policy)
|
129
|
+
await asyncio.sleep(delay_ms / 1000)
|
130
|
+
|
131
|
+
@staticmethod
|
132
|
+
def _retry_delay_ms(attempt_count: int, retry_policy: api_pb2.FunctionRetryPolicy) -> float:
|
133
|
+
"""
|
134
|
+
Computes the amount of time to sleep before retrying based on the backend_coefficient and initial_delay_ms args.
|
135
|
+
"""
|
136
|
+
if attempt_count < 1:
|
137
|
+
raise ValueError(f"Cannot compute retry delay. attempt_count must be at least 1, but was {attempt_count}")
|
138
|
+
delay_ms = retry_policy.initial_delay_ms * (retry_policy.backoff_coefficient ** (attempt_count - 1))
|
139
|
+
if delay_ms < MIN_INPUT_RETRY_DELAY_MS:
|
140
|
+
return MIN_INPUT_RETRY_DELAY_MS
|
141
|
+
if delay_ms > MAX_INPUT_RETRY_DELAY_MS:
|
142
|
+
return MAX_INPUT_RETRY_DELAY_MS
|
143
|
+
return delay_ms
|
modal/runner.py
CHANGED
@@ -4,8 +4,9 @@ import dataclasses
|
|
4
4
|
import os
|
5
5
|
import time
|
6
6
|
import typing
|
7
|
+
from collections.abc import AsyncGenerator
|
7
8
|
from multiprocessing.synchronize import Event
|
8
|
-
from typing import TYPE_CHECKING, Any,
|
9
|
+
from typing import TYPE_CHECKING, Any, Callable, Optional, TypeVar
|
9
10
|
|
10
11
|
from grpclib import GRPCError, Status
|
11
12
|
from synchronicity.async_wrap import asynccontextmanager
|
@@ -123,7 +124,7 @@ async def _init_local_app_from_name(
|
|
123
124
|
async def _create_all_objects(
|
124
125
|
client: _Client,
|
125
126
|
running_app: RunningApp,
|
126
|
-
indexed_objects:
|
127
|
+
indexed_objects: dict[str, _Object],
|
127
128
|
environment_name: str,
|
128
129
|
) -> None:
|
129
130
|
"""Create objects that have been defined but not created on the server."""
|
@@ -171,15 +172,15 @@ async def _publish_app(
|
|
171
172
|
client: _Client,
|
172
173
|
running_app: RunningApp,
|
173
174
|
app_state: int, # api_pb2.AppState.value
|
174
|
-
indexed_objects:
|
175
|
+
indexed_objects: dict[str, _Object],
|
175
176
|
name: str = "", # Only relevant for deployments
|
176
177
|
tag: str = "", # Only relevant for deployments
|
177
|
-
) ->
|
178
|
+
) -> tuple[str, list[str]]:
|
178
179
|
"""Wrapper for AppPublish RPC."""
|
179
180
|
|
180
181
|
# Could simplify this function some changing the internal representation to use
|
181
182
|
# function_ids / class_ids rather than the current tag_to_object_id (i.e. "indexed_objects")
|
182
|
-
def filter_values(full_dict:
|
183
|
+
def filter_values(full_dict: dict[str, V], condition: Callable[[V], bool]) -> dict[str, V]:
|
183
184
|
return {k: v for k, v in full_dict.items() if condition(v)}
|
184
185
|
|
185
186
|
function_ids = filter_values(running_app.tag_to_object_id, _Function._is_id_type)
|
@@ -453,7 +454,7 @@ class DeployResult:
|
|
453
454
|
app_id: str
|
454
455
|
app_page_url: str
|
455
456
|
app_logs_url: str
|
456
|
-
warnings:
|
457
|
+
warnings: list[str]
|
457
458
|
|
458
459
|
|
459
460
|
async def _deploy_app(
|
@@ -556,7 +557,7 @@ async def _deploy_app(
|
|
556
557
|
)
|
557
558
|
|
558
559
|
|
559
|
-
async def _interactive_shell(_app: _App, cmds:
|
560
|
+
async def _interactive_shell(_app: _App, cmds: list[str], environment_name: str = "", **kwargs: Any) -> None:
|
560
561
|
"""Run an interactive shell (like `bash`) within the image for this app.
|
561
562
|
|
562
563
|
This is useful for online debugging and interactive exploration of the
|
modal/runner.pyi
CHANGED
@@ -27,17 +27,17 @@ async def _init_local_app_from_name(
|
|
27
27
|
async def _create_all_objects(
|
28
28
|
client: modal.client._Client,
|
29
29
|
running_app: modal.running_app.RunningApp,
|
30
|
-
indexed_objects:
|
30
|
+
indexed_objects: dict[str, modal.object._Object],
|
31
31
|
environment_name: str,
|
32
32
|
) -> None: ...
|
33
33
|
async def _publish_app(
|
34
34
|
client: modal.client._Client,
|
35
35
|
running_app: modal.running_app.RunningApp,
|
36
36
|
app_state: int,
|
37
|
-
indexed_objects:
|
37
|
+
indexed_objects: dict[str, modal.object._Object],
|
38
38
|
name: str = "",
|
39
39
|
tag: str = "",
|
40
|
-
) ->
|
40
|
+
) -> tuple[str, list[str]]: ...
|
41
41
|
async def _disconnect(client: modal.client._Client, app_id: str, reason: int, exc_str: str = "") -> None: ...
|
42
42
|
async def _status_based_disconnect(
|
43
43
|
client: modal.client._Client, app_id: str, exc_info: typing.Optional[BaseException] = None
|
@@ -58,9 +58,9 @@ class DeployResult:
|
|
58
58
|
app_id: str
|
59
59
|
app_page_url: str
|
60
60
|
app_logs_url: str
|
61
|
-
warnings:
|
61
|
+
warnings: list[str]
|
62
62
|
|
63
|
-
def __init__(self, app_id: str, app_page_url: str, app_logs_url: str, warnings:
|
63
|
+
def __init__(self, app_id: str, app_page_url: str, app_logs_url: str, warnings: list[str]) -> None: ...
|
64
64
|
def __repr__(self): ...
|
65
65
|
def __eq__(self, other): ...
|
66
66
|
def __setattr__(self, name, value): ...
|
@@ -75,9 +75,7 @@ async def _deploy_app(
|
|
75
75
|
environment_name: typing.Optional[str] = None,
|
76
76
|
tag: str = "",
|
77
77
|
) -> DeployResult: ...
|
78
|
-
async def _interactive_shell(
|
79
|
-
_app: _App, cmds: typing.List[str], environment_name: str = "", **kwargs: typing.Any
|
80
|
-
) -> None: ...
|
78
|
+
async def _interactive_shell(_app: _App, cmds: list[str], environment_name: str = "", **kwargs: typing.Any) -> None: ...
|
81
79
|
def _run_stub(*args: typing.Any, **kwargs: typing.Any): ...
|
82
80
|
def _deploy_stub(*args: typing.Any, **kwargs: typing.Any): ...
|
83
81
|
|
@@ -136,12 +134,8 @@ class __deploy_app_spec(typing_extensions.Protocol):
|
|
136
134
|
deploy_app: __deploy_app_spec
|
137
135
|
|
138
136
|
class __interactive_shell_spec(typing_extensions.Protocol):
|
139
|
-
def __call__(
|
140
|
-
|
141
|
-
) -> None: ...
|
142
|
-
async def aio(
|
143
|
-
self, _app: _App, cmds: typing.List[str], environment_name: str = "", **kwargs: typing.Any
|
144
|
-
) -> None: ...
|
137
|
+
def __call__(self, _app: _App, cmds: list[str], environment_name: str = "", **kwargs: typing.Any) -> None: ...
|
138
|
+
async def aio(self, _app: _App, cmds: list[str], environment_name: str = "", **kwargs: typing.Any) -> None: ...
|
145
139
|
|
146
140
|
interactive_shell: __interactive_shell_spec
|
147
141
|
|
modal/running_app.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Copyright Modal Labs 2024
|
2
2
|
from dataclasses import dataclass, field
|
3
|
-
from typing import
|
3
|
+
from typing import Optional
|
4
4
|
|
5
5
|
from google.protobuf.message import Message
|
6
6
|
|
@@ -13,7 +13,7 @@ class RunningApp:
|
|
13
13
|
environment_name: Optional[str] = None
|
14
14
|
app_page_url: Optional[str] = None
|
15
15
|
app_logs_url: Optional[str] = None
|
16
|
-
tag_to_object_id:
|
17
|
-
object_handle_metadata:
|
16
|
+
tag_to_object_id: dict[str, str] = field(default_factory=dict)
|
17
|
+
object_handle_metadata: dict[str, Optional[Message]] = field(default_factory=dict)
|
18
18
|
interactive: bool = False
|
19
19
|
client: Optional[_Client] = None
|
modal/sandbox.py
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
# Copyright Modal Labs 2022
|
2
2
|
import asyncio
|
3
3
|
import os
|
4
|
-
from
|
4
|
+
from collections.abc import AsyncGenerator, Sequence
|
5
|
+
from typing import TYPE_CHECKING, Literal, Optional, Union, overload
|
5
6
|
|
6
7
|
from google.protobuf.message import Message
|
7
8
|
from grpclib import GRPCError, Status
|
@@ -27,6 +28,7 @@ from .io_streams import StreamReader, StreamWriter, _StreamReader, _StreamWriter
|
|
27
28
|
from .mount import _Mount
|
28
29
|
from .network_file_system import _NetworkFileSystem, network_file_system_mount_protos
|
29
30
|
from .object import _get_environment_name, _Object
|
31
|
+
from .proxy import _Proxy
|
30
32
|
from .scheduler_placement import SchedulerPlacement
|
31
33
|
from .secret import _Secret
|
32
34
|
from .stream_type import StreamType
|
@@ -50,7 +52,7 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
50
52
|
_stderr: _StreamReader[str]
|
51
53
|
_stdin: _StreamWriter
|
52
54
|
_task_id: Optional[str] = None
|
53
|
-
_tunnels: Optional[
|
55
|
+
_tunnels: Optional[dict[int, Tunnel]] = None
|
54
56
|
|
55
57
|
@staticmethod
|
56
58
|
def _new(
|
@@ -64,14 +66,15 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
64
66
|
cloud: Optional[str] = None,
|
65
67
|
region: Optional[Union[str, Sequence[str]]] = None,
|
66
68
|
cpu: Optional[float] = None,
|
67
|
-
memory: Optional[Union[int,
|
68
|
-
network_file_systems:
|
69
|
+
memory: Optional[Union[int, tuple[int, int]]] = None,
|
70
|
+
network_file_systems: dict[Union[str, os.PathLike], _NetworkFileSystem] = {},
|
69
71
|
block_network: bool = False,
|
70
72
|
cidr_allowlist: Optional[Sequence[str]] = None,
|
71
|
-
volumes:
|
73
|
+
volumes: dict[Union[str, os.PathLike], Union[_Volume, _CloudBucketMount]] = {},
|
72
74
|
pty_info: Optional[api_pb2.PTYInfo] = None,
|
73
75
|
encrypted_ports: Sequence[int] = [],
|
74
76
|
unencrypted_ports: Sequence[int] = [],
|
77
|
+
proxy: Optional[_Proxy] = None,
|
75
78
|
_experimental_scheduler_placement: Optional[SchedulerPlacement] = None,
|
76
79
|
) -> "_Sandbox":
|
77
80
|
"""mdmd:hidden"""
|
@@ -101,8 +104,8 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
101
104
|
cloud_bucket_mounts = [(k, v) for k, v in validated_volumes if isinstance(v, _CloudBucketMount)]
|
102
105
|
validated_volumes = [(k, v) for k, v in validated_volumes if isinstance(v, _Volume)]
|
103
106
|
|
104
|
-
def _deps() ->
|
105
|
-
deps:
|
107
|
+
def _deps() -> list[_Object]:
|
108
|
+
deps: list[_Object] = [image] + list(mounts) + list(secrets)
|
106
109
|
for _, vol in validated_network_file_systems:
|
107
110
|
deps.append(vol)
|
108
111
|
for _, vol in validated_volumes:
|
@@ -165,6 +168,7 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
165
168
|
worker_id=config.get("worker_id"),
|
166
169
|
open_ports=api_pb2.PortSpecs(ports=open_ports),
|
167
170
|
network_access=network_access,
|
171
|
+
proxy_id=(proxy.object_id if proxy else None),
|
168
172
|
)
|
169
173
|
|
170
174
|
# Note - `resolver.app_id` will be `None` for app-less sandboxes
|
@@ -186,7 +190,7 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
186
190
|
image: Optional[_Image] = None, # The image to run as the container for the sandbox.
|
187
191
|
mounts: Sequence[_Mount] = (), # Mounts to attach to the sandbox.
|
188
192
|
secrets: Sequence[_Secret] = (), # Environment variables to inject into the sandbox.
|
189
|
-
network_file_systems:
|
193
|
+
network_file_systems: dict[Union[str, os.PathLike], _NetworkFileSystem] = {},
|
190
194
|
timeout: Optional[int] = None, # Maximum execution time of the sandbox in seconds.
|
191
195
|
workdir: Optional[str] = None, # Working directory of the sandbox.
|
192
196
|
gpu: GPU_T = None,
|
@@ -195,11 +199,11 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
195
199
|
cpu: Optional[float] = None, # How many CPU cores to request. This is a soft limit.
|
196
200
|
# Specify, in MiB, a memory request which is the minimum memory required.
|
197
201
|
# Or, pass (request, limit) to additionally specify a hard limit in MiB.
|
198
|
-
memory: Optional[Union[int,
|
202
|
+
memory: Optional[Union[int, tuple[int, int]]] = None,
|
199
203
|
block_network: bool = False, # Whether to block network access
|
200
204
|
# List of CIDRs the sandbox is allowed to access. If None, all CIDRs are allowed.
|
201
205
|
cidr_allowlist: Optional[Sequence[str]] = None,
|
202
|
-
volumes:
|
206
|
+
volumes: dict[
|
203
207
|
Union[str, os.PathLike], Union[_Volume, _CloudBucketMount]
|
204
208
|
] = {}, # Mount points for Modal Volumes and CloudBucketMounts
|
205
209
|
pty_info: Optional[api_pb2.PTYInfo] = None,
|
@@ -207,6 +211,8 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
207
211
|
encrypted_ports: Sequence[int] = [],
|
208
212
|
# List of ports to tunnel into the sandbox without encryption.
|
209
213
|
unencrypted_ports: Sequence[int] = [],
|
214
|
+
# Reference to a Modal Proxy to use in front of this Sandbox.
|
215
|
+
proxy: Optional[_Proxy] = None,
|
210
216
|
_experimental_scheduler_placement: Optional[
|
211
217
|
SchedulerPlacement
|
212
218
|
] = None, # Experimental controls over fine-grained scheduling (alpha).
|
@@ -242,6 +248,7 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
242
248
|
pty_info=pty_info,
|
243
249
|
encrypted_ports=encrypted_ports,
|
244
250
|
unencrypted_ports=unencrypted_ports,
|
251
|
+
proxy=proxy,
|
245
252
|
_experimental_scheduler_placement=_experimental_scheduler_placement,
|
246
253
|
)
|
247
254
|
|
@@ -306,7 +313,7 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
306
313
|
|
307
314
|
return obj
|
308
315
|
|
309
|
-
async def set_tags(self, tags:
|
316
|
+
async def set_tags(self, tags: dict[str, str], *, client: Optional[_Client] = None):
|
310
317
|
"""Set tags (key-value pairs) on the Sandbox. Tags can be used to filter results in `Sandbox.list`."""
|
311
318
|
environment_name = _get_environment_name()
|
312
319
|
if client is None:
|
@@ -341,7 +348,7 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
341
348
|
raise SandboxTerminatedError()
|
342
349
|
break
|
343
350
|
|
344
|
-
async def tunnels(self, timeout: int = 50) ->
|
351
|
+
async def tunnels(self, timeout: int = 50) -> dict[int, Tunnel]:
|
345
352
|
"""Get tunnel metadata for the sandbox.
|
346
353
|
|
347
354
|
Raises `SandboxTimeoutError` if the tunnels are not available after the timeout.
|
@@ -531,7 +538,7 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
531
538
|
|
532
539
|
@staticmethod
|
533
540
|
async def list(
|
534
|
-
*, app_id: Optional[str] = None, tags: Optional[
|
541
|
+
*, app_id: Optional[str] = None, tags: Optional[dict[str, str]] = None, client: Optional[_Client] = None
|
535
542
|
) -> AsyncGenerator["_Sandbox", None]:
|
536
543
|
"""List all sandboxes for the current environment or app ID (if specified). If tags are specified, only
|
537
544
|
sandboxes that have at least those tags are returned. Returns an iterator over `Sandbox` objects."""
|
modal/sandbox.pyi
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
import collections.abc
|
1
2
|
import google.protobuf.message
|
2
3
|
import modal._tunnel
|
3
4
|
import modal.app
|
@@ -10,6 +11,7 @@ import modal.io_streams
|
|
10
11
|
import modal.mount
|
11
12
|
import modal.network_file_system
|
12
13
|
import modal.object
|
14
|
+
import modal.proxy
|
13
15
|
import modal.scheduler_placement
|
14
16
|
import modal.secret
|
15
17
|
import modal.stream_type
|
@@ -25,33 +27,32 @@ class _Sandbox(modal.object._Object):
|
|
25
27
|
_stderr: modal.io_streams._StreamReader[str]
|
26
28
|
_stdin: modal.io_streams._StreamWriter
|
27
29
|
_task_id: typing.Optional[str]
|
28
|
-
_tunnels: typing.Optional[
|
30
|
+
_tunnels: typing.Optional[dict[int, modal._tunnel.Tunnel]]
|
29
31
|
|
30
32
|
@staticmethod
|
31
33
|
def _new(
|
32
|
-
entrypoint_args:
|
34
|
+
entrypoint_args: collections.abc.Sequence[str],
|
33
35
|
image: modal.image._Image,
|
34
|
-
mounts:
|
35
|
-
secrets:
|
36
|
+
mounts: collections.abc.Sequence[modal.mount._Mount],
|
37
|
+
secrets: collections.abc.Sequence[modal.secret._Secret],
|
36
38
|
timeout: typing.Optional[int] = None,
|
37
39
|
workdir: typing.Optional[str] = None,
|
38
40
|
gpu: typing.Union[None, bool, str, modal.gpu._GPUConfig] = None,
|
39
41
|
cloud: typing.Optional[str] = None,
|
40
|
-
region: typing.Union[str,
|
42
|
+
region: typing.Union[str, collections.abc.Sequence[str], None] = None,
|
41
43
|
cpu: typing.Optional[float] = None,
|
42
|
-
memory: typing.Union[int,
|
43
|
-
network_file_systems: typing.
|
44
|
-
typing.Union[str, os.PathLike], modal.network_file_system._NetworkFileSystem
|
45
|
-
] = {},
|
44
|
+
memory: typing.Union[int, tuple[int, int], None] = None,
|
45
|
+
network_file_systems: dict[typing.Union[str, os.PathLike], modal.network_file_system._NetworkFileSystem] = {},
|
46
46
|
block_network: bool = False,
|
47
|
-
cidr_allowlist: typing.Optional[
|
48
|
-
volumes:
|
47
|
+
cidr_allowlist: typing.Optional[collections.abc.Sequence[str]] = None,
|
48
|
+
volumes: dict[
|
49
49
|
typing.Union[str, os.PathLike],
|
50
50
|
typing.Union[modal.volume._Volume, modal.cloud_bucket_mount._CloudBucketMount],
|
51
51
|
] = {},
|
52
52
|
pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
|
53
|
-
encrypted_ports:
|
54
|
-
unencrypted_ports:
|
53
|
+
encrypted_ports: collections.abc.Sequence[int] = [],
|
54
|
+
unencrypted_ports: collections.abc.Sequence[int] = [],
|
55
|
+
proxy: typing.Optional[modal.proxy._Proxy] = None,
|
55
56
|
_experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
|
56
57
|
) -> _Sandbox: ...
|
57
58
|
@staticmethod
|
@@ -60,36 +61,35 @@ class _Sandbox(modal.object._Object):
|
|
60
61
|
app: typing.Optional[modal.app._App] = None,
|
61
62
|
environment_name: typing.Optional[str] = None,
|
62
63
|
image: typing.Optional[modal.image._Image] = None,
|
63
|
-
mounts:
|
64
|
-
secrets:
|
65
|
-
network_file_systems: typing.
|
66
|
-
typing.Union[str, os.PathLike], modal.network_file_system._NetworkFileSystem
|
67
|
-
] = {},
|
64
|
+
mounts: collections.abc.Sequence[modal.mount._Mount] = (),
|
65
|
+
secrets: collections.abc.Sequence[modal.secret._Secret] = (),
|
66
|
+
network_file_systems: dict[typing.Union[str, os.PathLike], modal.network_file_system._NetworkFileSystem] = {},
|
68
67
|
timeout: typing.Optional[int] = None,
|
69
68
|
workdir: typing.Optional[str] = None,
|
70
69
|
gpu: typing.Union[None, bool, str, modal.gpu._GPUConfig] = None,
|
71
70
|
cloud: typing.Optional[str] = None,
|
72
|
-
region: typing.Union[str,
|
71
|
+
region: typing.Union[str, collections.abc.Sequence[str], None] = None,
|
73
72
|
cpu: typing.Optional[float] = None,
|
74
|
-
memory: typing.Union[int,
|
73
|
+
memory: typing.Union[int, tuple[int, int], None] = None,
|
75
74
|
block_network: bool = False,
|
76
|
-
cidr_allowlist: typing.Optional[
|
77
|
-
volumes:
|
75
|
+
cidr_allowlist: typing.Optional[collections.abc.Sequence[str]] = None,
|
76
|
+
volumes: dict[
|
78
77
|
typing.Union[str, os.PathLike],
|
79
78
|
typing.Union[modal.volume._Volume, modal.cloud_bucket_mount._CloudBucketMount],
|
80
79
|
] = {},
|
81
80
|
pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
|
82
|
-
encrypted_ports:
|
83
|
-
unencrypted_ports:
|
81
|
+
encrypted_ports: collections.abc.Sequence[int] = [],
|
82
|
+
unencrypted_ports: collections.abc.Sequence[int] = [],
|
83
|
+
proxy: typing.Optional[modal.proxy._Proxy] = None,
|
84
84
|
_experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
|
85
85
|
client: typing.Optional[modal.client._Client] = None,
|
86
86
|
) -> _Sandbox: ...
|
87
87
|
def _hydrate_metadata(self, handle_metadata: typing.Optional[google.protobuf.message.Message]): ...
|
88
88
|
@staticmethod
|
89
89
|
async def from_id(sandbox_id: str, client: typing.Optional[modal.client._Client] = None) -> _Sandbox: ...
|
90
|
-
async def set_tags(self, tags:
|
90
|
+
async def set_tags(self, tags: dict[str, str], *, client: typing.Optional[modal.client._Client] = None): ...
|
91
91
|
async def wait(self, raise_on_termination: bool = True): ...
|
92
|
-
async def tunnels(self, timeout: int = 50) ->
|
92
|
+
async def tunnels(self, timeout: int = 50) -> dict[int, modal._tunnel.Tunnel]: ...
|
93
93
|
async def terminate(self): ...
|
94
94
|
async def poll(self) -> typing.Optional[int]: ...
|
95
95
|
async def _get_task_id(self): ...
|
@@ -102,7 +102,7 @@ class _Sandbox(modal.object._Object):
|
|
102
102
|
stderr: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
103
103
|
timeout: typing.Optional[int] = None,
|
104
104
|
workdir: typing.Optional[str] = None,
|
105
|
-
secrets:
|
105
|
+
secrets: collections.abc.Sequence[modal.secret._Secret] = (),
|
106
106
|
text: typing.Literal[True] = True,
|
107
107
|
bufsize: typing.Literal[-1, 1] = -1,
|
108
108
|
_pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
|
@@ -116,7 +116,7 @@ class _Sandbox(modal.object._Object):
|
|
116
116
|
stderr: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
117
117
|
timeout: typing.Optional[int] = None,
|
118
118
|
workdir: typing.Optional[str] = None,
|
119
|
-
secrets:
|
119
|
+
secrets: collections.abc.Sequence[modal.secret._Secret] = (),
|
120
120
|
text: typing.Literal[False] = False,
|
121
121
|
bufsize: typing.Literal[-1, 1] = -1,
|
122
122
|
_pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
|
@@ -133,9 +133,9 @@ class _Sandbox(modal.object._Object):
|
|
133
133
|
def list(
|
134
134
|
*,
|
135
135
|
app_id: typing.Optional[str] = None,
|
136
|
-
tags: typing.Optional[
|
136
|
+
tags: typing.Optional[dict[str, str]] = None,
|
137
137
|
client: typing.Optional[modal.client._Client] = None,
|
138
|
-
) ->
|
138
|
+
) -> collections.abc.AsyncGenerator[_Sandbox, None]: ...
|
139
139
|
|
140
140
|
class Sandbox(modal.object.Object):
|
141
141
|
_result: typing.Optional[modal_proto.api_pb2.GenericResult]
|
@@ -143,33 +143,32 @@ class Sandbox(modal.object.Object):
|
|
143
143
|
_stderr: modal.io_streams.StreamReader[str]
|
144
144
|
_stdin: modal.io_streams.StreamWriter
|
145
145
|
_task_id: typing.Optional[str]
|
146
|
-
_tunnels: typing.Optional[
|
146
|
+
_tunnels: typing.Optional[dict[int, modal._tunnel.Tunnel]]
|
147
147
|
|
148
148
|
def __init__(self, *args, **kwargs): ...
|
149
149
|
@staticmethod
|
150
150
|
def _new(
|
151
|
-
entrypoint_args:
|
151
|
+
entrypoint_args: collections.abc.Sequence[str],
|
152
152
|
image: modal.image.Image,
|
153
|
-
mounts:
|
154
|
-
secrets:
|
153
|
+
mounts: collections.abc.Sequence[modal.mount.Mount],
|
154
|
+
secrets: collections.abc.Sequence[modal.secret.Secret],
|
155
155
|
timeout: typing.Optional[int] = None,
|
156
156
|
workdir: typing.Optional[str] = None,
|
157
157
|
gpu: typing.Union[None, bool, str, modal.gpu._GPUConfig] = None,
|
158
158
|
cloud: typing.Optional[str] = None,
|
159
|
-
region: typing.Union[str,
|
159
|
+
region: typing.Union[str, collections.abc.Sequence[str], None] = None,
|
160
160
|
cpu: typing.Optional[float] = None,
|
161
|
-
memory: typing.Union[int,
|
162
|
-
network_file_systems: typing.
|
163
|
-
typing.Union[str, os.PathLike], modal.network_file_system.NetworkFileSystem
|
164
|
-
] = {},
|
161
|
+
memory: typing.Union[int, tuple[int, int], None] = None,
|
162
|
+
network_file_systems: dict[typing.Union[str, os.PathLike], modal.network_file_system.NetworkFileSystem] = {},
|
165
163
|
block_network: bool = False,
|
166
|
-
cidr_allowlist: typing.Optional[
|
167
|
-
volumes:
|
164
|
+
cidr_allowlist: typing.Optional[collections.abc.Sequence[str]] = None,
|
165
|
+
volumes: dict[
|
168
166
|
typing.Union[str, os.PathLike], typing.Union[modal.volume.Volume, modal.cloud_bucket_mount.CloudBucketMount]
|
169
167
|
] = {},
|
170
168
|
pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
|
171
|
-
encrypted_ports:
|
172
|
-
unencrypted_ports:
|
169
|
+
encrypted_ports: collections.abc.Sequence[int] = [],
|
170
|
+
unencrypted_ports: collections.abc.Sequence[int] = [],
|
171
|
+
proxy: typing.Optional[modal.proxy.Proxy] = None,
|
173
172
|
_experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
|
174
173
|
) -> Sandbox: ...
|
175
174
|
|
@@ -180,27 +179,28 @@ class Sandbox(modal.object.Object):
|
|
180
179
|
app: typing.Optional[modal.app.App] = None,
|
181
180
|
environment_name: typing.Optional[str] = None,
|
182
181
|
image: typing.Optional[modal.image.Image] = None,
|
183
|
-
mounts:
|
184
|
-
secrets:
|
185
|
-
network_file_systems:
|
182
|
+
mounts: collections.abc.Sequence[modal.mount.Mount] = (),
|
183
|
+
secrets: collections.abc.Sequence[modal.secret.Secret] = (),
|
184
|
+
network_file_systems: dict[
|
186
185
|
typing.Union[str, os.PathLike], modal.network_file_system.NetworkFileSystem
|
187
186
|
] = {},
|
188
187
|
timeout: typing.Optional[int] = None,
|
189
188
|
workdir: typing.Optional[str] = None,
|
190
189
|
gpu: typing.Union[None, bool, str, modal.gpu._GPUConfig] = None,
|
191
190
|
cloud: typing.Optional[str] = None,
|
192
|
-
region: typing.Union[str,
|
191
|
+
region: typing.Union[str, collections.abc.Sequence[str], None] = None,
|
193
192
|
cpu: typing.Optional[float] = None,
|
194
|
-
memory: typing.Union[int,
|
193
|
+
memory: typing.Union[int, tuple[int, int], None] = None,
|
195
194
|
block_network: bool = False,
|
196
|
-
cidr_allowlist: typing.Optional[
|
197
|
-
volumes:
|
195
|
+
cidr_allowlist: typing.Optional[collections.abc.Sequence[str]] = None,
|
196
|
+
volumes: dict[
|
198
197
|
typing.Union[str, os.PathLike],
|
199
198
|
typing.Union[modal.volume.Volume, modal.cloud_bucket_mount.CloudBucketMount],
|
200
199
|
] = {},
|
201
200
|
pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
|
202
|
-
encrypted_ports:
|
203
|
-
unencrypted_ports:
|
201
|
+
encrypted_ports: collections.abc.Sequence[int] = [],
|
202
|
+
unencrypted_ports: collections.abc.Sequence[int] = [],
|
203
|
+
proxy: typing.Optional[modal.proxy.Proxy] = None,
|
204
204
|
_experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
|
205
205
|
client: typing.Optional[modal.client.Client] = None,
|
206
206
|
) -> Sandbox: ...
|
@@ -210,27 +210,28 @@ class Sandbox(modal.object.Object):
|
|
210
210
|
app: typing.Optional[modal.app.App] = None,
|
211
211
|
environment_name: typing.Optional[str] = None,
|
212
212
|
image: typing.Optional[modal.image.Image] = None,
|
213
|
-
mounts:
|
214
|
-
secrets:
|
215
|
-
network_file_systems:
|
213
|
+
mounts: collections.abc.Sequence[modal.mount.Mount] = (),
|
214
|
+
secrets: collections.abc.Sequence[modal.secret.Secret] = (),
|
215
|
+
network_file_systems: dict[
|
216
216
|
typing.Union[str, os.PathLike], modal.network_file_system.NetworkFileSystem
|
217
217
|
] = {},
|
218
218
|
timeout: typing.Optional[int] = None,
|
219
219
|
workdir: typing.Optional[str] = None,
|
220
220
|
gpu: typing.Union[None, bool, str, modal.gpu._GPUConfig] = None,
|
221
221
|
cloud: typing.Optional[str] = None,
|
222
|
-
region: typing.Union[str,
|
222
|
+
region: typing.Union[str, collections.abc.Sequence[str], None] = None,
|
223
223
|
cpu: typing.Optional[float] = None,
|
224
|
-
memory: typing.Union[int,
|
224
|
+
memory: typing.Union[int, tuple[int, int], None] = None,
|
225
225
|
block_network: bool = False,
|
226
|
-
cidr_allowlist: typing.Optional[
|
227
|
-
volumes:
|
226
|
+
cidr_allowlist: typing.Optional[collections.abc.Sequence[str]] = None,
|
227
|
+
volumes: dict[
|
228
228
|
typing.Union[str, os.PathLike],
|
229
229
|
typing.Union[modal.volume.Volume, modal.cloud_bucket_mount.CloudBucketMount],
|
230
230
|
] = {},
|
231
231
|
pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
|
232
|
-
encrypted_ports:
|
233
|
-
unencrypted_ports:
|
232
|
+
encrypted_ports: collections.abc.Sequence[int] = [],
|
233
|
+
unencrypted_ports: collections.abc.Sequence[int] = [],
|
234
|
+
proxy: typing.Optional[modal.proxy.Proxy] = None,
|
234
235
|
_experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
|
235
236
|
client: typing.Optional[modal.client.Client] = None,
|
236
237
|
) -> Sandbox: ...
|
@@ -246,8 +247,8 @@ class Sandbox(modal.object.Object):
|
|
246
247
|
from_id: __from_id_spec
|
247
248
|
|
248
249
|
class __set_tags_spec(typing_extensions.Protocol):
|
249
|
-
def __call__(self, tags:
|
250
|
-
async def aio(self, tags:
|
250
|
+
def __call__(self, tags: dict[str, str], *, client: typing.Optional[modal.client.Client] = None): ...
|
251
|
+
async def aio(self, tags: dict[str, str], *, client: typing.Optional[modal.client.Client] = None): ...
|
251
252
|
|
252
253
|
set_tags: __set_tags_spec
|
253
254
|
|
@@ -258,8 +259,8 @@ class Sandbox(modal.object.Object):
|
|
258
259
|
wait: __wait_spec
|
259
260
|
|
260
261
|
class __tunnels_spec(typing_extensions.Protocol):
|
261
|
-
def __call__(self, timeout: int = 50) ->
|
262
|
-
async def aio(self, timeout: int = 50) ->
|
262
|
+
def __call__(self, timeout: int = 50) -> dict[int, modal._tunnel.Tunnel]: ...
|
263
|
+
async def aio(self, timeout: int = 50) -> dict[int, modal._tunnel.Tunnel]: ...
|
263
264
|
|
264
265
|
tunnels: __tunnels_spec
|
265
266
|
|
@@ -291,7 +292,7 @@ class Sandbox(modal.object.Object):
|
|
291
292
|
stderr: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
292
293
|
timeout: typing.Optional[int] = None,
|
293
294
|
workdir: typing.Optional[str] = None,
|
294
|
-
secrets:
|
295
|
+
secrets: collections.abc.Sequence[modal.secret.Secret] = (),
|
295
296
|
text: typing.Literal[True] = True,
|
296
297
|
bufsize: typing.Literal[-1, 1] = -1,
|
297
298
|
_pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
|
@@ -305,7 +306,7 @@ class Sandbox(modal.object.Object):
|
|
305
306
|
stderr: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
306
307
|
timeout: typing.Optional[int] = None,
|
307
308
|
workdir: typing.Optional[str] = None,
|
308
|
-
secrets:
|
309
|
+
secrets: collections.abc.Sequence[modal.secret.Secret] = (),
|
309
310
|
text: typing.Literal[False] = False,
|
310
311
|
bufsize: typing.Literal[-1, 1] = -1,
|
311
312
|
_pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
|
@@ -319,7 +320,7 @@ class Sandbox(modal.object.Object):
|
|
319
320
|
stderr: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
320
321
|
timeout: typing.Optional[int] = None,
|
321
322
|
workdir: typing.Optional[str] = None,
|
322
|
-
secrets:
|
323
|
+
secrets: collections.abc.Sequence[modal.secret.Secret] = (),
|
323
324
|
text: typing.Literal[True] = True,
|
324
325
|
bufsize: typing.Literal[-1, 1] = -1,
|
325
326
|
_pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
|
@@ -333,7 +334,7 @@ class Sandbox(modal.object.Object):
|
|
333
334
|
stderr: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
334
335
|
timeout: typing.Optional[int] = None,
|
335
336
|
workdir: typing.Optional[str] = None,
|
336
|
-
secrets:
|
337
|
+
secrets: collections.abc.Sequence[modal.secret.Secret] = (),
|
337
338
|
text: typing.Literal[False] = False,
|
338
339
|
bufsize: typing.Literal[-1, 1] = -1,
|
339
340
|
_pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
|
@@ -355,16 +356,16 @@ class Sandbox(modal.object.Object):
|
|
355
356
|
self,
|
356
357
|
*,
|
357
358
|
app_id: typing.Optional[str] = None,
|
358
|
-
tags: typing.Optional[
|
359
|
+
tags: typing.Optional[dict[str, str]] = None,
|
359
360
|
client: typing.Optional[modal.client.Client] = None,
|
360
361
|
) -> typing.Generator[Sandbox, None, None]: ...
|
361
362
|
def aio(
|
362
363
|
self,
|
363
364
|
*,
|
364
365
|
app_id: typing.Optional[str] = None,
|
365
|
-
tags: typing.Optional[
|
366
|
+
tags: typing.Optional[dict[str, str]] = None,
|
366
367
|
client: typing.Optional[modal.client.Client] = None,
|
367
|
-
) ->
|
368
|
+
) -> collections.abc.AsyncGenerator[Sandbox, None]: ...
|
368
369
|
|
369
370
|
list: __list_spec
|
370
371
|
|