modal 1.1.5.dev83__py3-none-any.whl → 1.3.1.dev8__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.

Files changed (139) hide show
  1. modal/__init__.py +4 -4
  2. modal/__main__.py +4 -29
  3. modal/_billing.py +84 -0
  4. modal/_clustered_functions.py +1 -3
  5. modal/_container_entrypoint.py +33 -208
  6. modal/_functions.py +146 -121
  7. modal/_grpc_client.py +191 -0
  8. modal/_ipython.py +16 -6
  9. modal/_load_context.py +106 -0
  10. modal/_object.py +72 -21
  11. modal/_output.py +12 -14
  12. modal/_partial_function.py +31 -4
  13. modal/_resolver.py +44 -57
  14. modal/_runtime/container_io_manager.py +26 -28
  15. modal/_runtime/container_io_manager.pyi +42 -44
  16. modal/_runtime/gpu_memory_snapshot.py +9 -7
  17. modal/_runtime/user_code_event_loop.py +80 -0
  18. modal/_runtime/user_code_imports.py +236 -10
  19. modal/_serialization.py +2 -1
  20. modal/_traceback.py +4 -13
  21. modal/_tunnel.py +16 -11
  22. modal/_tunnel.pyi +25 -3
  23. modal/_utils/async_utils.py +337 -10
  24. modal/_utils/auth_token_manager.py +1 -4
  25. modal/_utils/blob_utils.py +29 -22
  26. modal/_utils/function_utils.py +20 -21
  27. modal/_utils/grpc_testing.py +6 -3
  28. modal/_utils/grpc_utils.py +223 -64
  29. modal/_utils/mount_utils.py +26 -1
  30. modal/_utils/package_utils.py +0 -1
  31. modal/_utils/rand_pb_testing.py +8 -1
  32. modal/_utils/task_command_router_client.py +524 -0
  33. modal/_vendor/cloudpickle.py +144 -48
  34. modal/app.py +215 -96
  35. modal/app.pyi +78 -37
  36. modal/billing.py +5 -0
  37. modal/builder/2025.06.txt +6 -3
  38. modal/builder/PREVIEW.txt +2 -1
  39. modal/builder/base-images.json +4 -2
  40. modal/cli/_download.py +19 -3
  41. modal/cli/cluster.py +4 -2
  42. modal/cli/config.py +3 -1
  43. modal/cli/container.py +5 -4
  44. modal/cli/dict.py +5 -2
  45. modal/cli/entry_point.py +26 -2
  46. modal/cli/environment.py +2 -16
  47. modal/cli/launch.py +1 -76
  48. modal/cli/network_file_system.py +5 -20
  49. modal/cli/queues.py +5 -4
  50. modal/cli/run.py +24 -204
  51. modal/cli/secret.py +1 -2
  52. modal/cli/shell.py +375 -0
  53. modal/cli/utils.py +1 -13
  54. modal/cli/volume.py +11 -17
  55. modal/client.py +16 -125
  56. modal/client.pyi +94 -144
  57. modal/cloud_bucket_mount.py +3 -1
  58. modal/cloud_bucket_mount.pyi +4 -0
  59. modal/cls.py +101 -64
  60. modal/cls.pyi +9 -8
  61. modal/config.py +21 -1
  62. modal/container_process.py +288 -12
  63. modal/container_process.pyi +99 -38
  64. modal/dict.py +72 -33
  65. modal/dict.pyi +88 -57
  66. modal/environments.py +16 -8
  67. modal/environments.pyi +6 -2
  68. modal/exception.py +154 -16
  69. modal/experimental/__init__.py +23 -5
  70. modal/experimental/flash.py +161 -74
  71. modal/experimental/flash.pyi +97 -49
  72. modal/file_io.py +50 -92
  73. modal/file_io.pyi +117 -89
  74. modal/functions.pyi +70 -87
  75. modal/image.py +73 -47
  76. modal/image.pyi +33 -30
  77. modal/io_streams.py +500 -149
  78. modal/io_streams.pyi +279 -189
  79. modal/mount.py +60 -45
  80. modal/mount.pyi +41 -17
  81. modal/network_file_system.py +19 -11
  82. modal/network_file_system.pyi +72 -39
  83. modal/object.pyi +114 -22
  84. modal/parallel_map.py +42 -44
  85. modal/parallel_map.pyi +9 -17
  86. modal/partial_function.pyi +4 -2
  87. modal/proxy.py +14 -6
  88. modal/proxy.pyi +10 -2
  89. modal/queue.py +45 -38
  90. modal/queue.pyi +88 -52
  91. modal/runner.py +96 -96
  92. modal/runner.pyi +44 -27
  93. modal/sandbox.py +225 -108
  94. modal/sandbox.pyi +226 -63
  95. modal/secret.py +58 -56
  96. modal/secret.pyi +28 -13
  97. modal/serving.py +7 -11
  98. modal/serving.pyi +7 -8
  99. modal/snapshot.py +29 -15
  100. modal/snapshot.pyi +18 -10
  101. modal/token_flow.py +1 -1
  102. modal/token_flow.pyi +4 -6
  103. modal/volume.py +102 -55
  104. modal/volume.pyi +125 -66
  105. {modal-1.1.5.dev83.dist-info → modal-1.3.1.dev8.dist-info}/METADATA +10 -9
  106. modal-1.3.1.dev8.dist-info/RECORD +189 -0
  107. modal_proto/api.proto +86 -30
  108. modal_proto/api_grpc.py +10 -25
  109. modal_proto/api_pb2.py +1080 -1047
  110. modal_proto/api_pb2.pyi +253 -79
  111. modal_proto/api_pb2_grpc.py +14 -48
  112. modal_proto/api_pb2_grpc.pyi +6 -18
  113. modal_proto/modal_api_grpc.py +175 -176
  114. modal_proto/{sandbox_router.proto → task_command_router.proto} +62 -45
  115. modal_proto/task_command_router_grpc.py +138 -0
  116. modal_proto/task_command_router_pb2.py +180 -0
  117. modal_proto/{sandbox_router_pb2.pyi → task_command_router_pb2.pyi} +110 -63
  118. modal_proto/task_command_router_pb2_grpc.py +272 -0
  119. modal_proto/task_command_router_pb2_grpc.pyi +100 -0
  120. modal_version/__init__.py +1 -1
  121. modal_version/__main__.py +1 -1
  122. modal/cli/programs/launch_instance_ssh.py +0 -94
  123. modal/cli/programs/run_marimo.py +0 -95
  124. modal-1.1.5.dev83.dist-info/RECORD +0 -191
  125. modal_proto/modal_options_grpc.py +0 -3
  126. modal_proto/options.proto +0 -19
  127. modal_proto/options_grpc.py +0 -3
  128. modal_proto/options_pb2.py +0 -35
  129. modal_proto/options_pb2.pyi +0 -20
  130. modal_proto/options_pb2_grpc.py +0 -4
  131. modal_proto/options_pb2_grpc.pyi +0 -7
  132. modal_proto/sandbox_router_grpc.py +0 -105
  133. modal_proto/sandbox_router_pb2.py +0 -148
  134. modal_proto/sandbox_router_pb2_grpc.py +0 -203
  135. modal_proto/sandbox_router_pb2_grpc.pyi +0 -75
  136. {modal-1.1.5.dev83.dist-info → modal-1.3.1.dev8.dist-info}/WHEEL +0 -0
  137. {modal-1.1.5.dev83.dist-info → modal-1.3.1.dev8.dist-info}/entry_points.txt +0 -0
  138. {modal-1.1.5.dev83.dist-info → modal-1.3.1.dev8.dist-info}/licenses/LICENSE +0 -0
  139. {modal-1.1.5.dev83.dist-info → modal-1.3.1.dev8.dist-info}/top_level.txt +0 -0
modal/sandbox.pyi CHANGED
@@ -3,6 +3,7 @@ import collections.abc
3
3
  import google.protobuf.message
4
4
  import modal._object
5
5
  import modal._tunnel
6
+ import modal._utils.task_command_router_client
6
7
  import modal.app
7
8
  import modal.client
8
9
  import modal.cloud_bucket_mount
@@ -15,18 +16,17 @@ import modal.mount
15
16
  import modal.network_file_system
16
17
  import modal.object
17
18
  import modal.proxy
18
- import modal.scheduler_placement
19
19
  import modal.secret
20
20
  import modal.snapshot
21
21
  import modal.stream_type
22
22
  import modal.volume
23
23
  import modal_proto.api_pb2
24
24
  import os
25
+ import pathlib
25
26
  import typing
26
27
  import typing_extensions
27
28
 
28
29
  def _validate_exec_args(args: collections.abc.Sequence[str]) -> None: ...
29
- def _warn_if_invalid_name(name: str) -> None: ...
30
30
 
31
31
  class DefaultSandboxNameOverride(str):
32
32
  """A singleton class that represents the default sandbox name override.
@@ -83,6 +83,7 @@ class _Sandbox(modal._object._Object):
83
83
  _task_id: typing.Optional[str]
84
84
  _tunnels: typing.Optional[dict[int, modal._tunnel.Tunnel]]
85
85
  _enable_snapshot: bool
86
+ _command_router_client: typing.Optional[modal._utils.task_command_router_client.TaskCommandRouterClient]
86
87
 
87
88
  @staticmethod
88
89
  def _default_pty_info() -> modal_proto.api_pb2.PTYInfo: ...
@@ -115,7 +116,6 @@ class _Sandbox(modal._object._Object):
115
116
  unencrypted_ports: collections.abc.Sequence[int] = [],
116
117
  proxy: typing.Optional[modal.proxy._Proxy] = None,
117
118
  experimental_options: typing.Optional[dict[str, bool]] = None,
118
- _experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
119
119
  enable_snapshot: bool = False,
120
120
  verbose: bool = False,
121
121
  ) -> _Sandbox:
@@ -153,7 +153,6 @@ class _Sandbox(modal._object._Object):
153
153
  verbose: bool = False,
154
154
  experimental_options: typing.Optional[dict[str, bool]] = None,
155
155
  _experimental_enable_snapshot: bool = False,
156
- _experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
157
156
  client: typing.Optional[modal.client._Client] = None,
158
157
  environment_name: typing.Optional[str] = None,
159
158
  pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
@@ -204,7 +203,6 @@ class _Sandbox(modal._object._Object):
204
203
  proxy: typing.Optional[modal.proxy._Proxy] = None,
205
204
  experimental_options: typing.Optional[dict[str, bool]] = None,
206
205
  _experimental_enable_snapshot: bool = False,
207
- _experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
208
206
  client: typing.Optional[modal.client._Client] = None,
209
207
  verbose: bool = False,
210
208
  pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
@@ -257,6 +255,18 @@ class _Sandbox(modal._object._Object):
257
255
  """
258
256
  ...
259
257
 
258
+ async def _experimental_mount_image(
259
+ self, path: typing.Union[pathlib.PurePosixPath, str], image: typing.Optional[modal.image._Image]
260
+ ):
261
+ """Mount an Image at a path in the Sandbox filesystem."""
262
+ ...
263
+
264
+ async def _experimental_snapshot_directory(
265
+ self, path: typing.Union[pathlib.PurePosixPath, str]
266
+ ) -> modal.image._Image:
267
+ """Snapshot local changes to a previously mounted Image, creating a new Image."""
268
+ ...
269
+
260
270
  async def wait(self, raise_on_termination: bool = True):
261
271
  """Wait for the Sandbox to finish running."""
262
272
  ...
@@ -276,11 +286,10 @@ class _Sandbox(modal._object._Object):
276
286
  async def create_connect_token(
277
287
  self, user_metadata: typing.Union[str, dict[str, typing.Any], None] = None
278
288
  ) -> SandboxConnectCredentials:
279
- """mdmd:hidden
280
- [Alpha] Create a token for making HTTP connections to the sandbox.
289
+ """[Alpha] Create a token for making HTTP connections to the Sandbox.
281
290
 
282
291
  Also accepts an optional user_metadata string or dict to associate with the token. This metadata
283
- will be added to the headers by the proxy when forwarding requests to the sandbox.
292
+ will be added to the headers by the proxy when forwarding requests to the Sandbox.
284
293
  """
285
294
  ...
286
295
 
@@ -306,6 +315,9 @@ class _Sandbox(modal._object._Object):
306
315
  ...
307
316
 
308
317
  async def _get_task_id(self) -> str: ...
318
+ async def _get_command_router_client(
319
+ self, task_id: str
320
+ ) -> typing.Optional[modal._utils.task_command_router_client.TaskCommandRouterClient]: ...
309
321
  @typing.overload
310
322
  async def exec(
311
323
  self,
@@ -357,6 +369,41 @@ class _Sandbox(modal._object._Object):
357
369
  """
358
370
  ...
359
371
 
372
+ async def _exec_through_server(
373
+ self,
374
+ *args: str,
375
+ task_id: str,
376
+ pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
377
+ stdout: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
378
+ stderr: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
379
+ timeout: typing.Optional[int] = None,
380
+ workdir: typing.Optional[str] = None,
381
+ secret_ids: typing.Optional[collections.abc.Collection[str]] = None,
382
+ text: bool = True,
383
+ bufsize: typing.Literal[-1, 1] = -1,
384
+ runtime_debug: bool = False,
385
+ ) -> typing.Union[modal.container_process._ContainerProcess[bytes], modal.container_process._ContainerProcess[str]]:
386
+ """Execute a command through the Modal server."""
387
+ ...
388
+
389
+ async def _exec_through_command_router(
390
+ self,
391
+ *args: str,
392
+ task_id: str,
393
+ command_router_client: modal._utils.task_command_router_client.TaskCommandRouterClient,
394
+ pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
395
+ stdout: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
396
+ stderr: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
397
+ timeout: typing.Optional[int] = None,
398
+ workdir: typing.Optional[str] = None,
399
+ secret_ids: typing.Optional[collections.abc.Collection[str]] = None,
400
+ text: bool = True,
401
+ bufsize: typing.Literal[-1, 1] = -1,
402
+ runtime_debug: bool = False,
403
+ ) -> typing.Union[modal.container_process._ContainerProcess[bytes], modal.container_process._ContainerProcess[str]]:
404
+ """Execute a command through a task command router running on the Modal worker."""
405
+ ...
406
+
360
407
  async def _experimental_snapshot(self) -> modal.snapshot._SandboxSnapshot: ...
361
408
  @staticmethod
362
409
  async def _experimental_from_snapshot(
@@ -429,8 +476,6 @@ class _Sandbox(modal._object._Object):
429
476
  """
430
477
  ...
431
478
 
432
- SUPERSELF = typing.TypeVar("SUPERSELF", covariant=True)
433
-
434
479
  class Sandbox(modal.object.Object):
435
480
  """A `Sandbox` object lets you interact with a running sandbox. This API is similar to Python's
436
481
  [asyncio.subprocess.Process](https://docs.python.org/3/library/asyncio-subprocess.html#asyncio.subprocess.Process).
@@ -445,6 +490,7 @@ class Sandbox(modal.object.Object):
445
490
  _task_id: typing.Optional[str]
446
491
  _tunnels: typing.Optional[dict[int, modal._tunnel.Tunnel]]
447
492
  _enable_snapshot: bool
493
+ _command_router_client: typing.Optional[modal._utils.task_command_router_client.TaskCommandRouterClient]
448
494
 
449
495
  def __init__(self, *args, **kwargs):
450
496
  """mdmd:hidden"""
@@ -480,7 +526,6 @@ class Sandbox(modal.object.Object):
480
526
  unencrypted_ports: collections.abc.Sequence[int] = [],
481
527
  proxy: typing.Optional[modal.proxy.Proxy] = None,
482
528
  experimental_options: typing.Optional[dict[str, bool]] = None,
483
- _experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
484
529
  enable_snapshot: bool = False,
485
530
  verbose: bool = False,
486
531
  ) -> Sandbox:
@@ -522,7 +567,6 @@ class Sandbox(modal.object.Object):
522
567
  verbose: bool = False,
523
568
  experimental_options: typing.Optional[dict[str, bool]] = None,
524
569
  _experimental_enable_snapshot: bool = False,
525
- _experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
526
570
  client: typing.Optional[modal.client.Client] = None,
527
571
  environment_name: typing.Optional[str] = None,
528
572
  pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
@@ -576,7 +620,6 @@ class Sandbox(modal.object.Object):
576
620
  verbose: bool = False,
577
621
  experimental_options: typing.Optional[dict[str, bool]] = None,
578
622
  _experimental_enable_snapshot: bool = False,
579
- _experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
580
623
  client: typing.Optional[modal.client.Client] = None,
581
624
  environment_name: typing.Optional[str] = None,
582
625
  pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
@@ -596,7 +639,7 @@ class Sandbox(modal.object.Object):
596
639
  """
597
640
  ...
598
641
 
599
- create: __create_spec
642
+ create: typing.ClassVar[__create_spec]
600
643
 
601
644
  class ___create_spec(typing_extensions.Protocol):
602
645
  def __call__(
@@ -633,7 +676,6 @@ class Sandbox(modal.object.Object):
633
676
  proxy: typing.Optional[modal.proxy.Proxy] = None,
634
677
  experimental_options: typing.Optional[dict[str, bool]] = None,
635
678
  _experimental_enable_snapshot: bool = False,
636
- _experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
637
679
  client: typing.Optional[modal.client.Client] = None,
638
680
  verbose: bool = False,
639
681
  pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
@@ -680,7 +722,6 @@ class Sandbox(modal.object.Object):
680
722
  proxy: typing.Optional[modal.proxy.Proxy] = None,
681
723
  experimental_options: typing.Optional[dict[str, bool]] = None,
682
724
  _experimental_enable_snapshot: bool = False,
683
- _experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
684
725
  client: typing.Optional[modal.client.Client] = None,
685
726
  verbose: bool = False,
686
727
  pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
@@ -693,7 +734,7 @@ class Sandbox(modal.object.Object):
693
734
  """
694
735
  ...
695
736
 
696
- _create: ___create_spec
737
+ _create: typing.ClassVar[___create_spec]
697
738
 
698
739
  def _hydrate_metadata(self, handle_metadata: typing.Optional[google.protobuf.message.Message]): ...
699
740
 
@@ -730,7 +771,7 @@ class Sandbox(modal.object.Object):
730
771
  """
731
772
  ...
732
773
 
733
- from_name: __from_name_spec
774
+ from_name: typing.ClassVar[__from_name_spec]
734
775
 
735
776
  class __from_id_spec(typing_extensions.Protocol):
736
777
  def __call__(self, /, sandbox_id: str, client: typing.Optional[modal.client.Client] = None) -> Sandbox:
@@ -747,9 +788,9 @@ class Sandbox(modal.object.Object):
747
788
  """
748
789
  ...
749
790
 
750
- from_id: __from_id_spec
791
+ from_id: typing.ClassVar[__from_id_spec]
751
792
 
752
- class __get_tags_spec(typing_extensions.Protocol[SUPERSELF]):
793
+ class __get_tags_spec(typing_extensions.Protocol):
753
794
  def __call__(self, /) -> dict[str, str]:
754
795
  """Fetches any tags (key-value pairs) currently attached to this Sandbox from the server."""
755
796
  ...
@@ -758,9 +799,9 @@ class Sandbox(modal.object.Object):
758
799
  """Fetches any tags (key-value pairs) currently attached to this Sandbox from the server."""
759
800
  ...
760
801
 
761
- get_tags: __get_tags_spec[typing_extensions.Self]
802
+ get_tags: __get_tags_spec
762
803
 
763
- class __set_tags_spec(typing_extensions.Protocol[SUPERSELF]):
804
+ class __set_tags_spec(typing_extensions.Protocol):
764
805
  def __call__(self, /, tags: dict[str, str], *, client: typing.Optional[modal.client.Client] = None) -> None:
765
806
  """Set tags (key-value pairs) on the Sandbox. Tags can be used to filter results in `Sandbox.list`."""
766
807
  ...
@@ -769,9 +810,9 @@ class Sandbox(modal.object.Object):
769
810
  """Set tags (key-value pairs) on the Sandbox. Tags can be used to filter results in `Sandbox.list`."""
770
811
  ...
771
812
 
772
- set_tags: __set_tags_spec[typing_extensions.Self]
813
+ set_tags: __set_tags_spec
773
814
 
774
- class __snapshot_filesystem_spec(typing_extensions.Protocol[SUPERSELF]):
815
+ class __snapshot_filesystem_spec(typing_extensions.Protocol):
775
816
  def __call__(self, /, timeout: int = 55) -> modal.image.Image:
776
817
  """Snapshot the filesystem of the Sandbox.
777
818
 
@@ -788,9 +829,35 @@ class Sandbox(modal.object.Object):
788
829
  """
789
830
  ...
790
831
 
791
- snapshot_filesystem: __snapshot_filesystem_spec[typing_extensions.Self]
832
+ snapshot_filesystem: __snapshot_filesystem_spec
833
+
834
+ class ___experimental_mount_image_spec(typing_extensions.Protocol):
835
+ def __call__(
836
+ self, /, path: typing.Union[pathlib.PurePosixPath, str], image: typing.Optional[modal.image.Image]
837
+ ):
838
+ """Mount an Image at a path in the Sandbox filesystem."""
839
+ ...
840
+
841
+ async def aio(
842
+ self, /, path: typing.Union[pathlib.PurePosixPath, str], image: typing.Optional[modal.image.Image]
843
+ ):
844
+ """Mount an Image at a path in the Sandbox filesystem."""
845
+ ...
846
+
847
+ _experimental_mount_image: ___experimental_mount_image_spec
848
+
849
+ class ___experimental_snapshot_directory_spec(typing_extensions.Protocol):
850
+ def __call__(self, /, path: typing.Union[pathlib.PurePosixPath, str]) -> modal.image.Image:
851
+ """Snapshot local changes to a previously mounted Image, creating a new Image."""
852
+ ...
853
+
854
+ async def aio(self, /, path: typing.Union[pathlib.PurePosixPath, str]) -> modal.image.Image:
855
+ """Snapshot local changes to a previously mounted Image, creating a new Image."""
856
+ ...
857
+
858
+ _experimental_snapshot_directory: ___experimental_snapshot_directory_spec
792
859
 
793
- class __wait_spec(typing_extensions.Protocol[SUPERSELF]):
860
+ class __wait_spec(typing_extensions.Protocol):
794
861
  def __call__(self, /, raise_on_termination: bool = True):
795
862
  """Wait for the Sandbox to finish running."""
796
863
  ...
@@ -799,9 +866,9 @@ class Sandbox(modal.object.Object):
799
866
  """Wait for the Sandbox to finish running."""
800
867
  ...
801
868
 
802
- wait: __wait_spec[typing_extensions.Self]
869
+ wait: __wait_spec
803
870
 
804
- class __tunnels_spec(typing_extensions.Protocol[SUPERSELF]):
871
+ class __tunnels_spec(typing_extensions.Protocol):
805
872
  def __call__(self, /, timeout: int = 50) -> dict[int, modal._tunnel.Tunnel]:
806
873
  """Get Tunnel metadata for the sandbox.
807
874
 
@@ -826,34 +893,32 @@ class Sandbox(modal.object.Object):
826
893
  """
827
894
  ...
828
895
 
829
- tunnels: __tunnels_spec[typing_extensions.Self]
896
+ tunnels: __tunnels_spec
830
897
 
831
- class __create_connect_token_spec(typing_extensions.Protocol[SUPERSELF]):
898
+ class __create_connect_token_spec(typing_extensions.Protocol):
832
899
  def __call__(
833
900
  self, /, user_metadata: typing.Union[str, dict[str, typing.Any], None] = None
834
901
  ) -> SandboxConnectCredentials:
835
- """mdmd:hidden
836
- [Alpha] Create a token for making HTTP connections to the sandbox.
902
+ """[Alpha] Create a token for making HTTP connections to the Sandbox.
837
903
 
838
904
  Also accepts an optional user_metadata string or dict to associate with the token. This metadata
839
- will be added to the headers by the proxy when forwarding requests to the sandbox.
905
+ will be added to the headers by the proxy when forwarding requests to the Sandbox.
840
906
  """
841
907
  ...
842
908
 
843
909
  async def aio(
844
910
  self, /, user_metadata: typing.Union[str, dict[str, typing.Any], None] = None
845
911
  ) -> SandboxConnectCredentials:
846
- """mdmd:hidden
847
- [Alpha] Create a token for making HTTP connections to the sandbox.
912
+ """[Alpha] Create a token for making HTTP connections to the Sandbox.
848
913
 
849
914
  Also accepts an optional user_metadata string or dict to associate with the token. This metadata
850
- will be added to the headers by the proxy when forwarding requests to the sandbox.
915
+ will be added to the headers by the proxy when forwarding requests to the Sandbox.
851
916
  """
852
917
  ...
853
918
 
854
- create_connect_token: __create_connect_token_spec[typing_extensions.Self]
919
+ create_connect_token: __create_connect_token_spec
855
920
 
856
- class __reload_volumes_spec(typing_extensions.Protocol[SUPERSELF]):
921
+ class __reload_volumes_spec(typing_extensions.Protocol):
857
922
  def __call__(self, /) -> None:
858
923
  """Reload all Volumes mounted in the Sandbox.
859
924
 
@@ -868,9 +933,9 @@ class Sandbox(modal.object.Object):
868
933
  """
869
934
  ...
870
935
 
871
- reload_volumes: __reload_volumes_spec[typing_extensions.Self]
936
+ reload_volumes: __reload_volumes_spec
872
937
 
873
- class __terminate_spec(typing_extensions.Protocol[SUPERSELF]):
938
+ class __terminate_spec(typing_extensions.Protocol):
874
939
  def __call__(self, /) -> None:
875
940
  """Terminate Sandbox execution.
876
941
 
@@ -885,9 +950,9 @@ class Sandbox(modal.object.Object):
885
950
  """
886
951
  ...
887
952
 
888
- terminate: __terminate_spec[typing_extensions.Self]
953
+ terminate: __terminate_spec
889
954
 
890
- class __poll_spec(typing_extensions.Protocol[SUPERSELF]):
955
+ class __poll_spec(typing_extensions.Protocol):
891
956
  def __call__(self, /) -> typing.Optional[int]:
892
957
  """Check if the Sandbox has finished running.
893
958
 
@@ -902,15 +967,25 @@ class Sandbox(modal.object.Object):
902
967
  """
903
968
  ...
904
969
 
905
- poll: __poll_spec[typing_extensions.Self]
970
+ poll: __poll_spec
906
971
 
907
- class ___get_task_id_spec(typing_extensions.Protocol[SUPERSELF]):
972
+ class ___get_task_id_spec(typing_extensions.Protocol):
908
973
  def __call__(self, /) -> str: ...
909
974
  async def aio(self, /) -> str: ...
910
975
 
911
- _get_task_id: ___get_task_id_spec[typing_extensions.Self]
976
+ _get_task_id: ___get_task_id_spec
977
+
978
+ class ___get_command_router_client_spec(typing_extensions.Protocol):
979
+ def __call__(
980
+ self, /, task_id: str
981
+ ) -> typing.Optional[modal._utils.task_command_router_client.TaskCommandRouterClient]: ...
982
+ async def aio(
983
+ self, /, task_id: str
984
+ ) -> typing.Optional[modal._utils.task_command_router_client.TaskCommandRouterClient]: ...
912
985
 
913
- class __exec_spec(typing_extensions.Protocol[SUPERSELF]):
986
+ _get_command_router_client: ___get_command_router_client_spec
987
+
988
+ class __exec_spec(typing_extensions.Protocol):
914
989
  @typing.overload
915
990
  def __call__(
916
991
  self,
@@ -980,9 +1055,9 @@ class Sandbox(modal.object.Object):
980
1055
  _pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
981
1056
  ) -> modal.container_process.ContainerProcess[bytes]: ...
982
1057
 
983
- exec: __exec_spec[typing_extensions.Self]
1058
+ exec: __exec_spec
984
1059
 
985
- class ___exec_spec(typing_extensions.Protocol[SUPERSELF]):
1060
+ class ___exec_spec(typing_extensions.Protocol):
986
1061
  def __call__(
987
1062
  self,
988
1063
  /,
@@ -1027,13 +1102,101 @@ class Sandbox(modal.object.Object):
1027
1102
  """
1028
1103
  ...
1029
1104
 
1030
- _exec: ___exec_spec[typing_extensions.Self]
1105
+ _exec: ___exec_spec
1106
+
1107
+ class ___exec_through_server_spec(typing_extensions.Protocol):
1108
+ def __call__(
1109
+ self,
1110
+ /,
1111
+ *args: str,
1112
+ task_id: str,
1113
+ pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
1114
+ stdout: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
1115
+ stderr: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
1116
+ timeout: typing.Optional[int] = None,
1117
+ workdir: typing.Optional[str] = None,
1118
+ secret_ids: typing.Optional[collections.abc.Collection[str]] = None,
1119
+ text: bool = True,
1120
+ bufsize: typing.Literal[-1, 1] = -1,
1121
+ runtime_debug: bool = False,
1122
+ ) -> typing.Union[
1123
+ modal.container_process.ContainerProcess[bytes], modal.container_process.ContainerProcess[str]
1124
+ ]:
1125
+ """Execute a command through the Modal server."""
1126
+ ...
1127
+
1128
+ async def aio(
1129
+ self,
1130
+ /,
1131
+ *args: str,
1132
+ task_id: str,
1133
+ pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
1134
+ stdout: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
1135
+ stderr: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
1136
+ timeout: typing.Optional[int] = None,
1137
+ workdir: typing.Optional[str] = None,
1138
+ secret_ids: typing.Optional[collections.abc.Collection[str]] = None,
1139
+ text: bool = True,
1140
+ bufsize: typing.Literal[-1, 1] = -1,
1141
+ runtime_debug: bool = False,
1142
+ ) -> typing.Union[
1143
+ modal.container_process.ContainerProcess[bytes], modal.container_process.ContainerProcess[str]
1144
+ ]:
1145
+ """Execute a command through the Modal server."""
1146
+ ...
1147
+
1148
+ _exec_through_server: ___exec_through_server_spec
1149
+
1150
+ class ___exec_through_command_router_spec(typing_extensions.Protocol):
1151
+ def __call__(
1152
+ self,
1153
+ /,
1154
+ *args: str,
1155
+ task_id: str,
1156
+ command_router_client: modal._utils.task_command_router_client.TaskCommandRouterClient,
1157
+ pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
1158
+ stdout: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
1159
+ stderr: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
1160
+ timeout: typing.Optional[int] = None,
1161
+ workdir: typing.Optional[str] = None,
1162
+ secret_ids: typing.Optional[collections.abc.Collection[str]] = None,
1163
+ text: bool = True,
1164
+ bufsize: typing.Literal[-1, 1] = -1,
1165
+ runtime_debug: bool = False,
1166
+ ) -> typing.Union[
1167
+ modal.container_process.ContainerProcess[bytes], modal.container_process.ContainerProcess[str]
1168
+ ]:
1169
+ """Execute a command through a task command router running on the Modal worker."""
1170
+ ...
1171
+
1172
+ async def aio(
1173
+ self,
1174
+ /,
1175
+ *args: str,
1176
+ task_id: str,
1177
+ command_router_client: modal._utils.task_command_router_client.TaskCommandRouterClient,
1178
+ pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
1179
+ stdout: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
1180
+ stderr: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
1181
+ timeout: typing.Optional[int] = None,
1182
+ workdir: typing.Optional[str] = None,
1183
+ secret_ids: typing.Optional[collections.abc.Collection[str]] = None,
1184
+ text: bool = True,
1185
+ bufsize: typing.Literal[-1, 1] = -1,
1186
+ runtime_debug: bool = False,
1187
+ ) -> typing.Union[
1188
+ modal.container_process.ContainerProcess[bytes], modal.container_process.ContainerProcess[str]
1189
+ ]:
1190
+ """Execute a command through a task command router running on the Modal worker."""
1191
+ ...
1192
+
1193
+ _exec_through_command_router: ___exec_through_command_router_spec
1031
1194
 
1032
- class ___experimental_snapshot_spec(typing_extensions.Protocol[SUPERSELF]):
1195
+ class ___experimental_snapshot_spec(typing_extensions.Protocol):
1033
1196
  def __call__(self, /) -> modal.snapshot.SandboxSnapshot: ...
1034
1197
  async def aio(self, /) -> modal.snapshot.SandboxSnapshot: ...
1035
1198
 
1036
- _experimental_snapshot: ___experimental_snapshot_spec[typing_extensions.Self]
1199
+ _experimental_snapshot: ___experimental_snapshot_spec
1037
1200
 
1038
1201
  class ___experimental_from_snapshot_spec(typing_extensions.Protocol):
1039
1202
  def __call__(
@@ -1053,9 +1216,9 @@ class Sandbox(modal.object.Object):
1053
1216
  name: typing.Optional[str] = _DEFAULT_SANDBOX_NAME_OVERRIDE,
1054
1217
  ): ...
1055
1218
 
1056
- _experimental_from_snapshot: ___experimental_from_snapshot_spec
1219
+ _experimental_from_snapshot: typing.ClassVar[___experimental_from_snapshot_spec]
1057
1220
 
1058
- class __open_spec(typing_extensions.Protocol[SUPERSELF]):
1221
+ class __open_spec(typing_extensions.Protocol):
1059
1222
  @typing.overload
1060
1223
  def __call__(self, /, path: str, mode: _typeshed.OpenTextMode) -> modal.file_io.FileIO[str]: ...
1061
1224
  @typing.overload
@@ -1065,9 +1228,9 @@ class Sandbox(modal.object.Object):
1065
1228
  @typing.overload
1066
1229
  async def aio(self, /, path: str, mode: _typeshed.OpenBinaryMode) -> modal.file_io.FileIO[bytes]: ...
1067
1230
 
1068
- open: __open_spec[typing_extensions.Self]
1231
+ open: __open_spec
1069
1232
 
1070
- class __ls_spec(typing_extensions.Protocol[SUPERSELF]):
1233
+ class __ls_spec(typing_extensions.Protocol):
1071
1234
  def __call__(self, /, path: str) -> list[str]:
1072
1235
  """[Alpha] List the contents of a directory in the Sandbox."""
1073
1236
  ...
@@ -1076,9 +1239,9 @@ class Sandbox(modal.object.Object):
1076
1239
  """[Alpha] List the contents of a directory in the Sandbox."""
1077
1240
  ...
1078
1241
 
1079
- ls: __ls_spec[typing_extensions.Self]
1242
+ ls: __ls_spec
1080
1243
 
1081
- class __mkdir_spec(typing_extensions.Protocol[SUPERSELF]):
1244
+ class __mkdir_spec(typing_extensions.Protocol):
1082
1245
  def __call__(self, /, path: str, parents: bool = False) -> None:
1083
1246
  """[Alpha] Create a new directory in the Sandbox."""
1084
1247
  ...
@@ -1087,9 +1250,9 @@ class Sandbox(modal.object.Object):
1087
1250
  """[Alpha] Create a new directory in the Sandbox."""
1088
1251
  ...
1089
1252
 
1090
- mkdir: __mkdir_spec[typing_extensions.Self]
1253
+ mkdir: __mkdir_spec
1091
1254
 
1092
- class __rm_spec(typing_extensions.Protocol[SUPERSELF]):
1255
+ class __rm_spec(typing_extensions.Protocol):
1093
1256
  def __call__(self, /, path: str, recursive: bool = False) -> None:
1094
1257
  """[Alpha] Remove a file or directory in the Sandbox."""
1095
1258
  ...
@@ -1098,9 +1261,9 @@ class Sandbox(modal.object.Object):
1098
1261
  """[Alpha] Remove a file or directory in the Sandbox."""
1099
1262
  ...
1100
1263
 
1101
- rm: __rm_spec[typing_extensions.Self]
1264
+ rm: __rm_spec
1102
1265
 
1103
- class __watch_spec(typing_extensions.Protocol[SUPERSELF]):
1266
+ class __watch_spec(typing_extensions.Protocol):
1104
1267
  def __call__(
1105
1268
  self,
1106
1269
  /,
@@ -1123,7 +1286,7 @@ class Sandbox(modal.object.Object):
1123
1286
  """[Alpha] Watch a file or directory in the Sandbox for changes."""
1124
1287
  ...
1125
1288
 
1126
- watch: __watch_spec[typing_extensions.Self]
1289
+ watch: __watch_spec
1127
1290
 
1128
1291
  @property
1129
1292
  def stdout(self) -> modal.io_streams.StreamReader[str]:
@@ -1178,6 +1341,6 @@ class Sandbox(modal.object.Object):
1178
1341
  """
1179
1342
  ...
1180
1343
 
1181
- list: __list_spec
1344
+ list: typing.ClassVar[__list_spec]
1182
1345
 
1183
1346
  _default_image: modal.image._Image