modal 1.1.1.dev2__py3-none-any.whl → 1.1.1.dev4__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/client.pyi CHANGED
@@ -33,7 +33,7 @@ class _Client:
33
33
  server_url: str,
34
34
  client_type: int,
35
35
  credentials: typing.Optional[tuple[str, str]],
36
- version: str = "1.1.1.dev2",
36
+ version: str = "1.1.1.dev4",
37
37
  ):
38
38
  """mdmd:hidden
39
39
  The Modal client object is not intended to be instantiated directly by users.
@@ -163,7 +163,7 @@ class Client:
163
163
  server_url: str,
164
164
  client_type: int,
165
165
  credentials: typing.Optional[tuple[str, str]],
166
- version: str = "1.1.1.dev2",
166
+ version: str = "1.1.1.dev4",
167
167
  ):
168
168
  """mdmd:hidden
169
169
  The Modal client object is not intended to be instantiated directly by users.
modal/functions.pyi CHANGED
@@ -428,7 +428,7 @@ class Function(
428
428
 
429
429
  _call_generator: ___call_generator_spec[typing_extensions.Self]
430
430
 
431
- class __remote_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER, SUPERSELF]):
431
+ class __remote_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
432
432
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER:
433
433
  """Calls the function remotely, executing it with the given arguments and returning the execution's result."""
434
434
  ...
@@ -437,7 +437,7 @@ class Function(
437
437
  """Calls the function remotely, executing it with the given arguments and returning the execution's result."""
438
438
  ...
439
439
 
440
- remote: __remote_spec[modal._functions.ReturnType, modal._functions.P, typing_extensions.Self]
440
+ remote: __remote_spec[modal._functions.P, modal._functions.ReturnType, typing_extensions.Self]
441
441
 
442
442
  class __remote_gen_spec(typing_extensions.Protocol[SUPERSELF]):
443
443
  def __call__(self, /, *args, **kwargs) -> typing.Generator[typing.Any, None, None]:
@@ -464,7 +464,7 @@ class Function(
464
464
  """
465
465
  ...
466
466
 
467
- class ___experimental_spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER, SUPERSELF]):
467
+ class ___experimental_spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
468
468
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]:
469
469
  """[Experimental] Calls the function with the given arguments, without waiting for the results.
470
470
 
@@ -488,7 +488,7 @@ class Function(
488
488
  ...
489
489
 
490
490
  _experimental_spawn: ___experimental_spawn_spec[
491
- modal._functions.ReturnType, modal._functions.P, typing_extensions.Self
491
+ modal._functions.P, modal._functions.ReturnType, typing_extensions.Self
492
492
  ]
493
493
 
494
494
  class ___spawn_map_inner_spec(typing_extensions.Protocol[P_INNER, SUPERSELF]):
@@ -497,7 +497,7 @@ class Function(
497
497
 
498
498
  _spawn_map_inner: ___spawn_map_inner_spec[modal._functions.P, typing_extensions.Self]
499
499
 
500
- class __spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER, SUPERSELF]):
500
+ class __spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
501
501
  def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]:
502
502
  """Calls the function with the given arguments, without waiting for the results.
503
503
 
@@ -518,7 +518,7 @@ class Function(
518
518
  """
519
519
  ...
520
520
 
521
- spawn: __spawn_spec[modal._functions.ReturnType, modal._functions.P, typing_extensions.Self]
521
+ spawn: __spawn_spec[modal._functions.P, modal._functions.ReturnType, typing_extensions.Self]
522
522
 
523
523
  def get_raw_f(self) -> collections.abc.Callable[..., typing.Any]:
524
524
  """Return the inner Python object wrapped by this Modal Function."""
modal/sandbox.py CHANGED
@@ -73,6 +73,20 @@ def _validate_exec_args(entrypoint_args: Sequence[str]) -> None:
73
73
  )
74
74
 
75
75
 
76
+ class DefaultSandboxNameOverride(str):
77
+ """A singleton class that represents the default sandbox name override.
78
+
79
+ It is used to indicate that the sandbox name should not be overridden.
80
+ """
81
+
82
+ def __repr__(self) -> str:
83
+ # NOTE: this must match the instance var name below in order for type stubs to work 😬
84
+ return "_DEFAULT_SANDBOX_NAME_OVERRIDE"
85
+
86
+
87
+ _DEFAULT_SANDBOX_NAME_OVERRIDE = DefaultSandboxNameOverride()
88
+
89
+
76
90
  class _Sandbox(_Object, type_prefix="sb"):
77
91
  """A `Sandbox` object lets you interact with a running sandbox. This API is similar to Python's
78
92
  [asyncio.subprocess.Process](https://docs.python.org/3/library/asyncio-subprocess.html#asyncio.subprocess.Process).
@@ -93,6 +107,7 @@ class _Sandbox(_Object, type_prefix="sb"):
93
107
  entrypoint_args: Sequence[str],
94
108
  image: _Image,
95
109
  secrets: Sequence[_Secret],
110
+ name: Optional[str] = None,
96
111
  timeout: Optional[int] = None,
97
112
  workdir: Optional[str] = None,
98
113
  gpu: GPU_T = None,
@@ -110,6 +125,7 @@ class _Sandbox(_Object, type_prefix="sb"):
110
125
  h2_ports: Sequence[int] = [],
111
126
  unencrypted_ports: Sequence[int] = [],
112
127
  proxy: Optional[_Proxy] = None,
128
+ experimental_options: Optional[dict[str, bool]] = None,
113
129
  _experimental_scheduler_placement: Optional[SchedulerPlacement] = None,
114
130
  enable_snapshot: bool = False,
115
131
  verbose: bool = False,
@@ -215,6 +231,8 @@ class _Sandbox(_Object, type_prefix="sb"):
215
231
  proxy_id=(proxy.object_id if proxy else None),
216
232
  enable_snapshot=enable_snapshot,
217
233
  verbose=verbose,
234
+ name=name,
235
+ experimental_options=experimental_options,
218
236
  )
219
237
 
220
238
  create_req = api_pb2.SandboxCreateRequest(app_id=resolver.app_id, definition=definition)
@@ -228,7 +246,9 @@ class _Sandbox(_Object, type_prefix="sb"):
228
246
  @staticmethod
229
247
  async def create(
230
248
  *entrypoint_args: str,
231
- app: Optional["modal.app._App"] = None, # Optionally associate the sandbox with an app
249
+ # Associate the sandbox with an app. Required unless creating from a container.
250
+ app: Optional["modal.app._App"] = None,
251
+ name: Optional[str] = None, # Optionally give the sandbox a name. Unique within an app.
232
252
  image: Optional[_Image] = None, # The image to run as the container for the sandbox.
233
253
  secrets: Sequence[_Secret] = (), # Environment variables to inject into the sandbox.
234
254
  network_file_systems: dict[Union[str, os.PathLike], _NetworkFileSystem] = {},
@@ -261,6 +281,7 @@ class _Sandbox(_Object, type_prefix="sb"):
261
281
  proxy: Optional[_Proxy] = None,
262
282
  # Enable verbose logging for sandbox operations.
263
283
  verbose: bool = False,
284
+ experimental_options: Optional[dict[str, bool]] = None,
264
285
  # Enable memory snapshots.
265
286
  _experimental_enable_snapshot: bool = False,
266
287
  _experimental_scheduler_placement: Optional[
@@ -292,6 +313,7 @@ class _Sandbox(_Object, type_prefix="sb"):
292
313
  return await _Sandbox._create(
293
314
  *entrypoint_args,
294
315
  app=app,
316
+ name=name,
295
317
  image=image,
296
318
  secrets=secrets,
297
319
  network_file_systems=network_file_systems,
@@ -310,6 +332,7 @@ class _Sandbox(_Object, type_prefix="sb"):
310
332
  h2_ports=h2_ports,
311
333
  unencrypted_ports=unencrypted_ports,
312
334
  proxy=proxy,
335
+ experimental_options=experimental_options,
313
336
  _experimental_enable_snapshot=_experimental_enable_snapshot,
314
337
  _experimental_scheduler_placement=_experimental_scheduler_placement,
315
338
  client=client,
@@ -319,7 +342,9 @@ class _Sandbox(_Object, type_prefix="sb"):
319
342
  @staticmethod
320
343
  async def _create(
321
344
  *entrypoint_args: str,
322
- app: Optional["modal.app._App"] = None, # Optionally associate the sandbox with an app
345
+ # Associate the sandbox with an app. Required unless creating from a container.
346
+ app: Optional["modal.app._App"] = None,
347
+ name: Optional[str] = None, # Optionally give the sandbox a name. Unique within an app.
323
348
  image: Optional[_Image] = None, # The image to run as the container for the sandbox.
324
349
  secrets: Sequence[_Secret] = (), # Environment variables to inject into the sandbox.
325
350
  mounts: Sequence[_Mount] = (),
@@ -351,6 +376,7 @@ class _Sandbox(_Object, type_prefix="sb"):
351
376
  unencrypted_ports: Sequence[int] = [],
352
377
  # Reference to a Modal Proxy to use in front of this Sandbox.
353
378
  proxy: Optional[_Proxy] = None,
379
+ experimental_options: Optional[dict[str, bool]] = None,
354
380
  # Enable memory snapshots.
355
381
  _experimental_enable_snapshot: bool = False,
356
382
  _experimental_scheduler_placement: Optional[
@@ -371,6 +397,7 @@ class _Sandbox(_Object, type_prefix="sb"):
371
397
  entrypoint_args,
372
398
  image=image or _default_image,
373
399
  secrets=secrets,
400
+ name=name,
374
401
  timeout=timeout,
375
402
  workdir=workdir,
376
403
  gpu=gpu,
@@ -388,6 +415,7 @@ class _Sandbox(_Object, type_prefix="sb"):
388
415
  h2_ports=h2_ports,
389
416
  unencrypted_ports=unencrypted_ports,
390
417
  proxy=proxy,
418
+ experimental_options=experimental_options,
391
419
  _experimental_scheduler_placement=_experimental_scheduler_placement,
392
420
  enable_snapshot=_experimental_enable_snapshot,
393
421
  verbose=verbose,
@@ -437,6 +465,27 @@ class _Sandbox(_Object, type_prefix="sb"):
437
465
  self._stdin = StreamWriter(self.object_id, "sandbox", self._client)
438
466
  self._result = None
439
467
 
468
+ @staticmethod
469
+ async def from_name(
470
+ app_name: str,
471
+ name: str,
472
+ *,
473
+ environment_name: Optional[str] = None,
474
+ client: Optional[_Client] = None,
475
+ ) -> "_Sandbox":
476
+ """Get a running Sandbox by name from the given app.
477
+
478
+ Raises an error if no running sandbox is found with the given name. A Sandbox's name
479
+ is the `name` argument passed to `Sandbox.create`.
480
+ """
481
+ if client is None:
482
+ client = await _Client.from_env()
483
+ env_name = _get_environment_name(environment_name)
484
+
485
+ req = api_pb2.SandboxGetFromNameRequest(sandbox_name=name, app_name=app_name, environment_name=env_name)
486
+ resp = await retry_transient_errors(client.stub.SandboxGetFromName, req)
487
+ return _Sandbox._new_hydrated(resp.sandbox_id, client, None)
488
+
440
489
  @staticmethod
441
490
  async def from_id(sandbox_id: str, client: Optional[_Client] = None) -> "_Sandbox":
442
491
  """Construct a Sandbox from an id and look up the Sandbox result.
@@ -713,10 +762,31 @@ class _Sandbox(_Object, type_prefix="sb"):
713
762
  return obj
714
763
 
715
764
  @staticmethod
716
- async def _experimental_from_snapshot(snapshot: _SandboxSnapshot, client: Optional[_Client] = None):
765
+ async def _experimental_from_snapshot(
766
+ snapshot: _SandboxSnapshot,
767
+ client: Optional[_Client] = None,
768
+ *,
769
+ name: Optional[str] = _DEFAULT_SANDBOX_NAME_OVERRIDE,
770
+ ):
717
771
  client = client or await _Client.from_env()
718
772
 
719
- restore_req = api_pb2.SandboxRestoreRequest(snapshot_id=snapshot.object_id)
773
+ if name is _DEFAULT_SANDBOX_NAME_OVERRIDE:
774
+ restore_req = api_pb2.SandboxRestoreRequest(
775
+ snapshot_id=snapshot.object_id,
776
+ sandbox_name_override_type=api_pb2.SandboxRestoreRequest.SANDBOX_NAME_OVERRIDE_TYPE_UNSPECIFIED,
777
+ )
778
+ elif name is None:
779
+ restore_req = api_pb2.SandboxRestoreRequest(
780
+ snapshot_id=snapshot.object_id,
781
+ sandbox_name_override_type=api_pb2.SandboxRestoreRequest.SANDBOX_NAME_OVERRIDE_TYPE_NONE,
782
+ )
783
+ else:
784
+ restore_req = api_pb2.SandboxRestoreRequest(
785
+ snapshot_id=snapshot.object_id,
786
+ sandbox_name_override=name,
787
+ sandbox_name_override_type=api_pb2.SandboxRestoreRequest.SANDBOX_NAME_OVERRIDE_TYPE_STRING,
788
+ )
789
+
720
790
  restore_resp: api_pb2.SandboxRestoreResponse = await retry_transient_errors(
721
791
  client.stub.SandboxRestore, restore_req
722
792
  )
modal/sandbox.pyi CHANGED
@@ -27,6 +27,17 @@ import typing_extensions
27
27
 
28
28
  def _validate_exec_args(entrypoint_args: collections.abc.Sequence[str]) -> None: ...
29
29
 
30
+ class DefaultSandboxNameOverride(str):
31
+ """A singleton class that represents the default sandbox name override.
32
+
33
+ It is used to indicate that the sandbox name should not be overridden.
34
+ """
35
+ def __repr__(self) -> str:
36
+ """Return repr(self)."""
37
+ ...
38
+
39
+ _DEFAULT_SANDBOX_NAME_OVERRIDE: DefaultSandboxNameOverride
40
+
30
41
  class _Sandbox(modal._object._Object):
31
42
  """A `Sandbox` object lets you interact with a running sandbox. This API is similar to Python's
32
43
  [asyncio.subprocess.Process](https://docs.python.org/3/library/asyncio-subprocess.html#asyncio.subprocess.Process).
@@ -47,6 +58,7 @@ class _Sandbox(modal._object._Object):
47
58
  entrypoint_args: collections.abc.Sequence[str],
48
59
  image: modal.image._Image,
49
60
  secrets: collections.abc.Sequence[modal.secret._Secret],
61
+ name: typing.Optional[str] = None,
50
62
  timeout: typing.Optional[int] = None,
51
63
  workdir: typing.Optional[str] = None,
52
64
  gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
@@ -67,6 +79,7 @@ class _Sandbox(modal._object._Object):
67
79
  h2_ports: collections.abc.Sequence[int] = [],
68
80
  unencrypted_ports: collections.abc.Sequence[int] = [],
69
81
  proxy: typing.Optional[modal.proxy._Proxy] = None,
82
+ experimental_options: typing.Optional[dict[str, bool]] = None,
70
83
  _experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
71
84
  enable_snapshot: bool = False,
72
85
  verbose: bool = False,
@@ -78,6 +91,7 @@ class _Sandbox(modal._object._Object):
78
91
  async def create(
79
92
  *entrypoint_args: str,
80
93
  app: typing.Optional[modal.app._App] = None,
94
+ name: typing.Optional[str] = None,
81
95
  image: typing.Optional[modal.image._Image] = None,
82
96
  secrets: collections.abc.Sequence[modal.secret._Secret] = (),
83
97
  network_file_systems: dict[typing.Union[str, os.PathLike], modal.network_file_system._NetworkFileSystem] = {},
@@ -100,6 +114,7 @@ class _Sandbox(modal._object._Object):
100
114
  unencrypted_ports: collections.abc.Sequence[int] = [],
101
115
  proxy: typing.Optional[modal.proxy._Proxy] = None,
102
116
  verbose: bool = False,
117
+ experimental_options: typing.Optional[dict[str, bool]] = None,
103
118
  _experimental_enable_snapshot: bool = False,
104
119
  _experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
105
120
  client: typing.Optional[modal.client._Client] = None,
@@ -123,6 +138,7 @@ class _Sandbox(modal._object._Object):
123
138
  async def _create(
124
139
  *entrypoint_args: str,
125
140
  app: typing.Optional[modal.app._App] = None,
141
+ name: typing.Optional[str] = None,
126
142
  image: typing.Optional[modal.image._Image] = None,
127
143
  secrets: collections.abc.Sequence[modal.secret._Secret] = (),
128
144
  mounts: collections.abc.Sequence[modal.mount._Mount] = (),
@@ -145,12 +161,28 @@ class _Sandbox(modal._object._Object):
145
161
  h2_ports: collections.abc.Sequence[int] = [],
146
162
  unencrypted_ports: collections.abc.Sequence[int] = [],
147
163
  proxy: typing.Optional[modal.proxy._Proxy] = None,
164
+ experimental_options: typing.Optional[dict[str, bool]] = None,
148
165
  _experimental_enable_snapshot: bool = False,
149
166
  _experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
150
167
  client: typing.Optional[modal.client._Client] = None,
151
168
  verbose: bool = False,
152
169
  ): ...
153
170
  def _hydrate_metadata(self, handle_metadata: typing.Optional[google.protobuf.message.Message]): ...
171
+ @staticmethod
172
+ async def from_name(
173
+ app_name: str,
174
+ name: str,
175
+ *,
176
+ environment_name: typing.Optional[str] = None,
177
+ client: typing.Optional[modal.client._Client] = None,
178
+ ) -> _Sandbox:
179
+ """Get a running Sandbox by name from the given app.
180
+
181
+ Raises an error if no running sandbox is found with the given name. A Sandbox's name
182
+ is the `name` argument passed to `Sandbox.create`.
183
+ """
184
+ ...
185
+
154
186
  @staticmethod
155
187
  async def from_id(sandbox_id: str, client: typing.Optional[modal.client._Client] = None) -> _Sandbox:
156
188
  """Construct a Sandbox from an id and look up the Sandbox result.
@@ -240,7 +272,10 @@ class _Sandbox(modal._object._Object):
240
272
  async def _experimental_snapshot(self) -> modal.snapshot._SandboxSnapshot: ...
241
273
  @staticmethod
242
274
  async def _experimental_from_snapshot(
243
- snapshot: modal.snapshot._SandboxSnapshot, client: typing.Optional[modal.client._Client] = None
275
+ snapshot: modal.snapshot._SandboxSnapshot,
276
+ client: typing.Optional[modal.client._Client] = None,
277
+ *,
278
+ name: typing.Optional[str] = _DEFAULT_SANDBOX_NAME_OVERRIDE,
244
279
  ): ...
245
280
  @typing.overload
246
281
  async def open(self, path: str, mode: _typeshed.OpenTextMode) -> modal.file_io._FileIO[str]: ...
@@ -332,6 +367,7 @@ class Sandbox(modal.object.Object):
332
367
  entrypoint_args: collections.abc.Sequence[str],
333
368
  image: modal.image.Image,
334
369
  secrets: collections.abc.Sequence[modal.secret.Secret],
370
+ name: typing.Optional[str] = None,
335
371
  timeout: typing.Optional[int] = None,
336
372
  workdir: typing.Optional[str] = None,
337
373
  gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
@@ -351,6 +387,7 @@ class Sandbox(modal.object.Object):
351
387
  h2_ports: collections.abc.Sequence[int] = [],
352
388
  unencrypted_ports: collections.abc.Sequence[int] = [],
353
389
  proxy: typing.Optional[modal.proxy.Proxy] = None,
390
+ experimental_options: typing.Optional[dict[str, bool]] = None,
354
391
  _experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
355
392
  enable_snapshot: bool = False,
356
393
  verbose: bool = False,
@@ -364,6 +401,7 @@ class Sandbox(modal.object.Object):
364
401
  /,
365
402
  *entrypoint_args: str,
366
403
  app: typing.Optional[modal.app.App] = None,
404
+ name: typing.Optional[str] = None,
367
405
  image: typing.Optional[modal.image.Image] = None,
368
406
  secrets: collections.abc.Sequence[modal.secret.Secret] = (),
369
407
  network_file_systems: dict[
@@ -388,6 +426,7 @@ class Sandbox(modal.object.Object):
388
426
  unencrypted_ports: collections.abc.Sequence[int] = [],
389
427
  proxy: typing.Optional[modal.proxy.Proxy] = None,
390
428
  verbose: bool = False,
429
+ experimental_options: typing.Optional[dict[str, bool]] = None,
391
430
  _experimental_enable_snapshot: bool = False,
392
431
  _experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
393
432
  client: typing.Optional[modal.client.Client] = None,
@@ -412,6 +451,7 @@ class Sandbox(modal.object.Object):
412
451
  /,
413
452
  *entrypoint_args: str,
414
453
  app: typing.Optional[modal.app.App] = None,
454
+ name: typing.Optional[str] = None,
415
455
  image: typing.Optional[modal.image.Image] = None,
416
456
  secrets: collections.abc.Sequence[modal.secret.Secret] = (),
417
457
  network_file_systems: dict[
@@ -436,6 +476,7 @@ class Sandbox(modal.object.Object):
436
476
  unencrypted_ports: collections.abc.Sequence[int] = [],
437
477
  proxy: typing.Optional[modal.proxy.Proxy] = None,
438
478
  verbose: bool = False,
479
+ experimental_options: typing.Optional[dict[str, bool]] = None,
439
480
  _experimental_enable_snapshot: bool = False,
440
481
  _experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
441
482
  client: typing.Optional[modal.client.Client] = None,
@@ -463,6 +504,7 @@ class Sandbox(modal.object.Object):
463
504
  /,
464
505
  *entrypoint_args: str,
465
506
  app: typing.Optional[modal.app.App] = None,
507
+ name: typing.Optional[str] = None,
466
508
  image: typing.Optional[modal.image.Image] = None,
467
509
  secrets: collections.abc.Sequence[modal.secret.Secret] = (),
468
510
  mounts: collections.abc.Sequence[modal.mount.Mount] = (),
@@ -487,6 +529,7 @@ class Sandbox(modal.object.Object):
487
529
  h2_ports: collections.abc.Sequence[int] = [],
488
530
  unencrypted_ports: collections.abc.Sequence[int] = [],
489
531
  proxy: typing.Optional[modal.proxy.Proxy] = None,
532
+ experimental_options: typing.Optional[dict[str, bool]] = None,
490
533
  _experimental_enable_snapshot: bool = False,
491
534
  _experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
492
535
  client: typing.Optional[modal.client.Client] = None,
@@ -497,6 +540,7 @@ class Sandbox(modal.object.Object):
497
540
  /,
498
541
  *entrypoint_args: str,
499
542
  app: typing.Optional[modal.app.App] = None,
543
+ name: typing.Optional[str] = None,
500
544
  image: typing.Optional[modal.image.Image] = None,
501
545
  secrets: collections.abc.Sequence[modal.secret.Secret] = (),
502
546
  mounts: collections.abc.Sequence[modal.mount.Mount] = (),
@@ -521,6 +565,7 @@ class Sandbox(modal.object.Object):
521
565
  h2_ports: collections.abc.Sequence[int] = [],
522
566
  unencrypted_ports: collections.abc.Sequence[int] = [],
523
567
  proxy: typing.Optional[modal.proxy.Proxy] = None,
568
+ experimental_options: typing.Optional[dict[str, bool]] = None,
524
569
  _experimental_enable_snapshot: bool = False,
525
570
  _experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
526
571
  client: typing.Optional[modal.client.Client] = None,
@@ -531,6 +576,41 @@ class Sandbox(modal.object.Object):
531
576
 
532
577
  def _hydrate_metadata(self, handle_metadata: typing.Optional[google.protobuf.message.Message]): ...
533
578
 
579
+ class __from_name_spec(typing_extensions.Protocol):
580
+ def __call__(
581
+ self,
582
+ /,
583
+ app_name: str,
584
+ name: str,
585
+ *,
586
+ environment_name: typing.Optional[str] = None,
587
+ client: typing.Optional[modal.client.Client] = None,
588
+ ) -> Sandbox:
589
+ """Get a running Sandbox by name from the given app.
590
+
591
+ Raises an error if no running sandbox is found with the given name. A Sandbox's name
592
+ is the `name` argument passed to `Sandbox.create`.
593
+ """
594
+ ...
595
+
596
+ async def aio(
597
+ self,
598
+ /,
599
+ app_name: str,
600
+ name: str,
601
+ *,
602
+ environment_name: typing.Optional[str] = None,
603
+ client: typing.Optional[modal.client.Client] = None,
604
+ ) -> Sandbox:
605
+ """Get a running Sandbox by name from the given app.
606
+
607
+ Raises an error if no running sandbox is found with the given name. A Sandbox's name
608
+ is the `name` argument passed to `Sandbox.create`.
609
+ """
610
+ ...
611
+
612
+ from_name: __from_name_spec
613
+
534
614
  class __from_id_spec(typing_extensions.Protocol):
535
615
  def __call__(self, /, sandbox_id: str, client: typing.Optional[modal.client.Client] = None) -> Sandbox:
536
616
  """Construct a Sandbox from an id and look up the Sandbox result.
@@ -745,10 +825,20 @@ class Sandbox(modal.object.Object):
745
825
 
746
826
  class ___experimental_from_snapshot_spec(typing_extensions.Protocol):
747
827
  def __call__(
748
- self, /, snapshot: modal.snapshot.SandboxSnapshot, client: typing.Optional[modal.client.Client] = None
828
+ self,
829
+ /,
830
+ snapshot: modal.snapshot.SandboxSnapshot,
831
+ client: typing.Optional[modal.client.Client] = None,
832
+ *,
833
+ name: typing.Optional[str] = _DEFAULT_SANDBOX_NAME_OVERRIDE,
749
834
  ): ...
750
835
  async def aio(
751
- self, /, snapshot: modal.snapshot.SandboxSnapshot, client: typing.Optional[modal.client.Client] = None
836
+ self,
837
+ /,
838
+ snapshot: modal.snapshot.SandboxSnapshot,
839
+ client: typing.Optional[modal.client.Client] = None,
840
+ *,
841
+ name: typing.Optional[str] = _DEFAULT_SANDBOX_NAME_OVERRIDE,
752
842
  ): ...
753
843
 
754
844
  _experimental_from_snapshot: ___experimental_from_snapshot_spec
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 1.1.1.dev2
3
+ Version: 1.1.1.dev4
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -22,7 +22,7 @@ modal/app.py,sha256=BBR2NmGzZbFGfhKAmtzllD0o4TbVDBbOEs0O2ysSdQo,48277
22
22
  modal/app.pyi,sha256=h6JtBA6a7wobdZAuS3QuXrWCUZqfyKPuGV3XdjCqT3k,43753
23
23
  modal/call_graph.py,sha256=1g2DGcMIJvRy-xKicuf63IVE98gJSnQsr8R_NVMptNc,2581
24
24
  modal/client.py,sha256=pBSZ7lv5dezIL9U9H4tpE0Yz6qA1n0NoNbnJ3KCQMMA,18252
25
- modal/client.pyi,sha256=XzEufAav6aq6sxc5fgrgFQzJC2RBvp0GrnOXCGdAjt0,15388
25
+ modal/client.pyi,sha256=Cn1yHzML2_Ob9_OujCEM52hIVuWHGNsA7bvHnAqylDQ,15388
26
26
  modal/cloud_bucket_mount.py,sha256=YOe9nnvSr4ZbeCn587d7_VhE9IioZYRvF9VYQTQux08,5914
27
27
  modal/cloud_bucket_mount.pyi,sha256=-qSfYAQvIoO_l2wsCCGTG5ZUwQieNKXdAO00yP1-LYU,7394
28
28
  modal/cls.py,sha256=7A0xGnugQzm8dOfnKMjLjtqekRlRtQ0jPFRYgq6xdUM,40018
@@ -39,7 +39,7 @@ modal/file_io.py,sha256=BVqAJ0sgPUfN8QsYztWiGB4j56he60TncM02KsylnCw,21449
39
39
  modal/file_io.pyi,sha256=cPT_hsplE5iLCXhYOLn1Sp9eDdk7DxdFmicQHanJZyg,15918
40
40
  modal/file_pattern_matcher.py,sha256=urAue8es8jxqX94k9EYoZxxhtfgOlsEES8lbFHOorzc,7734
41
41
  modal/functions.py,sha256=kcNHvqeGBxPI7Cgd57NIBBghkfbeFJzXO44WW0jSmao,325
42
- modal/functions.pyi,sha256=0P4f8ew79lf0lWXObYmNFxKoUPbWmoT0CD5IqGNKFhE,34823
42
+ modal/functions.pyi,sha256=sht8252nY3f7y20vURdjz4R-NU0_EvHjHVl97PQ1t_4,34823
43
43
  modal/gpu.py,sha256=Fe5ORvVPDIstSq1xjmM6OoNgLYFWvogP9r5BgmD3hYg,6769
44
44
  modal/image.py,sha256=0E3Tge4W3JLS-8dzFy1AVlkdccMhYs3TQkv5kQwv3G0,102368
45
45
  modal/image.pyi,sha256=s_AQaFoWmjLzffJGmiedFf9K1qQkedVIlsC6vRtlKS8,68161
@@ -65,8 +65,8 @@ modal/retries.py,sha256=IvNLDM0f_GLUDD5VgEDoN09C88yoxSrCquinAuxT1Sc,5205
65
65
  modal/runner.py,sha256=ostdzYpQb-20tlD6dIq7bpWTkZkOhjJBNuMNektqnJA,24068
66
66
  modal/runner.pyi,sha256=lbwLljm1cC8d6PcNvmYQhkE8501V9fg0bYqqKX6G4r4,8489
67
67
  modal/running_app.py,sha256=v61mapYNV1-O-Uaho5EfJlryMLvIT9We0amUOSvSGx8,1188
68
- modal/sandbox.py,sha256=5n4bM-a1i9ba_1r8UAMJRQv_kBu8XUzes_5PtRdEClQ,37620
69
- modal/sandbox.pyi,sha256=xmXcfh24MAAneJFU_AEH-eaHfGRWET0LtjQeFr6Qcgs,38513
68
+ modal/sandbox.py,sha256=o7LnaMDgfflE6gOvlCESoboFY6_BFZzBydoOhq91t3U,40469
69
+ modal/sandbox.pyi,sha256=SRCbHXMBpBT5PBvKuC2lOTv8YenQHk0lvRj8dAqV_X8,41743
70
70
  modal/schedule.py,sha256=ng0g0AqNY5GQI9KhkXZQ5Wam5G42glbkqVQsNpBtbDE,3078
71
71
  modal/scheduler_placement.py,sha256=BAREdOY5HzHpzSBqt6jDVR6YC_jYfHMVqOzkyqQfngU,1235
72
72
  modal/secret.py,sha256=bpgtv0urwaBOmmJpMTZIwVWUraQlpeu4hW8pbJiGcOA,10546
@@ -151,7 +151,7 @@ modal/requirements/2025.06.txt,sha256=KxDaVTOwatHvboDo4lorlgJ7-n-MfAwbPwxJ0zcJqr
151
151
  modal/requirements/PREVIEW.txt,sha256=KxDaVTOwatHvboDo4lorlgJ7-n-MfAwbPwxJ0zcJqrs,312
152
152
  modal/requirements/README.md,sha256=9tK76KP0Uph7O0M5oUgsSwEZDj5y-dcUPsnpR0Sc-Ik,854
153
153
  modal/requirements/base-images.json,sha256=JYSDAgHTl-WrV_TZW5icY-IJEnbe2eQ4CZ_KN6EOZKU,1304
154
- modal-1.1.1.dev2.dist-info/licenses/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
154
+ modal-1.1.1.dev4.dist-info/licenses/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
155
155
  modal_docs/__init__.py,sha256=svYKtV8HDwDCN86zbdWqyq5T8sMdGDj0PVlzc2tIxDM,28
156
156
  modal_docs/gen_cli_docs.py,sha256=c1yfBS_x--gL5bs0N4ihMwqwX8l3IBWSkBAKNNIi6bQ,3801
157
157
  modal_docs/gen_reference_docs.py,sha256=d_CQUGQ0rfw28u75I2mov9AlS773z9rG40-yq5o7g2U,6359
@@ -159,10 +159,10 @@ modal_docs/mdmd/__init__.py,sha256=svYKtV8HDwDCN86zbdWqyq5T8sMdGDj0PVlzc2tIxDM,2
159
159
  modal_docs/mdmd/mdmd.py,sha256=eW5MzrEl7mSclDo4Uv64sQ1-4IyLggldbgUJdBVLDdI,6449
160
160
  modal_docs/mdmd/signatures.py,sha256=XJaZrK7Mdepk5fdX51A8uENiLFNil85Ud0d4MH8H5f0,3218
161
161
  modal_proto/__init__.py,sha256=MIEP8jhXUeGq_eCjYFcqN5b1bxBM4fdk0VESpjWR0fc,28
162
- modal_proto/api.proto,sha256=Ld17DVsscsPcwEszfASZ-2d6UxmyQVDzZuvJUC6NfKI,99929
162
+ modal_proto/api.proto,sha256=N05BG_WD22aybgQW7u0S8cDkBpaNXaQ1sLfS_6wgKjo,100003
163
163
  modal_proto/api_grpc.py,sha256=F7Hu-1Yg7p5a2SbKw9yR4AgpyU0ntvgZTaVbIJMR0DE,122366
164
- modal_proto/api_pb2.py,sha256=S3gY-E20BmDOe3LZS4m0oOWZXxRwC8cWCbu2IWrMrXk,350493
165
- modal_proto/api_pb2.pyi,sha256=RIPvCw17k-l9dmaWcT6BIcyFOA7SSkGljTo_rpoTs6k,479201
164
+ modal_proto/api_pb2.py,sha256=7P2vtfAJahfBdX08tIB1vj2jV6xTewiKfMRkPBLXqkY,351422
165
+ modal_proto/api_pb2.pyi,sha256=8PRc7tUO6uf7u1yrp0n_Tmjrgv3aZJLO7yDQ0WQmtYc,480096
166
166
  modal_proto/api_pb2_grpc.py,sha256=pIFrNmCOgRRcIW8A1Ekja9Po6fHcsj54ExDZFzTpYe4,264347
167
167
  modal_proto/api_pb2_grpc.pyi,sha256=vtxrQ9xnQG6ZRXjp2uk43Mb7wV7F4qGYuVl5JUBc8jI,61968
168
168
  modal_proto/modal_api_grpc.py,sha256=Yl_fGbSIuX2FAEnURkYpKqshs7kbNqtz5HlTJEXkbhE,18487
@@ -174,10 +174,10 @@ modal_proto/options_pb2.pyi,sha256=l7DBrbLO7q3Ir-XDkWsajm0d0TQqqrfuX54i4BMpdQg,1
174
174
  modal_proto/options_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXHDCNMhZD2VXqocC9l_gk,159
175
175
  modal_proto/options_pb2_grpc.pyi,sha256=CImmhxHsYnF09iENPoe8S4J-n93jtgUYD2JPAc0yJSI,247
176
176
  modal_proto/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
177
- modal_version/__init__.py,sha256=9OmJRa3iPgvT8onoRa9MYYs87vUV9EEhfLSkphlicFk,120
177
+ modal_version/__init__.py,sha256=7l0gBNbxYTxFEtanxGB_DQR1WiHDd4JbDIMYjuXVxn0,120
178
178
  modal_version/__main__.py,sha256=2FO0yYQQwDTh6udt1h-cBnGd1c4ZyHnHSI4BksxzVac,105
179
- modal-1.1.1.dev2.dist-info/METADATA,sha256=pc_KssqjJL1mGruUSp1CMA7Q-Xg41IN3xJCi-S5h7HI,2461
180
- modal-1.1.1.dev2.dist-info/WHEEL,sha256=1tXe9gY0PYatrMPMDd6jXqjfpz_B-Wqm32CPfRC58XU,91
181
- modal-1.1.1.dev2.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
182
- modal-1.1.1.dev2.dist-info/top_level.txt,sha256=4BWzoKYREKUZ5iyPzZpjqx4G8uB5TWxXPDwibLcVa7k,43
183
- modal-1.1.1.dev2.dist-info/RECORD,,
179
+ modal-1.1.1.dev4.dist-info/METADATA,sha256=8lO94lXYPCi3v2Sfs35lySEOMSljVUSECSxN7_8p_OA,2461
180
+ modal-1.1.1.dev4.dist-info/WHEEL,sha256=1tXe9gY0PYatrMPMDd6jXqjfpz_B-Wqm32CPfRC58XU,91
181
+ modal-1.1.1.dev4.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
182
+ modal-1.1.1.dev4.dist-info/top_level.txt,sha256=4BWzoKYREKUZ5iyPzZpjqx4G8uB5TWxXPDwibLcVa7k,43
183
+ modal-1.1.1.dev4.dist-info/RECORD,,
modal_proto/api.proto CHANGED
@@ -2520,6 +2520,9 @@ message Sandbox {
2520
2520
 
2521
2521
  // If set, the sandbox will be created with a name.
2522
2522
  optional string name = 30;
2523
+
2524
+ // Experimental options
2525
+ map<string, bool> experimental_options = 31;
2523
2526
  }
2524
2527
 
2525
2528
  message SandboxCreateRequest {