modal 0.73.30__py3-none-any.whl → 0.73.32__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/app.pyi +7 -15
- modal/client.pyi +2 -2
- modal/cls.pyi +2 -2
- modal/functions.pyi +1 -3
- modal/gpu.py +25 -6
- modal/image.pyi +26 -30
- modal/sandbox.py +21 -0
- modal/sandbox.pyi +7 -5
- {modal-0.73.30.dist-info → modal-0.73.32.dist-info}/METADATA +1 -1
- {modal-0.73.30.dist-info → modal-0.73.32.dist-info}/RECORD +15 -15
- modal_version/_version_generated.py +1 -1
- {modal-0.73.30.dist-info → modal-0.73.32.dist-info}/LICENSE +0 -0
- {modal-0.73.30.dist-info → modal-0.73.32.dist-info}/WHEEL +0 -0
- {modal-0.73.30.dist-info → modal-0.73.32.dist-info}/entry_points.txt +0 -0
- {modal-0.73.30.dist-info → modal-0.73.32.dist-info}/top_level.txt +0 -0
modal/app.pyi
CHANGED
@@ -161,9 +161,7 @@ class _App:
|
|
161
161
|
image: typing.Optional[modal.image._Image] = None,
|
162
162
|
schedule: typing.Optional[modal.schedule.Schedule] = None,
|
163
163
|
secrets: collections.abc.Sequence[modal.secret._Secret] = (),
|
164
|
-
gpu: typing.Union[
|
165
|
-
None, bool, str, modal.gpu._GPUConfig, list[typing.Union[None, bool, str, modal.gpu._GPUConfig]]
|
166
|
-
] = None,
|
164
|
+
gpu: typing.Union[None, str, modal.gpu._GPUConfig, list[typing.Union[None, str, modal.gpu._GPUConfig]]] = None,
|
167
165
|
serialized: bool = False,
|
168
166
|
mounts: collections.abc.Sequence[modal.mount._Mount] = (),
|
169
167
|
network_file_systems: dict[
|
@@ -209,9 +207,7 @@ class _App:
|
|
209
207
|
*,
|
210
208
|
image: typing.Optional[modal.image._Image] = None,
|
211
209
|
secrets: collections.abc.Sequence[modal.secret._Secret] = (),
|
212
|
-
gpu: typing.Union[
|
213
|
-
None, bool, str, modal.gpu._GPUConfig, list[typing.Union[None, bool, str, modal.gpu._GPUConfig]]
|
214
|
-
] = None,
|
210
|
+
gpu: typing.Union[None, str, modal.gpu._GPUConfig, list[typing.Union[None, str, modal.gpu._GPUConfig]]] = None,
|
215
211
|
serialized: bool = False,
|
216
212
|
mounts: collections.abc.Sequence[modal.mount._Mount] = (),
|
217
213
|
network_file_systems: dict[
|
@@ -255,7 +251,7 @@ class _App:
|
|
255
251
|
] = {},
|
256
252
|
timeout: typing.Optional[int] = None,
|
257
253
|
workdir: typing.Optional[str] = None,
|
258
|
-
gpu: typing.Union[None,
|
254
|
+
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
259
255
|
cloud: typing.Optional[str] = None,
|
260
256
|
region: typing.Union[str, collections.abc.Sequence[str], None] = None,
|
261
257
|
cpu: typing.Union[float, tuple[float, float], None] = None,
|
@@ -397,9 +393,7 @@ class App:
|
|
397
393
|
image: typing.Optional[modal.image.Image] = None,
|
398
394
|
schedule: typing.Optional[modal.schedule.Schedule] = None,
|
399
395
|
secrets: collections.abc.Sequence[modal.secret.Secret] = (),
|
400
|
-
gpu: typing.Union[
|
401
|
-
None, bool, str, modal.gpu._GPUConfig, list[typing.Union[None, bool, str, modal.gpu._GPUConfig]]
|
402
|
-
] = None,
|
396
|
+
gpu: typing.Union[None, str, modal.gpu._GPUConfig, list[typing.Union[None, str, modal.gpu._GPUConfig]]] = None,
|
403
397
|
serialized: bool = False,
|
404
398
|
mounts: collections.abc.Sequence[modal.mount.Mount] = (),
|
405
399
|
network_file_systems: dict[
|
@@ -445,9 +439,7 @@ class App:
|
|
445
439
|
*,
|
446
440
|
image: typing.Optional[modal.image.Image] = None,
|
447
441
|
secrets: collections.abc.Sequence[modal.secret.Secret] = (),
|
448
|
-
gpu: typing.Union[
|
449
|
-
None, bool, str, modal.gpu._GPUConfig, list[typing.Union[None, bool, str, modal.gpu._GPUConfig]]
|
450
|
-
] = None,
|
442
|
+
gpu: typing.Union[None, str, modal.gpu._GPUConfig, list[typing.Union[None, str, modal.gpu._GPUConfig]]] = None,
|
451
443
|
serialized: bool = False,
|
452
444
|
mounts: collections.abc.Sequence[modal.mount.Mount] = (),
|
453
445
|
network_file_systems: dict[
|
@@ -493,7 +485,7 @@ class App:
|
|
493
485
|
] = {},
|
494
486
|
timeout: typing.Optional[int] = None,
|
495
487
|
workdir: typing.Optional[str] = None,
|
496
|
-
gpu: typing.Union[None,
|
488
|
+
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
497
489
|
cloud: typing.Optional[str] = None,
|
498
490
|
region: typing.Union[str, collections.abc.Sequence[str], None] = None,
|
499
491
|
cpu: typing.Union[float, tuple[float, float], None] = None,
|
@@ -517,7 +509,7 @@ class App:
|
|
517
509
|
] = {},
|
518
510
|
timeout: typing.Optional[int] = None,
|
519
511
|
workdir: typing.Optional[str] = None,
|
520
|
-
gpu: typing.Union[None,
|
512
|
+
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
521
513
|
cloud: typing.Optional[str] = None,
|
522
514
|
region: typing.Union[str, collections.abc.Sequence[str], None] = None,
|
523
515
|
cpu: typing.Union[float, tuple[float, float], None] = None,
|
modal/client.pyi
CHANGED
@@ -27,7 +27,7 @@ class _Client:
|
|
27
27
|
_snapshotted: bool
|
28
28
|
|
29
29
|
def __init__(
|
30
|
-
self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.73.
|
30
|
+
self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.73.32"
|
31
31
|
): ...
|
32
32
|
def is_closed(self) -> bool: ...
|
33
33
|
@property
|
@@ -85,7 +85,7 @@ class Client:
|
|
85
85
|
_snapshotted: bool
|
86
86
|
|
87
87
|
def __init__(
|
88
|
-
self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.73.
|
88
|
+
self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.73.32"
|
89
89
|
): ...
|
90
90
|
def is_closed(self) -> bool: ...
|
91
91
|
@property
|
modal/cls.pyi
CHANGED
@@ -129,7 +129,7 @@ class _Cls(modal._object._Object):
|
|
129
129
|
self: _Cls,
|
130
130
|
cpu: typing.Union[float, tuple[float, float], None] = None,
|
131
131
|
memory: typing.Union[int, tuple[int, int], None] = None,
|
132
|
-
gpu: typing.Union[None,
|
132
|
+
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
133
133
|
secrets: collections.abc.Collection[modal.secret._Secret] = (),
|
134
134
|
volumes: dict[typing.Union[str, os.PathLike], modal.volume._Volume] = {},
|
135
135
|
retries: typing.Union[int, modal.retries.Retries, None] = None,
|
@@ -187,7 +187,7 @@ class Cls(modal.object.Object):
|
|
187
187
|
self: Cls,
|
188
188
|
cpu: typing.Union[float, tuple[float, float], None] = None,
|
189
189
|
memory: typing.Union[int, tuple[int, int], None] = None,
|
190
|
-
gpu: typing.Union[None,
|
190
|
+
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
191
191
|
secrets: collections.abc.Collection[modal.secret.Secret] = (),
|
192
192
|
volumes: dict[typing.Union[str, os.PathLike], modal.volume.Volume] = {},
|
193
193
|
retries: typing.Union[int, modal.retries.Retries, None] = None,
|
modal/functions.pyi
CHANGED
@@ -64,9 +64,7 @@ class Function(
|
|
64
64
|
secrets: collections.abc.Sequence[modal.secret.Secret] = (),
|
65
65
|
schedule: typing.Optional[modal.schedule.Schedule] = None,
|
66
66
|
is_generator: bool = False,
|
67
|
-
gpu: typing.Union[
|
68
|
-
None, bool, str, modal.gpu._GPUConfig, list[typing.Union[None, bool, str, modal.gpu._GPUConfig]]
|
69
|
-
] = None,
|
67
|
+
gpu: typing.Union[None, str, modal.gpu._GPUConfig, list[typing.Union[None, str, modal.gpu._GPUConfig]]] = None,
|
70
68
|
mounts: collections.abc.Collection[modal.mount.Mount] = (),
|
71
69
|
network_file_systems: dict[
|
72
70
|
typing.Union[str, pathlib.PurePosixPath], modal.network_file_system.NetworkFileSystem
|
modal/gpu.py
CHANGED
@@ -1,17 +1,25 @@
|
|
1
1
|
# Copyright Modal Labs 2022
|
2
|
-
from dataclasses import dataclass
|
3
2
|
from typing import Union
|
4
3
|
|
5
4
|
from modal_proto import api_pb2
|
6
5
|
|
6
|
+
from ._utils.deprecation import deprecation_warning
|
7
7
|
from .exception import InvalidError
|
8
8
|
|
9
9
|
|
10
|
-
@dataclass(frozen=True)
|
11
10
|
class _GPUConfig:
|
12
11
|
gpu_type: str
|
13
12
|
count: int
|
14
13
|
|
14
|
+
def __init__(self, gpu_type: str, count: int):
|
15
|
+
name = self.__class__.__name__
|
16
|
+
str_value = gpu_type
|
17
|
+
if count > 1:
|
18
|
+
str_value += f":{count}"
|
19
|
+
deprecation_warning((2025, 2, 7), f'`gpu={name}(...)` is deprecated. Use `gpu="{str_value}"` instead.')
|
20
|
+
self.gpu_type = gpu_type
|
21
|
+
self.count = count
|
22
|
+
|
15
23
|
def _to_proto(self) -> api_pb2.GPUConfig:
|
16
24
|
"""Convert this GPU config to an internal protobuf representation."""
|
17
25
|
return api_pb2.GPUConfig(
|
@@ -175,10 +183,19 @@ You can see a list of Modal GPU options in the
|
|
175
183
|
def my_gpu_function():
|
176
184
|
... # This will have 4 A100-80GB with each container
|
177
185
|
```
|
186
|
+
|
187
|
+
**Deprecation notes**
|
188
|
+
|
189
|
+
An older deprecated way to configure GPU is also still supported,
|
190
|
+
but will be removed in future versions of Modal. Examples:
|
191
|
+
|
192
|
+
- `gpu=modal.gpu.H100()` will attach 1 H100 GPU to each container
|
193
|
+
- `gpu=modal.gpu.T4(count=4)` will attach 4 T4 GPUs to each container
|
194
|
+
- `gpu=modal.gpu.A100()` will attach 1 A100-40GB GPUs to each container
|
195
|
+
- `gpu=modal.gpu.A100(size="80GB")` will attach 1 A100-80GB GPUs to each container
|
178
196
|
"""
|
179
197
|
|
180
|
-
|
181
|
-
GPU_T = Union[None, bool, str, _GPUConfig]
|
198
|
+
GPU_T = Union[None, str, _GPUConfig]
|
182
199
|
|
183
200
|
|
184
201
|
def parse_gpu_config(value: GPU_T) -> api_pb2.GPUConfig:
|
@@ -197,7 +214,9 @@ def parse_gpu_config(value: GPU_T) -> api_pb2.GPUConfig:
|
|
197
214
|
gpu_type=gpu_type,
|
198
215
|
count=count,
|
199
216
|
)
|
200
|
-
elif value is None
|
217
|
+
elif value is None:
|
201
218
|
return api_pb2.GPUConfig()
|
202
219
|
else:
|
203
|
-
raise InvalidError(
|
220
|
+
raise InvalidError(
|
221
|
+
f"Invalid GPU config: {value}. Value must be a string or `None` (or a deprecated `modal.gpu` object)"
|
222
|
+
)
|
modal/image.pyi
CHANGED
@@ -155,7 +155,7 @@ class _Image(modal._object._Object):
|
|
155
155
|
extra_options: str = "",
|
156
156
|
force_build: bool = False,
|
157
157
|
secrets: collections.abc.Sequence[modal.secret._Secret] = [],
|
158
|
-
gpu: typing.Union[None,
|
158
|
+
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
159
159
|
) -> _Image: ...
|
160
160
|
def pip_install_private_repos(
|
161
161
|
self,
|
@@ -166,7 +166,7 @@ class _Image(modal._object._Object):
|
|
166
166
|
extra_index_url: typing.Optional[str] = None,
|
167
167
|
pre: bool = False,
|
168
168
|
extra_options: str = "",
|
169
|
-
gpu: typing.Union[None,
|
169
|
+
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
170
170
|
secrets: collections.abc.Sequence[modal.secret._Secret] = [],
|
171
171
|
force_build: bool = False,
|
172
172
|
) -> _Image: ...
|
@@ -181,7 +181,7 @@ class _Image(modal._object._Object):
|
|
181
181
|
extra_options: str = "",
|
182
182
|
force_build: bool = False,
|
183
183
|
secrets: collections.abc.Sequence[modal.secret._Secret] = [],
|
184
|
-
gpu: typing.Union[None,
|
184
|
+
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
185
185
|
) -> _Image: ...
|
186
186
|
def pip_install_from_pyproject(
|
187
187
|
self,
|
@@ -195,7 +195,7 @@ class _Image(modal._object._Object):
|
|
195
195
|
extra_options: str = "",
|
196
196
|
force_build: bool = False,
|
197
197
|
secrets: collections.abc.Sequence[modal.secret._Secret] = [],
|
198
|
-
gpu: typing.Union[None,
|
198
|
+
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
199
199
|
) -> _Image: ...
|
200
200
|
def poetry_install_from_file(
|
201
201
|
self,
|
@@ -209,14 +209,14 @@ class _Image(modal._object._Object):
|
|
209
209
|
only: list[str] = [],
|
210
210
|
*,
|
211
211
|
secrets: collections.abc.Sequence[modal.secret._Secret] = [],
|
212
|
-
gpu: typing.Union[None,
|
212
|
+
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
213
213
|
) -> _Image: ...
|
214
214
|
def dockerfile_commands(
|
215
215
|
self,
|
216
216
|
*dockerfile_commands: typing.Union[str, list[str]],
|
217
217
|
context_files: dict[str, str] = {},
|
218
218
|
secrets: collections.abc.Sequence[modal.secret._Secret] = [],
|
219
|
-
gpu: typing.Union[None,
|
219
|
+
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
220
220
|
context_mount: typing.Optional[modal.mount._Mount] = None,
|
221
221
|
force_build: bool = False,
|
222
222
|
ignore: typing.Union[
|
@@ -229,7 +229,7 @@ class _Image(modal._object._Object):
|
|
229
229
|
self,
|
230
230
|
*commands: typing.Union[str, list[str]],
|
231
231
|
secrets: collections.abc.Sequence[modal.secret._Secret] = [],
|
232
|
-
gpu: typing.Union[None,
|
232
|
+
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
233
233
|
force_build: bool = False,
|
234
234
|
) -> _Image: ...
|
235
235
|
@staticmethod
|
@@ -240,7 +240,7 @@ class _Image(modal._object._Object):
|
|
240
240
|
channels: list[str] = [],
|
241
241
|
force_build: bool = False,
|
242
242
|
secrets: collections.abc.Sequence[modal.secret._Secret] = [],
|
243
|
-
gpu: typing.Union[None,
|
243
|
+
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
244
244
|
): ...
|
245
245
|
def conda_update_from_environment(
|
246
246
|
self,
|
@@ -248,7 +248,7 @@ class _Image(modal._object._Object):
|
|
248
248
|
force_build: bool = False,
|
249
249
|
*,
|
250
250
|
secrets: collections.abc.Sequence[modal.secret._Secret] = [],
|
251
|
-
gpu: typing.Union[None,
|
251
|
+
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
252
252
|
): ...
|
253
253
|
@staticmethod
|
254
254
|
def micromamba(python_version: typing.Optional[str] = None, force_build: bool = False) -> _Image: ...
|
@@ -259,7 +259,7 @@ class _Image(modal._object._Object):
|
|
259
259
|
channels: list[str] = [],
|
260
260
|
force_build: bool = False,
|
261
261
|
secrets: collections.abc.Sequence[modal.secret._Secret] = [],
|
262
|
-
gpu: typing.Union[None,
|
262
|
+
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
263
263
|
) -> _Image: ...
|
264
264
|
@staticmethod
|
265
265
|
def _registry_setup_commands(
|
@@ -305,7 +305,7 @@ class _Image(modal._object._Object):
|
|
305
305
|
force_build: bool = False,
|
306
306
|
*,
|
307
307
|
secrets: collections.abc.Sequence[modal.secret._Secret] = [],
|
308
|
-
gpu: typing.Union[None,
|
308
|
+
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
309
309
|
add_python: typing.Optional[str] = None,
|
310
310
|
ignore: typing.Union[
|
311
311
|
collections.abc.Sequence[str], collections.abc.Callable[[pathlib.Path], bool]
|
@@ -318,15 +318,13 @@ class _Image(modal._object._Object):
|
|
318
318
|
*packages: typing.Union[str, list[str]],
|
319
319
|
force_build: bool = False,
|
320
320
|
secrets: collections.abc.Sequence[modal.secret._Secret] = [],
|
321
|
-
gpu: typing.Union[None,
|
321
|
+
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
322
322
|
) -> _Image: ...
|
323
323
|
def run_function(
|
324
324
|
self,
|
325
325
|
raw_f: collections.abc.Callable[..., typing.Any],
|
326
326
|
secrets: collections.abc.Sequence[modal.secret._Secret] = (),
|
327
|
-
gpu: typing.Union[
|
328
|
-
None, bool, str, modal.gpu._GPUConfig, list[typing.Union[None, bool, str, modal.gpu._GPUConfig]]
|
329
|
-
] = None,
|
327
|
+
gpu: typing.Union[None, str, modal.gpu._GPUConfig, list[typing.Union[None, str, modal.gpu._GPUConfig]]] = None,
|
330
328
|
mounts: collections.abc.Sequence[modal.mount._Mount] = (),
|
331
329
|
volumes: dict[
|
332
330
|
typing.Union[str, pathlib.PurePosixPath],
|
@@ -432,7 +430,7 @@ class Image(modal.object.Object):
|
|
432
430
|
extra_options: str = "",
|
433
431
|
force_build: bool = False,
|
434
432
|
secrets: collections.abc.Sequence[modal.secret.Secret] = [],
|
435
|
-
gpu: typing.Union[None,
|
433
|
+
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
436
434
|
) -> Image: ...
|
437
435
|
def pip_install_private_repos(
|
438
436
|
self,
|
@@ -443,7 +441,7 @@ class Image(modal.object.Object):
|
|
443
441
|
extra_index_url: typing.Optional[str] = None,
|
444
442
|
pre: bool = False,
|
445
443
|
extra_options: str = "",
|
446
|
-
gpu: typing.Union[None,
|
444
|
+
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
447
445
|
secrets: collections.abc.Sequence[modal.secret.Secret] = [],
|
448
446
|
force_build: bool = False,
|
449
447
|
) -> Image: ...
|
@@ -458,7 +456,7 @@ class Image(modal.object.Object):
|
|
458
456
|
extra_options: str = "",
|
459
457
|
force_build: bool = False,
|
460
458
|
secrets: collections.abc.Sequence[modal.secret.Secret] = [],
|
461
|
-
gpu: typing.Union[None,
|
459
|
+
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
462
460
|
) -> Image: ...
|
463
461
|
def pip_install_from_pyproject(
|
464
462
|
self,
|
@@ -472,7 +470,7 @@ class Image(modal.object.Object):
|
|
472
470
|
extra_options: str = "",
|
473
471
|
force_build: bool = False,
|
474
472
|
secrets: collections.abc.Sequence[modal.secret.Secret] = [],
|
475
|
-
gpu: typing.Union[None,
|
473
|
+
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
476
474
|
) -> Image: ...
|
477
475
|
def poetry_install_from_file(
|
478
476
|
self,
|
@@ -486,14 +484,14 @@ class Image(modal.object.Object):
|
|
486
484
|
only: list[str] = [],
|
487
485
|
*,
|
488
486
|
secrets: collections.abc.Sequence[modal.secret.Secret] = [],
|
489
|
-
gpu: typing.Union[None,
|
487
|
+
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
490
488
|
) -> Image: ...
|
491
489
|
def dockerfile_commands(
|
492
490
|
self,
|
493
491
|
*dockerfile_commands: typing.Union[str, list[str]],
|
494
492
|
context_files: dict[str, str] = {},
|
495
493
|
secrets: collections.abc.Sequence[modal.secret.Secret] = [],
|
496
|
-
gpu: typing.Union[None,
|
494
|
+
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
497
495
|
context_mount: typing.Optional[modal.mount.Mount] = None,
|
498
496
|
force_build: bool = False,
|
499
497
|
ignore: typing.Union[
|
@@ -506,7 +504,7 @@ class Image(modal.object.Object):
|
|
506
504
|
self,
|
507
505
|
*commands: typing.Union[str, list[str]],
|
508
506
|
secrets: collections.abc.Sequence[modal.secret.Secret] = [],
|
509
|
-
gpu: typing.Union[None,
|
507
|
+
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
510
508
|
force_build: bool = False,
|
511
509
|
) -> Image: ...
|
512
510
|
@staticmethod
|
@@ -517,7 +515,7 @@ class Image(modal.object.Object):
|
|
517
515
|
channels: list[str] = [],
|
518
516
|
force_build: bool = False,
|
519
517
|
secrets: collections.abc.Sequence[modal.secret.Secret] = [],
|
520
|
-
gpu: typing.Union[None,
|
518
|
+
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
521
519
|
): ...
|
522
520
|
def conda_update_from_environment(
|
523
521
|
self,
|
@@ -525,7 +523,7 @@ class Image(modal.object.Object):
|
|
525
523
|
force_build: bool = False,
|
526
524
|
*,
|
527
525
|
secrets: collections.abc.Sequence[modal.secret.Secret] = [],
|
528
|
-
gpu: typing.Union[None,
|
526
|
+
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
529
527
|
): ...
|
530
528
|
@staticmethod
|
531
529
|
def micromamba(python_version: typing.Optional[str] = None, force_build: bool = False) -> Image: ...
|
@@ -536,7 +534,7 @@ class Image(modal.object.Object):
|
|
536
534
|
channels: list[str] = [],
|
537
535
|
force_build: bool = False,
|
538
536
|
secrets: collections.abc.Sequence[modal.secret.Secret] = [],
|
539
|
-
gpu: typing.Union[None,
|
537
|
+
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
540
538
|
) -> Image: ...
|
541
539
|
@staticmethod
|
542
540
|
def _registry_setup_commands(
|
@@ -582,7 +580,7 @@ class Image(modal.object.Object):
|
|
582
580
|
force_build: bool = False,
|
583
581
|
*,
|
584
582
|
secrets: collections.abc.Sequence[modal.secret.Secret] = [],
|
585
|
-
gpu: typing.Union[None,
|
583
|
+
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
586
584
|
add_python: typing.Optional[str] = None,
|
587
585
|
ignore: typing.Union[
|
588
586
|
collections.abc.Sequence[str], collections.abc.Callable[[pathlib.Path], bool]
|
@@ -595,15 +593,13 @@ class Image(modal.object.Object):
|
|
595
593
|
*packages: typing.Union[str, list[str]],
|
596
594
|
force_build: bool = False,
|
597
595
|
secrets: collections.abc.Sequence[modal.secret.Secret] = [],
|
598
|
-
gpu: typing.Union[None,
|
596
|
+
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
599
597
|
) -> Image: ...
|
600
598
|
def run_function(
|
601
599
|
self,
|
602
600
|
raw_f: collections.abc.Callable[..., typing.Any],
|
603
601
|
secrets: collections.abc.Sequence[modal.secret.Secret] = (),
|
604
|
-
gpu: typing.Union[
|
605
|
-
None, bool, str, modal.gpu._GPUConfig, list[typing.Union[None, bool, str, modal.gpu._GPUConfig]]
|
606
|
-
] = None,
|
602
|
+
gpu: typing.Union[None, str, modal.gpu._GPUConfig, list[typing.Union[None, str, modal.gpu._GPUConfig]]] = None,
|
607
603
|
mounts: collections.abc.Sequence[modal.mount.Mount] = (),
|
608
604
|
volumes: dict[
|
609
605
|
typing.Union[str, pathlib.PurePosixPath],
|
modal/sandbox.py
CHANGED
@@ -42,10 +42,28 @@ from .stream_type import StreamType
|
|
42
42
|
_default_image: _Image = _Image.debian_slim()
|
43
43
|
|
44
44
|
|
45
|
+
# The maximum number of bytes that can be passed to an exec on Linux.
|
46
|
+
# Though this is technically a 'server side' limit, it is unlikely to change.
|
47
|
+
# getconf ARG_MAX will show this value on a host.
|
48
|
+
ARG_MAX_BYTES = 2_097_152 # 2MiB
|
49
|
+
|
45
50
|
if TYPE_CHECKING:
|
46
51
|
import modal.app
|
47
52
|
|
48
53
|
|
54
|
+
def _validate_exec_args(entrypoint_args: Sequence[str]) -> None:
|
55
|
+
# Entrypoint args must be strings.
|
56
|
+
if not all(isinstance(arg, str) for arg in entrypoint_args):
|
57
|
+
raise InvalidError("All entrypoint arguments must be strings")
|
58
|
+
# Avoid "[Errno 7] Argument list too long" errors.
|
59
|
+
total_arg_len = sum(len(arg) for arg in entrypoint_args)
|
60
|
+
if total_arg_len > ARG_MAX_BYTES:
|
61
|
+
raise InvalidError(
|
62
|
+
f"Total length of entrypoint arguments must be less than {ARG_MAX_BYTES} bytes (ARG_MAX). "
|
63
|
+
f"Got {total_arg_len} bytes."
|
64
|
+
)
|
65
|
+
|
66
|
+
|
49
67
|
class _Sandbox(_Object, type_prefix="sb"):
|
50
68
|
"""A `Sandbox` object lets you interact with a running sandbox. This API is similar to Python's
|
51
69
|
[asyncio.subprocess.Process](https://docs.python.org/3/library/asyncio-subprocess.html#asyncio.subprocess.Process).
|
@@ -245,6 +263,8 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
245
263
|
max_sleep_time = 60 * 60 * 24 * 2 # 2 days is plenty since workers roll every 24h
|
246
264
|
entrypoint_args = ("sleep", str(max_sleep_time))
|
247
265
|
|
266
|
+
_validate_exec_args(entrypoint_args)
|
267
|
+
|
248
268
|
# TODO(erikbern): Get rid of the `_new` method and create an already-hydrated object
|
249
269
|
obj = _Sandbox._new(
|
250
270
|
entrypoint_args,
|
@@ -521,6 +541,7 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
521
541
|
|
522
542
|
if workdir is not None and not workdir.startswith("/"):
|
523
543
|
raise InvalidError(f"workdir must be an absolute path, got: {workdir}")
|
544
|
+
_validate_exec_args(cmds)
|
524
545
|
|
525
546
|
# Force secret resolution so we can pass the secret IDs to the backend.
|
526
547
|
secret_coros = [secret.hydrate(client=self._client) for secret in secrets]
|
modal/sandbox.pyi
CHANGED
@@ -25,6 +25,8 @@ import os
|
|
25
25
|
import typing
|
26
26
|
import typing_extensions
|
27
27
|
|
28
|
+
def _validate_exec_args(entrypoint_args: collections.abc.Sequence[str]) -> None: ...
|
29
|
+
|
28
30
|
class _Sandbox(modal._object._Object):
|
29
31
|
_result: typing.Optional[modal_proto.api_pb2.GenericResult]
|
30
32
|
_stdout: modal.io_streams._StreamReader[str]
|
@@ -42,7 +44,7 @@ class _Sandbox(modal._object._Object):
|
|
42
44
|
secrets: collections.abc.Sequence[modal.secret._Secret],
|
43
45
|
timeout: typing.Optional[int] = None,
|
44
46
|
workdir: typing.Optional[str] = None,
|
45
|
-
gpu: typing.Union[None,
|
47
|
+
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
46
48
|
cloud: typing.Optional[str] = None,
|
47
49
|
region: typing.Union[str, collections.abc.Sequence[str], None] = None,
|
48
50
|
cpu: typing.Optional[float] = None,
|
@@ -72,7 +74,7 @@ class _Sandbox(modal._object._Object):
|
|
72
74
|
network_file_systems: dict[typing.Union[str, os.PathLike], modal.network_file_system._NetworkFileSystem] = {},
|
73
75
|
timeout: typing.Optional[int] = None,
|
74
76
|
workdir: typing.Optional[str] = None,
|
75
|
-
gpu: typing.Union[None,
|
77
|
+
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
76
78
|
cloud: typing.Optional[str] = None,
|
77
79
|
region: typing.Union[str, collections.abc.Sequence[str], None] = None,
|
78
80
|
cpu: typing.Union[float, tuple[float, float], None] = None,
|
@@ -184,7 +186,7 @@ class Sandbox(modal.object.Object):
|
|
184
186
|
secrets: collections.abc.Sequence[modal.secret.Secret],
|
185
187
|
timeout: typing.Optional[int] = None,
|
186
188
|
workdir: typing.Optional[str] = None,
|
187
|
-
gpu: typing.Union[None,
|
189
|
+
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
188
190
|
cloud: typing.Optional[str] = None,
|
189
191
|
region: typing.Union[str, collections.abc.Sequence[str], None] = None,
|
190
192
|
cpu: typing.Optional[float] = None,
|
@@ -217,7 +219,7 @@ class Sandbox(modal.object.Object):
|
|
217
219
|
] = {},
|
218
220
|
timeout: typing.Optional[int] = None,
|
219
221
|
workdir: typing.Optional[str] = None,
|
220
|
-
gpu: typing.Union[None,
|
222
|
+
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
221
223
|
cloud: typing.Optional[str] = None,
|
222
224
|
region: typing.Union[str, collections.abc.Sequence[str], None] = None,
|
223
225
|
cpu: typing.Union[float, tuple[float, float], None] = None,
|
@@ -249,7 +251,7 @@ class Sandbox(modal.object.Object):
|
|
249
251
|
] = {},
|
250
252
|
timeout: typing.Optional[int] = None,
|
251
253
|
workdir: typing.Optional[str] = None,
|
252
|
-
gpu: typing.Union[None,
|
254
|
+
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
253
255
|
cloud: typing.Optional[str] = None,
|
254
256
|
region: typing.Union[str, collections.abc.Sequence[str], None] = None,
|
255
257
|
cpu: typing.Union[float, tuple[float, float], None] = None,
|
@@ -19,14 +19,14 @@ modal/_tunnel.py,sha256=zTBxBiuH1O22tS1OliAJdIsSmaZS8PlnifS_6S5z-mk,6320
|
|
19
19
|
modal/_tunnel.pyi,sha256=JmmDYAy9F1FpgJ_hWx0xkom2nTOFQjn4mTPYlU3PFo4,1245
|
20
20
|
modal/_watcher.py,sha256=K6LYnlmSGQB4tWWI9JADv-tvSvQ1j522FwT71B51CX8,3584
|
21
21
|
modal/app.py,sha256=rCOPD51gVyow8muyaqMuV65qfTnAZKf_w1OCZdSF_6o,44636
|
22
|
-
modal/app.pyi,sha256=
|
22
|
+
modal/app.pyi,sha256=0MMCgskIL4r3eq8oBcfm2lLyeao2gXjS3iXaIfmaJ-o,25959
|
23
23
|
modal/call_graph.py,sha256=1g2DGcMIJvRy-xKicuf63IVE98gJSnQsr8R_NVMptNc,2581
|
24
24
|
modal/client.py,sha256=8SQawr7P1PNUCq1UmJMUQXG2jIo4Nmdcs311XqrNLRE,15276
|
25
|
-
modal/client.pyi,sha256=
|
25
|
+
modal/client.pyi,sha256=pxFu0T3BrokSyDj5XWlvDeV8k35RQo60dwVV3PQ5jh0,7593
|
26
26
|
modal/cloud_bucket_mount.py,sha256=YOe9nnvSr4ZbeCn587d7_VhE9IioZYRvF9VYQTQux08,5914
|
27
27
|
modal/cloud_bucket_mount.pyi,sha256=30T3K1a89l6wzmEJ_J9iWv9SknoGqaZDx59Xs-ZQcmk,1607
|
28
28
|
modal/cls.py,sha256=5Er9L9tGpLGIrbiHOI7c9266gPG6nhxoJ_BX8op96nU,31096
|
29
|
-
modal/cls.pyi,sha256=
|
29
|
+
modal/cls.pyi,sha256=QqYoRKVCKhP_HkHittKpEZ6sqXkEdtEl4n1wMqeoe3M,8897
|
30
30
|
modal/config.py,sha256=XT1W4Y9PVkbYMAXjJRshvQEPDhZmnfW_ZRMwl8XKoqA,11149
|
31
31
|
modal/container_process.py,sha256=WTqLn01dJPVkPpwR_0w_JH96ceN5mV4TGtiu1ZR2RRA,6108
|
32
32
|
modal/container_process.pyi,sha256=Hf0J5JyDdCCXBJSKx6gvkPOo0XrztCm78xzxamtzUjQ,2828
|
@@ -41,10 +41,10 @@ modal/file_io.py,sha256=lcMs_E9Xfm0YX1t9U2wNIBPnqHRxmImqjLW1GHqVmyg,20945
|
|
41
41
|
modal/file_io.pyi,sha256=NTRft1tbPSWf9TlWVeZmTlgB5AZ_Zhu2srWIrWr7brk,9445
|
42
42
|
modal/file_pattern_matcher.py,sha256=trosX-Bp7dOubudN1bLLhRAoidWy1TcoaR4Pv8CedWw,6497
|
43
43
|
modal/functions.py,sha256=kcNHvqeGBxPI7Cgd57NIBBghkfbeFJzXO44WW0jSmao,325
|
44
|
-
modal/functions.pyi,sha256=
|
45
|
-
modal/gpu.py,sha256=
|
44
|
+
modal/functions.pyi,sha256=B6sPrnpt34Z_DVz_5SpHV7NVpfk2nTXuS215Xcu4kK0,14255
|
45
|
+
modal/gpu.py,sha256=Kbhs_u49FaC2Zi0TjCdrpstpRtT5eZgecynmQi5IZVE,6752
|
46
46
|
modal/image.py,sha256=KYc6bg-m9A6wiLF38dWcFBMrEATyR2KOF0sp-6O9uC0,91508
|
47
|
-
modal/image.pyi,sha256=
|
47
|
+
modal/image.pyi,sha256=kMkIDHcyyhA7BC2Vrx0RfrLEsqK8Ng2-IqUKL-CJexI,26250
|
48
48
|
modal/io_streams.py,sha256=QkQiizKRzd5bnbKQsap31LJgBYlAnj4-XkV_50xPYX0,15079
|
49
49
|
modal/io_streams.pyi,sha256=bJ7ZLmSmJ0nKoa6r4FJpbqvzdUVa0lEe0Fa-MMpMezU,5071
|
50
50
|
modal/mount.py,sha256=hNoy7J-E2C-CkSmbKldfL_zg8db8nP8cVzRj_35Rsp0,32124
|
@@ -67,8 +67,8 @@ modal/retries.py,sha256=HKR2Q9aNPWkMjQ5nwobqYTuZaSuw0a8lI2zrtY5IW98,5230
|
|
67
67
|
modal/runner.py,sha256=fdUyDGN-bWu_aZBvxBO_MIgEuucsA0PgDKDHBn5k8J0,24451
|
68
68
|
modal/runner.pyi,sha256=RYEYsnofrvVroYefWLhWAy8I_uwXV9fRNuJaVgcNzrg,5278
|
69
69
|
modal/running_app.py,sha256=v61mapYNV1-O-Uaho5EfJlryMLvIT9We0amUOSvSGx8,1188
|
70
|
-
modal/sandbox.py,sha256=
|
71
|
-
modal/sandbox.pyi,sha256=
|
70
|
+
modal/sandbox.py,sha256=Vp-LlqbeRz4HNAFQW2oIh9RlfsurUyp5bKKUuKEGlMQ,32670
|
71
|
+
modal/sandbox.pyi,sha256=cLmSwI1ab-2DgEuXNf6S1PiK63wfUR9dHtxlZtSOuX8,22719
|
72
72
|
modal/schedule.py,sha256=0ZFpKs1bOxeo5n3HZjoL7OE2ktsb-_oGtq-WJEPO4tY,2615
|
73
73
|
modal/scheduler_placement.py,sha256=BAREdOY5HzHpzSBqt6jDVR6YC_jYfHMVqOzkyqQfngU,1235
|
74
74
|
modal/secret.py,sha256=U2Jivqdb94eI_BrGCMVbCots8F2gDcbXLMia_gVlej0,10455
|
@@ -172,10 +172,10 @@ modal_proto/options_pb2_grpc.pyi,sha256=CImmhxHsYnF09iENPoe8S4J-n93jtgUYD2JPAc0y
|
|
172
172
|
modal_proto/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
173
173
|
modal_version/__init__.py,sha256=wiJQ53c-OMs0Xf1UeXOxQ7FwlV1VzIjnX6o-pRYZ_Pk,470
|
174
174
|
modal_version/__main__.py,sha256=2FO0yYQQwDTh6udt1h-cBnGd1c4ZyHnHSI4BksxzVac,105
|
175
|
-
modal_version/_version_generated.py,sha256=
|
176
|
-
modal-0.73.
|
177
|
-
modal-0.73.
|
178
|
-
modal-0.73.
|
179
|
-
modal-0.73.
|
180
|
-
modal-0.73.
|
181
|
-
modal-0.73.
|
175
|
+
modal_version/_version_generated.py,sha256=qB711bhl6L8MqhOCkiWQLqBZrWYWZ-dYKuWSPvtQmec,149
|
176
|
+
modal-0.73.32.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
|
177
|
+
modal-0.73.32.dist-info/METADATA,sha256=MUHy26_qys8dtiKDfQ_fcHmgDnbWcpgAOWKx0mEqdFw,2330
|
178
|
+
modal-0.73.32.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
|
179
|
+
modal-0.73.32.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
|
180
|
+
modal-0.73.32.dist-info/top_level.txt,sha256=1nvYbOSIKcmU50fNrpnQnrrOpj269ei3LzgB6j9xGqg,64
|
181
|
+
modal-0.73.32.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|