modal 1.1.5.dev20__py3-none-any.whl → 1.1.5.dev21__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/_functions.py +12 -4
- modal/app.py +12 -3
- modal/app.pyi +8 -4
- modal/client.pyi +2 -2
- modal/cls.py +7 -2
- modal/cls.pyi +7 -5
- modal/functions.pyi +12 -8
- modal/image.py +85 -15
- modal/image.pyi +54 -28
- modal/sandbox.py +31 -14
- modal/sandbox.pyi +32 -17
- modal/secret.py +1 -1
- {modal-1.1.5.dev20.dist-info → modal-1.1.5.dev21.dist-info}/METADATA +1 -1
- {modal-1.1.5.dev20.dist-info → modal-1.1.5.dev21.dist-info}/RECORD +19 -19
- modal_version/__init__.py +1 -1
- {modal-1.1.5.dev20.dist-info → modal-1.1.5.dev21.dist-info}/WHEEL +0 -0
- {modal-1.1.5.dev20.dist-info → modal-1.1.5.dev21.dist-info}/entry_points.txt +0 -0
- {modal-1.1.5.dev20.dist-info → modal-1.1.5.dev21.dist-info}/licenses/LICENSE +0 -0
- {modal-1.1.5.dev20.dist-info → modal-1.1.5.dev21.dist-info}/top_level.txt +0 -0
modal/image.pyi
CHANGED
|
@@ -166,7 +166,7 @@ class _Image(modal._object._Object):
|
|
|
166
166
|
[typing.Literal["2023.12", "2024.04", "2024.10", "2025.06", "PREVIEW"]], DockerfileSpec
|
|
167
167
|
]
|
|
168
168
|
] = None,
|
|
169
|
-
secrets: typing.Optional[collections.abc.
|
|
169
|
+
secrets: typing.Optional[collections.abc.Collection[modal.secret._Secret]] = None,
|
|
170
170
|
gpu_config: typing.Optional[modal_proto.api_pb2.GPUConfig] = None,
|
|
171
171
|
build_function: typing.Optional[modal._functions._Function] = None,
|
|
172
172
|
build_function_input: typing.Optional[modal_proto.api_pb2.FunctionInput] = None,
|
|
@@ -327,7 +327,8 @@ class _Image(modal._object._Object):
|
|
|
327
327
|
pre: bool = False,
|
|
328
328
|
extra_options: str = "",
|
|
329
329
|
force_build: bool = False,
|
|
330
|
-
|
|
330
|
+
env: typing.Optional[dict[str, typing.Optional[str]]] = None,
|
|
331
|
+
secrets: typing.Optional[collections.abc.Collection[modal.secret._Secret]] = None,
|
|
331
332
|
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
|
332
333
|
) -> _Image:
|
|
333
334
|
"""Install a list of Python packages using pip.
|
|
@@ -369,7 +370,8 @@ class _Image(modal._object._Object):
|
|
|
369
370
|
pre: bool = False,
|
|
370
371
|
extra_options: str = "",
|
|
371
372
|
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
|
372
|
-
|
|
373
|
+
env: typing.Optional[dict[str, typing.Optional[str]]] = None,
|
|
374
|
+
secrets: typing.Optional[collections.abc.Collection[modal.secret._Secret]] = None,
|
|
373
375
|
force_build: bool = False,
|
|
374
376
|
) -> _Image:
|
|
375
377
|
"""Install a list of Python packages from private git repositories using pip.
|
|
@@ -414,7 +416,8 @@ class _Image(modal._object._Object):
|
|
|
414
416
|
pre: bool = False,
|
|
415
417
|
extra_options: str = "",
|
|
416
418
|
force_build: bool = False,
|
|
417
|
-
|
|
419
|
+
env: typing.Optional[dict[str, typing.Optional[str]]] = None,
|
|
420
|
+
secrets: typing.Optional[collections.abc.Collection[modal.secret._Secret]] = None,
|
|
418
421
|
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
|
419
422
|
) -> _Image:
|
|
420
423
|
"""Install a list of Python packages from a local `requirements.txt` file."""
|
|
@@ -431,7 +434,8 @@ class _Image(modal._object._Object):
|
|
|
431
434
|
pre: bool = False,
|
|
432
435
|
extra_options: str = "",
|
|
433
436
|
force_build: bool = False,
|
|
434
|
-
|
|
437
|
+
env: typing.Optional[dict[str, typing.Optional[str]]] = None,
|
|
438
|
+
secrets: typing.Optional[collections.abc.Collection[modal.secret._Secret]] = None,
|
|
435
439
|
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
|
436
440
|
) -> _Image:
|
|
437
441
|
"""Install dependencies specified by a local `pyproject.toml` file.
|
|
@@ -454,7 +458,8 @@ class _Image(modal._object._Object):
|
|
|
454
458
|
extra_options: str = "",
|
|
455
459
|
force_build: bool = False,
|
|
456
460
|
uv_version: typing.Optional[str] = None,
|
|
457
|
-
|
|
461
|
+
env: typing.Optional[dict[str, typing.Optional[str]]] = None,
|
|
462
|
+
secrets: typing.Optional[collections.abc.Collection[modal.secret._Secret]] = None,
|
|
458
463
|
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
|
459
464
|
) -> _Image:
|
|
460
465
|
"""Install a list of Python packages using uv pip install.
|
|
@@ -487,7 +492,8 @@ class _Image(modal._object._Object):
|
|
|
487
492
|
only: list[str] = [],
|
|
488
493
|
poetry_version: typing.Optional[str] = "latest",
|
|
489
494
|
old_installer: bool = False,
|
|
490
|
-
|
|
495
|
+
env: typing.Optional[dict[str, typing.Optional[str]]] = None,
|
|
496
|
+
secrets: typing.Optional[collections.abc.Collection[modal.secret._Secret]] = None,
|
|
491
497
|
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
|
492
498
|
) -> _Image:
|
|
493
499
|
"""Install poetry *dependencies* specified by a local `pyproject.toml` file.
|
|
@@ -514,7 +520,8 @@ class _Image(modal._object._Object):
|
|
|
514
520
|
frozen: bool = True,
|
|
515
521
|
extra_options: str = "",
|
|
516
522
|
uv_version: typing.Optional[str] = None,
|
|
517
|
-
|
|
523
|
+
env: typing.Optional[dict[str, typing.Optional[str]]] = None,
|
|
524
|
+
secrets: typing.Optional[collections.abc.Collection[modal.secret._Secret]] = None,
|
|
518
525
|
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
|
519
526
|
) -> _Image:
|
|
520
527
|
"""Creates a virtual environment with the dependencies in a uv managed project with `uv sync`.
|
|
@@ -535,7 +542,8 @@ class _Image(modal._object._Object):
|
|
|
535
542
|
self,
|
|
536
543
|
*dockerfile_commands: typing.Union[str, list[str]],
|
|
537
544
|
context_files: dict[str, str] = {},
|
|
538
|
-
|
|
545
|
+
env: typing.Optional[dict[str, typing.Optional[str]]] = None,
|
|
546
|
+
secrets: typing.Optional[collections.abc.Collection[modal.secret._Secret]] = None,
|
|
539
547
|
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
|
540
548
|
context_mount: typing.Optional[modal.mount._Mount] = None,
|
|
541
549
|
context_dir: typing.Union[str, pathlib.Path, None] = None,
|
|
@@ -597,7 +605,8 @@ class _Image(modal._object._Object):
|
|
|
597
605
|
def run_commands(
|
|
598
606
|
self,
|
|
599
607
|
*commands: typing.Union[str, list[str]],
|
|
600
|
-
|
|
608
|
+
env: typing.Optional[dict[str, typing.Optional[str]]] = None,
|
|
609
|
+
secrets: typing.Optional[collections.abc.Collection[modal.secret._Secret]] = None,
|
|
601
610
|
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
|
602
611
|
force_build: bool = False,
|
|
603
612
|
) -> _Image:
|
|
@@ -615,7 +624,8 @@ class _Image(modal._object._Object):
|
|
|
615
624
|
spec_file: typing.Optional[str] = None,
|
|
616
625
|
channels: list[str] = [],
|
|
617
626
|
force_build: bool = False,
|
|
618
|
-
|
|
627
|
+
env: typing.Optional[dict[str, typing.Optional[str]]] = None,
|
|
628
|
+
secrets: typing.Optional[collections.abc.Collection[modal.secret._Secret]] = None,
|
|
619
629
|
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
|
620
630
|
) -> _Image:
|
|
621
631
|
"""Install a list of additional packages using micromamba."""
|
|
@@ -756,7 +766,8 @@ class _Image(modal._object._Object):
|
|
|
756
766
|
context_mount: typing.Optional[modal.mount._Mount] = None,
|
|
757
767
|
force_build: bool = False,
|
|
758
768
|
context_dir: typing.Union[str, pathlib.Path, None] = None,
|
|
759
|
-
|
|
769
|
+
env: typing.Optional[dict[str, typing.Optional[str]]] = None,
|
|
770
|
+
secrets: typing.Optional[collections.abc.Collection[modal.secret._Secret]] = None,
|
|
760
771
|
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
|
761
772
|
add_python: typing.Optional[str] = None,
|
|
762
773
|
build_args: dict[str, str] = {},
|
|
@@ -824,7 +835,8 @@ class _Image(modal._object._Object):
|
|
|
824
835
|
self,
|
|
825
836
|
*packages: typing.Union[str, list[str]],
|
|
826
837
|
force_build: bool = False,
|
|
827
|
-
|
|
838
|
+
env: typing.Optional[dict[str, typing.Optional[str]]] = None,
|
|
839
|
+
secrets: typing.Optional[collections.abc.Collection[modal.secret._Secret]] = None,
|
|
828
840
|
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
|
829
841
|
) -> _Image:
|
|
830
842
|
"""Install a list of Debian packages using `apt`.
|
|
@@ -841,7 +853,8 @@ class _Image(modal._object._Object):
|
|
|
841
853
|
self,
|
|
842
854
|
raw_f: collections.abc.Callable[..., typing.Any],
|
|
843
855
|
*,
|
|
844
|
-
|
|
856
|
+
env: typing.Optional[dict[str, typing.Optional[str]]] = None,
|
|
857
|
+
secrets: typing.Optional[collections.abc.Collection[modal.secret._Secret]] = None,
|
|
845
858
|
volumes: dict[
|
|
846
859
|
typing.Union[str, pathlib.PurePosixPath],
|
|
847
860
|
typing.Union[modal.volume._Volume, modal.cloud_bucket_mount._CloudBucketMount],
|
|
@@ -1008,7 +1021,7 @@ class Image(modal.object.Object):
|
|
|
1008
1021
|
[typing.Literal["2023.12", "2024.04", "2024.10", "2025.06", "PREVIEW"]], DockerfileSpec
|
|
1009
1022
|
]
|
|
1010
1023
|
] = None,
|
|
1011
|
-
secrets: typing.Optional[collections.abc.
|
|
1024
|
+
secrets: typing.Optional[collections.abc.Collection[modal.secret.Secret]] = None,
|
|
1012
1025
|
gpu_config: typing.Optional[modal_proto.api_pb2.GPUConfig] = None,
|
|
1013
1026
|
build_function: typing.Optional[modal.functions.Function] = None,
|
|
1014
1027
|
build_function_input: typing.Optional[modal_proto.api_pb2.FunctionInput] = None,
|
|
@@ -1178,7 +1191,8 @@ class Image(modal.object.Object):
|
|
|
1178
1191
|
pre: bool = False,
|
|
1179
1192
|
extra_options: str = "",
|
|
1180
1193
|
force_build: bool = False,
|
|
1181
|
-
|
|
1194
|
+
env: typing.Optional[dict[str, typing.Optional[str]]] = None,
|
|
1195
|
+
secrets: typing.Optional[collections.abc.Collection[modal.secret.Secret]] = None,
|
|
1182
1196
|
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
|
1183
1197
|
) -> Image:
|
|
1184
1198
|
"""Install a list of Python packages using pip.
|
|
@@ -1220,7 +1234,8 @@ class Image(modal.object.Object):
|
|
|
1220
1234
|
pre: bool = False,
|
|
1221
1235
|
extra_options: str = "",
|
|
1222
1236
|
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
|
1223
|
-
|
|
1237
|
+
env: typing.Optional[dict[str, typing.Optional[str]]] = None,
|
|
1238
|
+
secrets: typing.Optional[collections.abc.Collection[modal.secret.Secret]] = None,
|
|
1224
1239
|
force_build: bool = False,
|
|
1225
1240
|
) -> Image:
|
|
1226
1241
|
"""Install a list of Python packages from private git repositories using pip.
|
|
@@ -1265,7 +1280,8 @@ class Image(modal.object.Object):
|
|
|
1265
1280
|
pre: bool = False,
|
|
1266
1281
|
extra_options: str = "",
|
|
1267
1282
|
force_build: bool = False,
|
|
1268
|
-
|
|
1283
|
+
env: typing.Optional[dict[str, typing.Optional[str]]] = None,
|
|
1284
|
+
secrets: typing.Optional[collections.abc.Collection[modal.secret.Secret]] = None,
|
|
1269
1285
|
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
|
1270
1286
|
) -> Image:
|
|
1271
1287
|
"""Install a list of Python packages from a local `requirements.txt` file."""
|
|
@@ -1282,7 +1298,8 @@ class Image(modal.object.Object):
|
|
|
1282
1298
|
pre: bool = False,
|
|
1283
1299
|
extra_options: str = "",
|
|
1284
1300
|
force_build: bool = False,
|
|
1285
|
-
|
|
1301
|
+
env: typing.Optional[dict[str, typing.Optional[str]]] = None,
|
|
1302
|
+
secrets: typing.Optional[collections.abc.Collection[modal.secret.Secret]] = None,
|
|
1286
1303
|
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
|
1287
1304
|
) -> Image:
|
|
1288
1305
|
"""Install dependencies specified by a local `pyproject.toml` file.
|
|
@@ -1305,7 +1322,8 @@ class Image(modal.object.Object):
|
|
|
1305
1322
|
extra_options: str = "",
|
|
1306
1323
|
force_build: bool = False,
|
|
1307
1324
|
uv_version: typing.Optional[str] = None,
|
|
1308
|
-
|
|
1325
|
+
env: typing.Optional[dict[str, typing.Optional[str]]] = None,
|
|
1326
|
+
secrets: typing.Optional[collections.abc.Collection[modal.secret.Secret]] = None,
|
|
1309
1327
|
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
|
1310
1328
|
) -> Image:
|
|
1311
1329
|
"""Install a list of Python packages using uv pip install.
|
|
@@ -1338,7 +1356,8 @@ class Image(modal.object.Object):
|
|
|
1338
1356
|
only: list[str] = [],
|
|
1339
1357
|
poetry_version: typing.Optional[str] = "latest",
|
|
1340
1358
|
old_installer: bool = False,
|
|
1341
|
-
|
|
1359
|
+
env: typing.Optional[dict[str, typing.Optional[str]]] = None,
|
|
1360
|
+
secrets: typing.Optional[collections.abc.Collection[modal.secret.Secret]] = None,
|
|
1342
1361
|
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
|
1343
1362
|
) -> Image:
|
|
1344
1363
|
"""Install poetry *dependencies* specified by a local `pyproject.toml` file.
|
|
@@ -1365,7 +1384,8 @@ class Image(modal.object.Object):
|
|
|
1365
1384
|
frozen: bool = True,
|
|
1366
1385
|
extra_options: str = "",
|
|
1367
1386
|
uv_version: typing.Optional[str] = None,
|
|
1368
|
-
|
|
1387
|
+
env: typing.Optional[dict[str, typing.Optional[str]]] = None,
|
|
1388
|
+
secrets: typing.Optional[collections.abc.Collection[modal.secret.Secret]] = None,
|
|
1369
1389
|
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
|
1370
1390
|
) -> Image:
|
|
1371
1391
|
"""Creates a virtual environment with the dependencies in a uv managed project with `uv sync`.
|
|
@@ -1386,7 +1406,8 @@ class Image(modal.object.Object):
|
|
|
1386
1406
|
self,
|
|
1387
1407
|
*dockerfile_commands: typing.Union[str, list[str]],
|
|
1388
1408
|
context_files: dict[str, str] = {},
|
|
1389
|
-
|
|
1409
|
+
env: typing.Optional[dict[str, typing.Optional[str]]] = None,
|
|
1410
|
+
secrets: typing.Optional[collections.abc.Collection[modal.secret.Secret]] = None,
|
|
1390
1411
|
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
|
1391
1412
|
context_mount: typing.Optional[modal.mount.Mount] = None,
|
|
1392
1413
|
context_dir: typing.Union[str, pathlib.Path, None] = None,
|
|
@@ -1448,7 +1469,8 @@ class Image(modal.object.Object):
|
|
|
1448
1469
|
def run_commands(
|
|
1449
1470
|
self,
|
|
1450
1471
|
*commands: typing.Union[str, list[str]],
|
|
1451
|
-
|
|
1472
|
+
env: typing.Optional[dict[str, typing.Optional[str]]] = None,
|
|
1473
|
+
secrets: typing.Optional[collections.abc.Collection[modal.secret.Secret]] = None,
|
|
1452
1474
|
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
|
1453
1475
|
force_build: bool = False,
|
|
1454
1476
|
) -> Image:
|
|
@@ -1466,7 +1488,8 @@ class Image(modal.object.Object):
|
|
|
1466
1488
|
spec_file: typing.Optional[str] = None,
|
|
1467
1489
|
channels: list[str] = [],
|
|
1468
1490
|
force_build: bool = False,
|
|
1469
|
-
|
|
1491
|
+
env: typing.Optional[dict[str, typing.Optional[str]]] = None,
|
|
1492
|
+
secrets: typing.Optional[collections.abc.Collection[modal.secret.Secret]] = None,
|
|
1470
1493
|
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
|
1471
1494
|
) -> Image:
|
|
1472
1495
|
"""Install a list of additional packages using micromamba."""
|
|
@@ -1607,7 +1630,8 @@ class Image(modal.object.Object):
|
|
|
1607
1630
|
context_mount: typing.Optional[modal.mount.Mount] = None,
|
|
1608
1631
|
force_build: bool = False,
|
|
1609
1632
|
context_dir: typing.Union[str, pathlib.Path, None] = None,
|
|
1610
|
-
|
|
1633
|
+
env: typing.Optional[dict[str, typing.Optional[str]]] = None,
|
|
1634
|
+
secrets: typing.Optional[collections.abc.Collection[modal.secret.Secret]] = None,
|
|
1611
1635
|
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
|
1612
1636
|
add_python: typing.Optional[str] = None,
|
|
1613
1637
|
build_args: dict[str, str] = {},
|
|
@@ -1675,7 +1699,8 @@ class Image(modal.object.Object):
|
|
|
1675
1699
|
self,
|
|
1676
1700
|
*packages: typing.Union[str, list[str]],
|
|
1677
1701
|
force_build: bool = False,
|
|
1678
|
-
|
|
1702
|
+
env: typing.Optional[dict[str, typing.Optional[str]]] = None,
|
|
1703
|
+
secrets: typing.Optional[collections.abc.Collection[modal.secret.Secret]] = None,
|
|
1679
1704
|
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
|
1680
1705
|
) -> Image:
|
|
1681
1706
|
"""Install a list of Debian packages using `apt`.
|
|
@@ -1692,7 +1717,8 @@ class Image(modal.object.Object):
|
|
|
1692
1717
|
self,
|
|
1693
1718
|
raw_f: collections.abc.Callable[..., typing.Any],
|
|
1694
1719
|
*,
|
|
1695
|
-
|
|
1720
|
+
env: typing.Optional[dict[str, typing.Optional[str]]] = None,
|
|
1721
|
+
secrets: typing.Optional[collections.abc.Collection[modal.secret.Secret]] = None,
|
|
1696
1722
|
volumes: dict[
|
|
1697
1723
|
typing.Union[str, pathlib.PurePosixPath],
|
|
1698
1724
|
typing.Union[modal.volume.Volume, modal.cloud_bucket_mount.CloudBucketMount],
|
modal/sandbox.py
CHANGED
|
@@ -3,7 +3,7 @@ import asyncio
|
|
|
3
3
|
import json
|
|
4
4
|
import os
|
|
5
5
|
import time
|
|
6
|
-
from collections.abc import AsyncGenerator, Sequence
|
|
6
|
+
from collections.abc import AsyncGenerator, Collection, Sequence
|
|
7
7
|
from dataclasses import dataclass
|
|
8
8
|
from typing import TYPE_CHECKING, Any, AsyncIterator, Literal, Optional, Union, overload
|
|
9
9
|
|
|
@@ -133,7 +133,7 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
133
133
|
def _new(
|
|
134
134
|
args: Sequence[str],
|
|
135
135
|
image: _Image,
|
|
136
|
-
secrets:
|
|
136
|
+
secrets: Collection[_Secret],
|
|
137
137
|
name: Optional[str] = None,
|
|
138
138
|
timeout: int = 300,
|
|
139
139
|
idle_timeout: Optional[int] = None,
|
|
@@ -288,7 +288,8 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
288
288
|
app: Optional["modal.app._App"] = None,
|
|
289
289
|
name: Optional[str] = None, # Optionally give the sandbox a name. Unique within an app.
|
|
290
290
|
image: Optional[_Image] = None, # The image to run as the container for the sandbox.
|
|
291
|
-
|
|
291
|
+
env: Optional[dict[str, Optional[str]]] = None, # Environment variables to set in the Sandbox.
|
|
292
|
+
secrets: Optional[Collection[_Secret]] = None, # Secrets to inject into the Sandbox as environment variables.
|
|
292
293
|
network_file_systems: dict[Union[str, os.PathLike], _NetworkFileSystem] = {},
|
|
293
294
|
timeout: int = 300, # Maximum lifetime of the sandbox in seconds.
|
|
294
295
|
# The amount of time in seconds that a sandbox can be idle before being terminated.
|
|
@@ -359,6 +360,10 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
359
360
|
"Set the `pty` parameter to `True` instead.",
|
|
360
361
|
)
|
|
361
362
|
|
|
363
|
+
secrets = secrets or []
|
|
364
|
+
if env:
|
|
365
|
+
secrets = [*secrets, _Secret.from_dict(env)]
|
|
366
|
+
|
|
362
367
|
return await _Sandbox._create(
|
|
363
368
|
*args,
|
|
364
369
|
app=app,
|
|
@@ -396,7 +401,8 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
396
401
|
app: Optional["modal.app._App"] = None,
|
|
397
402
|
name: Optional[str] = None,
|
|
398
403
|
image: Optional[_Image] = None,
|
|
399
|
-
|
|
404
|
+
env: Optional[dict[str, Optional[str]]] = None,
|
|
405
|
+
secrets: Optional[Collection[_Secret]] = None,
|
|
400
406
|
mounts: Sequence[_Mount] = (),
|
|
401
407
|
network_file_systems: dict[Union[str, os.PathLike], _NetworkFileSystem] = {},
|
|
402
408
|
timeout: int = 300,
|
|
@@ -409,9 +415,7 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
409
415
|
memory: Optional[Union[int, tuple[int, int]]] = None,
|
|
410
416
|
block_network: bool = False,
|
|
411
417
|
cidr_allowlist: Optional[Sequence[str]] = None,
|
|
412
|
-
volumes: dict[
|
|
413
|
-
Union[str, os.PathLike], Union[_Volume, _CloudBucketMount]
|
|
414
|
-
] = {},
|
|
418
|
+
volumes: dict[Union[str, os.PathLike], Union[_Volume, _CloudBucketMount]] = {},
|
|
415
419
|
pty: bool = False,
|
|
416
420
|
encrypted_ports: Sequence[int] = [],
|
|
417
421
|
h2_ports: Sequence[int] = [],
|
|
@@ -419,9 +423,7 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
419
423
|
proxy: Optional[_Proxy] = None,
|
|
420
424
|
experimental_options: Optional[dict[str, bool]] = None,
|
|
421
425
|
_experimental_enable_snapshot: bool = False,
|
|
422
|
-
_experimental_scheduler_placement: Optional[
|
|
423
|
-
SchedulerPlacement
|
|
424
|
-
] = None,
|
|
426
|
+
_experimental_scheduler_placement: Optional[SchedulerPlacement] = None,
|
|
425
427
|
client: Optional[_Client] = None,
|
|
426
428
|
verbose: bool = False,
|
|
427
429
|
pty_info: Optional[api_pb2.PTYInfo] = None,
|
|
@@ -441,6 +443,10 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
441
443
|
if block_network and (encrypted_ports or h2_ports or unencrypted_ports):
|
|
442
444
|
raise InvalidError("Cannot specify open ports when `block_network` is enabled")
|
|
443
445
|
|
|
446
|
+
secrets = secrets or []
|
|
447
|
+
if env:
|
|
448
|
+
secrets = [*secrets, _Secret.from_dict(env)]
|
|
449
|
+
|
|
444
450
|
# TODO(erikbern): Get rid of the `_new` method and create an already-hydrated object
|
|
445
451
|
obj = _Sandbox._new(
|
|
446
452
|
args,
|
|
@@ -717,7 +723,8 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
717
723
|
stderr: StreamType = StreamType.PIPE,
|
|
718
724
|
timeout: Optional[int] = None,
|
|
719
725
|
workdir: Optional[str] = None,
|
|
720
|
-
|
|
726
|
+
env: Optional[dict[str, Optional[str]]] = None,
|
|
727
|
+
secrets: Optional[Collection[_Secret]] = None,
|
|
721
728
|
text: Literal[True] = True,
|
|
722
729
|
bufsize: Literal[-1, 1] = -1,
|
|
723
730
|
pty: bool = False,
|
|
@@ -733,7 +740,8 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
733
740
|
stderr: StreamType = StreamType.PIPE,
|
|
734
741
|
timeout: Optional[int] = None,
|
|
735
742
|
workdir: Optional[str] = None,
|
|
736
|
-
|
|
743
|
+
env: Optional[dict[str, Optional[str]]] = None,
|
|
744
|
+
secrets: Optional[Collection[_Secret]] = None,
|
|
737
745
|
text: Literal[False] = False,
|
|
738
746
|
bufsize: Literal[-1, 1] = -1,
|
|
739
747
|
pty: bool = False,
|
|
@@ -748,7 +756,10 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
748
756
|
stderr: StreamType = StreamType.PIPE,
|
|
749
757
|
timeout: Optional[int] = None,
|
|
750
758
|
workdir: Optional[str] = None,
|
|
751
|
-
|
|
759
|
+
env: Optional[dict[str, Optional[str]]] = None, # Environment variables to set during command execution.
|
|
760
|
+
secrets: Optional[
|
|
761
|
+
Collection[_Secret]
|
|
762
|
+
] = None, # Secrets to inject as environment variables during command execution.
|
|
752
763
|
# Encode output as text.
|
|
753
764
|
text: bool = True,
|
|
754
765
|
# Control line-buffered output.
|
|
@@ -793,6 +804,7 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
793
804
|
stderr=stderr,
|
|
794
805
|
timeout=timeout,
|
|
795
806
|
workdir=workdir,
|
|
807
|
+
env=env,
|
|
796
808
|
secrets=secrets,
|
|
797
809
|
text=text,
|
|
798
810
|
bufsize=bufsize,
|
|
@@ -806,7 +818,8 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
806
818
|
stderr: StreamType = StreamType.PIPE,
|
|
807
819
|
timeout: Optional[int] = None,
|
|
808
820
|
workdir: Optional[str] = None,
|
|
809
|
-
|
|
821
|
+
env: Optional[dict[str, Optional[str]]] = None,
|
|
822
|
+
secrets: Optional[Collection[_Secret]] = None,
|
|
810
823
|
text: bool = True,
|
|
811
824
|
bufsize: Literal[-1, 1] = -1,
|
|
812
825
|
) -> Union[_ContainerProcess[bytes], _ContainerProcess[str]]:
|
|
@@ -818,6 +831,10 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
818
831
|
raise InvalidError(f"workdir must be an absolute path, got: {workdir}")
|
|
819
832
|
_validate_exec_args(args)
|
|
820
833
|
|
|
834
|
+
secrets = secrets or []
|
|
835
|
+
if env:
|
|
836
|
+
secrets = [*secrets, _Secret.from_dict(env)]
|
|
837
|
+
|
|
821
838
|
# Force secret resolution so we can pass the secret IDs to the backend.
|
|
822
839
|
secret_coros = [secret.hydrate(client=self._client) for secret in secrets]
|
|
823
840
|
await TaskContext.gather(*secret_coros)
|
modal/sandbox.pyi
CHANGED
|
@@ -90,7 +90,7 @@ class _Sandbox(modal._object._Object):
|
|
|
90
90
|
def _new(
|
|
91
91
|
args: collections.abc.Sequence[str],
|
|
92
92
|
image: modal.image._Image,
|
|
93
|
-
secrets: collections.abc.
|
|
93
|
+
secrets: collections.abc.Collection[modal.secret._Secret],
|
|
94
94
|
name: typing.Optional[str] = None,
|
|
95
95
|
timeout: int = 300,
|
|
96
96
|
idle_timeout: typing.Optional[int] = None,
|
|
@@ -128,7 +128,8 @@ class _Sandbox(modal._object._Object):
|
|
|
128
128
|
app: typing.Optional[modal.app._App] = None,
|
|
129
129
|
name: typing.Optional[str] = None,
|
|
130
130
|
image: typing.Optional[modal.image._Image] = None,
|
|
131
|
-
|
|
131
|
+
env: typing.Optional[dict[str, typing.Optional[str]]] = None,
|
|
132
|
+
secrets: typing.Optional[collections.abc.Collection[modal.secret._Secret]] = None,
|
|
132
133
|
network_file_systems: dict[typing.Union[str, os.PathLike], modal.network_file_system._NetworkFileSystem] = {},
|
|
133
134
|
timeout: int = 300,
|
|
134
135
|
idle_timeout: typing.Optional[int] = None,
|
|
@@ -178,7 +179,8 @@ class _Sandbox(modal._object._Object):
|
|
|
178
179
|
app: typing.Optional[modal.app._App] = None,
|
|
179
180
|
name: typing.Optional[str] = None,
|
|
180
181
|
image: typing.Optional[modal.image._Image] = None,
|
|
181
|
-
|
|
182
|
+
env: typing.Optional[dict[str, typing.Optional[str]]] = None,
|
|
183
|
+
secrets: typing.Optional[collections.abc.Collection[modal.secret._Secret]] = None,
|
|
182
184
|
mounts: collections.abc.Sequence[modal.mount._Mount] = (),
|
|
183
185
|
network_file_systems: dict[typing.Union[str, os.PathLike], modal.network_file_system._NetworkFileSystem] = {},
|
|
184
186
|
timeout: int = 300,
|
|
@@ -307,7 +309,8 @@ class _Sandbox(modal._object._Object):
|
|
|
307
309
|
stderr: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
|
308
310
|
timeout: typing.Optional[int] = None,
|
|
309
311
|
workdir: typing.Optional[str] = None,
|
|
310
|
-
|
|
312
|
+
env: typing.Optional[dict[str, typing.Optional[str]]] = None,
|
|
313
|
+
secrets: typing.Optional[collections.abc.Collection[modal.secret._Secret]] = None,
|
|
311
314
|
text: typing.Literal[True] = True,
|
|
312
315
|
bufsize: typing.Literal[-1, 1] = -1,
|
|
313
316
|
pty: bool = False,
|
|
@@ -322,7 +325,8 @@ class _Sandbox(modal._object._Object):
|
|
|
322
325
|
stderr: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
|
323
326
|
timeout: typing.Optional[int] = None,
|
|
324
327
|
workdir: typing.Optional[str] = None,
|
|
325
|
-
|
|
328
|
+
env: typing.Optional[dict[str, typing.Optional[str]]] = None,
|
|
329
|
+
secrets: typing.Optional[collections.abc.Collection[modal.secret._Secret]] = None,
|
|
326
330
|
text: typing.Literal[False] = False,
|
|
327
331
|
bufsize: typing.Literal[-1, 1] = -1,
|
|
328
332
|
pty: bool = False,
|
|
@@ -337,7 +341,8 @@ class _Sandbox(modal._object._Object):
|
|
|
337
341
|
stderr: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
|
338
342
|
timeout: typing.Optional[int] = None,
|
|
339
343
|
workdir: typing.Optional[str] = None,
|
|
340
|
-
|
|
344
|
+
env: typing.Optional[dict[str, typing.Optional[str]]] = None,
|
|
345
|
+
secrets: typing.Optional[collections.abc.Collection[modal.secret._Secret]] = None,
|
|
341
346
|
text: bool = True,
|
|
342
347
|
bufsize: typing.Literal[-1, 1] = -1,
|
|
343
348
|
) -> typing.Union[modal.container_process._ContainerProcess[bytes], modal.container_process._ContainerProcess[str]]:
|
|
@@ -446,7 +451,7 @@ class Sandbox(modal.object.Object):
|
|
|
446
451
|
def _new(
|
|
447
452
|
args: collections.abc.Sequence[str],
|
|
448
453
|
image: modal.image.Image,
|
|
449
|
-
secrets: collections.abc.
|
|
454
|
+
secrets: collections.abc.Collection[modal.secret.Secret],
|
|
450
455
|
name: typing.Optional[str] = None,
|
|
451
456
|
timeout: int = 300,
|
|
452
457
|
idle_timeout: typing.Optional[int] = None,
|
|
@@ -485,7 +490,8 @@ class Sandbox(modal.object.Object):
|
|
|
485
490
|
app: typing.Optional[modal.app.App] = None,
|
|
486
491
|
name: typing.Optional[str] = None,
|
|
487
492
|
image: typing.Optional[modal.image.Image] = None,
|
|
488
|
-
|
|
493
|
+
env: typing.Optional[dict[str, typing.Optional[str]]] = None,
|
|
494
|
+
secrets: typing.Optional[collections.abc.Collection[modal.secret.Secret]] = None,
|
|
489
495
|
network_file_systems: dict[
|
|
490
496
|
typing.Union[str, os.PathLike], modal.network_file_system.NetworkFileSystem
|
|
491
497
|
] = {},
|
|
@@ -538,7 +544,8 @@ class Sandbox(modal.object.Object):
|
|
|
538
544
|
app: typing.Optional[modal.app.App] = None,
|
|
539
545
|
name: typing.Optional[str] = None,
|
|
540
546
|
image: typing.Optional[modal.image.Image] = None,
|
|
541
|
-
|
|
547
|
+
env: typing.Optional[dict[str, typing.Optional[str]]] = None,
|
|
548
|
+
secrets: typing.Optional[collections.abc.Collection[modal.secret.Secret]] = None,
|
|
542
549
|
network_file_systems: dict[
|
|
543
550
|
typing.Union[str, os.PathLike], modal.network_file_system.NetworkFileSystem
|
|
544
551
|
] = {},
|
|
@@ -594,7 +601,8 @@ class Sandbox(modal.object.Object):
|
|
|
594
601
|
app: typing.Optional[modal.app.App] = None,
|
|
595
602
|
name: typing.Optional[str] = None,
|
|
596
603
|
image: typing.Optional[modal.image.Image] = None,
|
|
597
|
-
|
|
604
|
+
env: typing.Optional[dict[str, typing.Optional[str]]] = None,
|
|
605
|
+
secrets: typing.Optional[collections.abc.Collection[modal.secret.Secret]] = None,
|
|
598
606
|
mounts: collections.abc.Sequence[modal.mount.Mount] = (),
|
|
599
607
|
network_file_systems: dict[
|
|
600
608
|
typing.Union[str, os.PathLike], modal.network_file_system.NetworkFileSystem
|
|
@@ -640,7 +648,8 @@ class Sandbox(modal.object.Object):
|
|
|
640
648
|
app: typing.Optional[modal.app.App] = None,
|
|
641
649
|
name: typing.Optional[str] = None,
|
|
642
650
|
image: typing.Optional[modal.image.Image] = None,
|
|
643
|
-
|
|
651
|
+
env: typing.Optional[dict[str, typing.Optional[str]]] = None,
|
|
652
|
+
secrets: typing.Optional[collections.abc.Collection[modal.secret.Secret]] = None,
|
|
644
653
|
mounts: collections.abc.Sequence[modal.mount.Mount] = (),
|
|
645
654
|
network_file_systems: dict[
|
|
646
655
|
typing.Union[str, os.PathLike], modal.network_file_system.NetworkFileSystem
|
|
@@ -893,7 +902,8 @@ class Sandbox(modal.object.Object):
|
|
|
893
902
|
stderr: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
|
894
903
|
timeout: typing.Optional[int] = None,
|
|
895
904
|
workdir: typing.Optional[str] = None,
|
|
896
|
-
|
|
905
|
+
env: typing.Optional[dict[str, typing.Optional[str]]] = None,
|
|
906
|
+
secrets: typing.Optional[collections.abc.Collection[modal.secret.Secret]] = None,
|
|
897
907
|
text: typing.Literal[True] = True,
|
|
898
908
|
bufsize: typing.Literal[-1, 1] = -1,
|
|
899
909
|
pty: bool = False,
|
|
@@ -909,7 +919,8 @@ class Sandbox(modal.object.Object):
|
|
|
909
919
|
stderr: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
|
910
920
|
timeout: typing.Optional[int] = None,
|
|
911
921
|
workdir: typing.Optional[str] = None,
|
|
912
|
-
|
|
922
|
+
env: typing.Optional[dict[str, typing.Optional[str]]] = None,
|
|
923
|
+
secrets: typing.Optional[collections.abc.Collection[modal.secret.Secret]] = None,
|
|
913
924
|
text: typing.Literal[False] = False,
|
|
914
925
|
bufsize: typing.Literal[-1, 1] = -1,
|
|
915
926
|
pty: bool = False,
|
|
@@ -925,7 +936,8 @@ class Sandbox(modal.object.Object):
|
|
|
925
936
|
stderr: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
|
926
937
|
timeout: typing.Optional[int] = None,
|
|
927
938
|
workdir: typing.Optional[str] = None,
|
|
928
|
-
|
|
939
|
+
env: typing.Optional[dict[str, typing.Optional[str]]] = None,
|
|
940
|
+
secrets: typing.Optional[collections.abc.Collection[modal.secret.Secret]] = None,
|
|
929
941
|
text: typing.Literal[True] = True,
|
|
930
942
|
bufsize: typing.Literal[-1, 1] = -1,
|
|
931
943
|
pty: bool = False,
|
|
@@ -941,7 +953,8 @@ class Sandbox(modal.object.Object):
|
|
|
941
953
|
stderr: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
|
942
954
|
timeout: typing.Optional[int] = None,
|
|
943
955
|
workdir: typing.Optional[str] = None,
|
|
944
|
-
|
|
956
|
+
env: typing.Optional[dict[str, typing.Optional[str]]] = None,
|
|
957
|
+
secrets: typing.Optional[collections.abc.Collection[modal.secret.Secret]] = None,
|
|
945
958
|
text: typing.Literal[False] = False,
|
|
946
959
|
bufsize: typing.Literal[-1, 1] = -1,
|
|
947
960
|
pty: bool = False,
|
|
@@ -961,7 +974,8 @@ class Sandbox(modal.object.Object):
|
|
|
961
974
|
stderr: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
|
962
975
|
timeout: typing.Optional[int] = None,
|
|
963
976
|
workdir: typing.Optional[str] = None,
|
|
964
|
-
|
|
977
|
+
env: typing.Optional[dict[str, typing.Optional[str]]] = None,
|
|
978
|
+
secrets: typing.Optional[collections.abc.Collection[modal.secret.Secret]] = None,
|
|
965
979
|
text: bool = True,
|
|
966
980
|
bufsize: typing.Literal[-1, 1] = -1,
|
|
967
981
|
) -> typing.Union[
|
|
@@ -982,7 +996,8 @@ class Sandbox(modal.object.Object):
|
|
|
982
996
|
stderr: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
|
983
997
|
timeout: typing.Optional[int] = None,
|
|
984
998
|
workdir: typing.Optional[str] = None,
|
|
985
|
-
|
|
999
|
+
env: typing.Optional[dict[str, typing.Optional[str]]] = None,
|
|
1000
|
+
secrets: typing.Optional[collections.abc.Collection[modal.secret.Secret]] = None,
|
|
986
1001
|
text: bool = True,
|
|
987
1002
|
bufsize: typing.Literal[-1, 1] = -1,
|
|
988
1003
|
) -> typing.Union[
|
modal/secret.py
CHANGED
|
@@ -239,7 +239,7 @@ class _Secret(_Object, type_prefix="st"):
|
|
|
239
239
|
@staticmethod
|
|
240
240
|
def from_dict(
|
|
241
241
|
env_dict: dict[
|
|
242
|
-
str,
|
|
242
|
+
str, Optional[str]
|
|
243
243
|
] = {}, # dict of entries to be inserted as environment variables in functions using the secret
|
|
244
244
|
) -> "_Secret":
|
|
245
245
|
"""Create a secret from a str-str dictionary. Values can also be `None`, which is ignored.
|