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/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.Sequence[modal.secret._Secret]] = None,
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
- secrets: collections.abc.Sequence[modal.secret._Secret] = [],
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
- secrets: collections.abc.Sequence[modal.secret._Secret] = [],
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
- secrets: collections.abc.Sequence[modal.secret._Secret] = [],
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
- secrets: collections.abc.Sequence[modal.secret._Secret] = [],
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
- secrets: collections.abc.Sequence[modal.secret._Secret] = [],
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
- secrets: collections.abc.Sequence[modal.secret._Secret] = [],
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
- secrets: collections.abc.Sequence[modal.secret._Secret] = [],
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
- secrets: collections.abc.Sequence[modal.secret._Secret] = [],
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
- secrets: collections.abc.Sequence[modal.secret._Secret] = [],
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
- secrets: collections.abc.Sequence[modal.secret._Secret] = [],
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
- secrets: collections.abc.Sequence[modal.secret._Secret] = [],
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
- secrets: collections.abc.Sequence[modal.secret._Secret] = [],
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
- secrets: collections.abc.Sequence[modal.secret._Secret] = (),
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.Sequence[modal.secret.Secret]] = None,
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
- secrets: collections.abc.Sequence[modal.secret.Secret] = [],
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
- secrets: collections.abc.Sequence[modal.secret.Secret] = [],
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
- secrets: collections.abc.Sequence[modal.secret.Secret] = [],
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
- secrets: collections.abc.Sequence[modal.secret.Secret] = [],
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
- secrets: collections.abc.Sequence[modal.secret.Secret] = [],
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
- secrets: collections.abc.Sequence[modal.secret.Secret] = [],
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
- secrets: collections.abc.Sequence[modal.secret.Secret] = [],
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
- secrets: collections.abc.Sequence[modal.secret.Secret] = [],
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
- secrets: collections.abc.Sequence[modal.secret.Secret] = [],
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
- secrets: collections.abc.Sequence[modal.secret.Secret] = [],
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
- secrets: collections.abc.Sequence[modal.secret.Secret] = [],
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
- secrets: collections.abc.Sequence[modal.secret.Secret] = [],
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
- secrets: collections.abc.Sequence[modal.secret.Secret] = (),
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: Sequence[_Secret],
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
- secrets: Sequence[_Secret] = (), # Environment variables to inject into the sandbox.
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
- secrets: Sequence[_Secret] = (),
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
- secrets: Sequence[_Secret] = (),
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
- secrets: Sequence[_Secret] = (),
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
- secrets: Sequence[_Secret] = (),
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
- secrets: Sequence[_Secret] = (),
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.Sequence[modal.secret._Secret],
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
- secrets: collections.abc.Sequence[modal.secret._Secret] = (),
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
- secrets: collections.abc.Sequence[modal.secret._Secret] = (),
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
- secrets: collections.abc.Sequence[modal.secret._Secret] = (),
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
- secrets: collections.abc.Sequence[modal.secret._Secret] = (),
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
- secrets: collections.abc.Sequence[modal.secret._Secret] = (),
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.Sequence[modal.secret.Secret],
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
- secrets: collections.abc.Sequence[modal.secret.Secret] = (),
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
- secrets: collections.abc.Sequence[modal.secret.Secret] = (),
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
- secrets: collections.abc.Sequence[modal.secret.Secret] = (),
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
- secrets: collections.abc.Sequence[modal.secret.Secret] = (),
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
- secrets: collections.abc.Sequence[modal.secret.Secret] = (),
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
- secrets: collections.abc.Sequence[modal.secret.Secret] = (),
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
- secrets: collections.abc.Sequence[modal.secret.Secret] = (),
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
- secrets: collections.abc.Sequence[modal.secret.Secret] = (),
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
- secrets: collections.abc.Sequence[modal.secret.Secret] = (),
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
- secrets: collections.abc.Sequence[modal.secret.Secret] = (),
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, Union[str, None]
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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.1.5.dev20
3
+ Version: 1.1.5.dev21
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0