modal 1.2.1.dev15__py3-none-any.whl → 1.2.1.dev16__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/_utils/task_command_router_client.py +3 -5
- modal/client.pyi +2 -2
- modal/container_process.py +7 -1
- modal/container_process.pyi +4 -0
- modal/functions.pyi +6 -6
- modal/io_streams.py +1 -1
- modal/sandbox.py +124 -6
- modal/sandbox.pyi +139 -0
- {modal-1.2.1.dev15.dist-info → modal-1.2.1.dev16.dist-info}/METADATA +1 -1
- {modal-1.2.1.dev15.dist-info → modal-1.2.1.dev16.dist-info}/RECORD +15 -15
- modal_version/__init__.py +1 -1
- {modal-1.2.1.dev15.dist-info → modal-1.2.1.dev16.dist-info}/WHEEL +0 -0
- {modal-1.2.1.dev15.dist-info → modal-1.2.1.dev16.dist-info}/entry_points.txt +0 -0
- {modal-1.2.1.dev15.dist-info → modal-1.2.1.dev16.dist-info}/licenses/LICENSE +0 -0
- {modal-1.2.1.dev15.dist-info → modal-1.2.1.dev16.dist-info}/top_level.txt +0 -0
|
@@ -442,12 +442,10 @@ class TaskCommandRouterClient:
|
|
|
442
442
|
logger.debug(f"Cancelled JWT refresh loop for exec with task ID {self._task_id}")
|
|
443
443
|
break
|
|
444
444
|
except Exception as e:
|
|
445
|
+
# Exceptions here can stem from non-transient errors against the server sending
|
|
446
|
+
# the TaskGetCommandRouterAccess RPC, for instance, if the task has finished.
|
|
445
447
|
logger.warning(f"Background JWT refresh failed for exec with task ID {self._task_id}: {e}")
|
|
446
|
-
|
|
447
|
-
await asyncio.sleep(1.0)
|
|
448
|
-
except Exception:
|
|
449
|
-
# Ignore sleep issues; loop will re-check closed flag.
|
|
450
|
-
pass
|
|
448
|
+
break
|
|
451
449
|
|
|
452
450
|
async def _stream_stdio(
|
|
453
451
|
self,
|
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.2.1.
|
|
36
|
+
version: str = "1.2.1.dev16",
|
|
37
37
|
):
|
|
38
38
|
"""mdmd:hidden
|
|
39
39
|
The Modal client object is not intended to be instantiated directly by users.
|
|
@@ -164,7 +164,7 @@ class Client:
|
|
|
164
164
|
server_url: str,
|
|
165
165
|
client_type: int,
|
|
166
166
|
credentials: typing.Optional[tuple[str, str]],
|
|
167
|
-
version: str = "1.2.1.
|
|
167
|
+
version: str = "1.2.1.dev16",
|
|
168
168
|
):
|
|
169
169
|
"""mdmd:hidden
|
|
170
170
|
The Modal client object is not intended to be instantiated directly by users.
|
modal/container_process.py
CHANGED
|
@@ -273,6 +273,9 @@ class _ContainerProcessThroughCommandRouter(Generic[T]):
|
|
|
273
273
|
)
|
|
274
274
|
self._returncode = None
|
|
275
275
|
|
|
276
|
+
def __repr__(self) -> str:
|
|
277
|
+
return f"ContainerProcess(process_id={self._process_id!r})"
|
|
278
|
+
|
|
276
279
|
@property
|
|
277
280
|
def stdout(self) -> _StreamReader[T]:
|
|
278
281
|
return self._stdout
|
|
@@ -314,7 +317,10 @@ class _ContainerProcessThroughCommandRouter(Generic[T]):
|
|
|
314
317
|
raise InvalidError("Unexpected exit status")
|
|
315
318
|
except ExecTimeoutError:
|
|
316
319
|
logger.debug(f"ContainerProcess poll for {self._process_id} did not complete within deadline")
|
|
317
|
-
|
|
320
|
+
# TODO(saltzm): This is a weird API, but customers currently may rely on it. This
|
|
321
|
+
# should probably raise an ExecTimeoutError instead.
|
|
322
|
+
self._returncode = -1
|
|
323
|
+
return self._returncode
|
|
318
324
|
except Exception as e:
|
|
319
325
|
# Re-raise non-transient errors or errors resulting from exceeding retries on transient errors.
|
|
320
326
|
logger.warning(f"ContainerProcess poll for {self._process_id} failed: {e}")
|
modal/container_process.pyi
CHANGED
|
@@ -112,6 +112,10 @@ class _ContainerProcessThroughCommandRouter(typing.Generic[T]):
|
|
|
112
112
|
"""Initialize self. See help(type(self)) for accurate signature."""
|
|
113
113
|
...
|
|
114
114
|
|
|
115
|
+
def __repr__(self) -> str:
|
|
116
|
+
"""Return repr(self)."""
|
|
117
|
+
...
|
|
118
|
+
|
|
115
119
|
@property
|
|
116
120
|
def stdout(self) -> modal.io_streams._StreamReader[T]: ...
|
|
117
121
|
@property
|
modal/functions.pyi
CHANGED
|
@@ -401,7 +401,7 @@ class Function(
|
|
|
401
401
|
|
|
402
402
|
_call_generator: ___call_generator_spec[typing_extensions.Self]
|
|
403
403
|
|
|
404
|
-
class __remote_spec(typing_extensions.Protocol[
|
|
404
|
+
class __remote_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
|
|
405
405
|
def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER:
|
|
406
406
|
"""Calls the function remotely, executing it with the given arguments and returning the execution's result."""
|
|
407
407
|
...
|
|
@@ -410,7 +410,7 @@ class Function(
|
|
|
410
410
|
"""Calls the function remotely, executing it with the given arguments and returning the execution's result."""
|
|
411
411
|
...
|
|
412
412
|
|
|
413
|
-
remote: __remote_spec[modal._functions.
|
|
413
|
+
remote: __remote_spec[modal._functions.P, modal._functions.ReturnType, typing_extensions.Self]
|
|
414
414
|
|
|
415
415
|
class __remote_gen_spec(typing_extensions.Protocol[SUPERSELF]):
|
|
416
416
|
def __call__(self, /, *args, **kwargs) -> typing.Generator[typing.Any, None, None]:
|
|
@@ -437,7 +437,7 @@ class Function(
|
|
|
437
437
|
"""
|
|
438
438
|
...
|
|
439
439
|
|
|
440
|
-
class ___experimental_spawn_spec(typing_extensions.Protocol[
|
|
440
|
+
class ___experimental_spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
|
|
441
441
|
def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]:
|
|
442
442
|
"""[Experimental] Calls the function with the given arguments, without waiting for the results.
|
|
443
443
|
|
|
@@ -461,7 +461,7 @@ class Function(
|
|
|
461
461
|
...
|
|
462
462
|
|
|
463
463
|
_experimental_spawn: ___experimental_spawn_spec[
|
|
464
|
-
modal._functions.
|
|
464
|
+
modal._functions.P, modal._functions.ReturnType, typing_extensions.Self
|
|
465
465
|
]
|
|
466
466
|
|
|
467
467
|
class ___spawn_map_inner_spec(typing_extensions.Protocol[P_INNER, SUPERSELF]):
|
|
@@ -470,7 +470,7 @@ class Function(
|
|
|
470
470
|
|
|
471
471
|
_spawn_map_inner: ___spawn_map_inner_spec[modal._functions.P, typing_extensions.Self]
|
|
472
472
|
|
|
473
|
-
class __spawn_spec(typing_extensions.Protocol[
|
|
473
|
+
class __spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
|
|
474
474
|
def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]:
|
|
475
475
|
"""Calls the function with the given arguments, without waiting for the results.
|
|
476
476
|
|
|
@@ -491,7 +491,7 @@ class Function(
|
|
|
491
491
|
"""
|
|
492
492
|
...
|
|
493
493
|
|
|
494
|
-
spawn: __spawn_spec[modal._functions.
|
|
494
|
+
spawn: __spawn_spec[modal._functions.P, modal._functions.ReturnType, typing_extensions.Self]
|
|
495
495
|
|
|
496
496
|
def get_raw_f(self) -> collections.abc.Callable[..., typing.Any]:
|
|
497
497
|
"""Return the inner Python object wrapped by this Modal Function."""
|
modal/io_streams.py
CHANGED
|
@@ -553,7 +553,7 @@ class _StreamReader(Generic[T]):
|
|
|
553
553
|
# unimplemented for now.
|
|
554
554
|
if stream_type == StreamType.STDOUT:
|
|
555
555
|
raise NotImplementedError(
|
|
556
|
-
"Currently
|
|
556
|
+
"Currently the STDOUT stream type is not supported when using exec "
|
|
557
557
|
"through a task command router, which is currently in beta."
|
|
558
558
|
)
|
|
559
559
|
params = _StreamReaderThroughCommandRouterParams(
|
modal/sandbox.py
CHANGED
|
@@ -3,6 +3,7 @@ import asyncio
|
|
|
3
3
|
import json
|
|
4
4
|
import os
|
|
5
5
|
import time
|
|
6
|
+
import uuid
|
|
6
7
|
from collections.abc import AsyncGenerator, Collection, Sequence
|
|
7
8
|
from dataclasses import dataclass
|
|
8
9
|
from typing import TYPE_CHECKING, Any, AsyncIterator, Literal, Optional, Union, overload
|
|
@@ -20,7 +21,7 @@ from modal._tunnel import Tunnel
|
|
|
20
21
|
from modal.cloud_bucket_mount import _CloudBucketMount, cloud_bucket_mounts_to_proto
|
|
21
22
|
from modal.mount import _Mount
|
|
22
23
|
from modal.volume import _Volume
|
|
23
|
-
from modal_proto import api_pb2
|
|
24
|
+
from modal_proto import api_pb2, task_command_router_pb2 as sr_pb2
|
|
24
25
|
|
|
25
26
|
from ._object import _get_environment_name, _Object
|
|
26
27
|
from ._resolver import Resolver
|
|
@@ -30,6 +31,7 @@ from ._utils.deprecation import deprecation_warning
|
|
|
30
31
|
from ._utils.grpc_utils import retry_transient_errors
|
|
31
32
|
from ._utils.mount_utils import validate_network_file_systems, validate_volumes
|
|
32
33
|
from ._utils.name_utils import is_valid_object_name
|
|
34
|
+
from ._utils.task_command_router_client import TaskCommandRouterClient
|
|
33
35
|
from .client import _Client
|
|
34
36
|
from .container_process import _ContainerProcess
|
|
35
37
|
from .exception import AlreadyExistsError, ExecutionError, InvalidError, SandboxTerminatedError, SandboxTimeoutError
|
|
@@ -121,9 +123,10 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
121
123
|
_stdout: _StreamReader[str]
|
|
122
124
|
_stderr: _StreamReader[str]
|
|
123
125
|
_stdin: _StreamWriter
|
|
124
|
-
_task_id: Optional[str]
|
|
125
|
-
_tunnels: Optional[dict[int, Tunnel]]
|
|
126
|
-
_enable_snapshot: bool
|
|
126
|
+
_task_id: Optional[str]
|
|
127
|
+
_tunnels: Optional[dict[int, Tunnel]]
|
|
128
|
+
_enable_snapshot: bool
|
|
129
|
+
_command_router_client: Optional[TaskCommandRouterClient]
|
|
127
130
|
|
|
128
131
|
@staticmethod
|
|
129
132
|
def _default_pty_info() -> api_pb2.PTYInfo:
|
|
@@ -521,6 +524,10 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
521
524
|
)
|
|
522
525
|
self._stdin = StreamWriter(self.object_id, "sandbox", self._client)
|
|
523
526
|
self._result = None
|
|
527
|
+
self._task_id = None
|
|
528
|
+
self._tunnels = None
|
|
529
|
+
self._enable_snapshot = False
|
|
530
|
+
self._command_router_client = None
|
|
524
531
|
|
|
525
532
|
@staticmethod
|
|
526
533
|
async def from_name(
|
|
@@ -730,6 +737,13 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
730
737
|
await asyncio.sleep(0.5)
|
|
731
738
|
return self._task_id
|
|
732
739
|
|
|
740
|
+
async def _get_command_router_client(self, task_id: str) -> Optional[TaskCommandRouterClient]:
|
|
741
|
+
if self._command_router_client is None:
|
|
742
|
+
# Attempt to initialize a router client. Returns None if the new exec path not enabled
|
|
743
|
+
# for this sandbox.
|
|
744
|
+
self._command_router_client = await TaskCommandRouterClient.try_init(self._client, task_id)
|
|
745
|
+
return self._command_router_client
|
|
746
|
+
|
|
733
747
|
@overload
|
|
734
748
|
async def exec(
|
|
735
749
|
self,
|
|
@@ -855,14 +869,49 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
855
869
|
await TaskContext.gather(*secret_coros)
|
|
856
870
|
|
|
857
871
|
task_id = await self._get_task_id()
|
|
872
|
+
kwargs = {
|
|
873
|
+
"task_id": task_id,
|
|
874
|
+
"pty_info": pty_info,
|
|
875
|
+
"stdout": stdout,
|
|
876
|
+
"stderr": stderr,
|
|
877
|
+
"timeout": timeout,
|
|
878
|
+
"workdir": workdir,
|
|
879
|
+
"secret_ids": [secret.object_id for secret in secrets],
|
|
880
|
+
"text": text,
|
|
881
|
+
"bufsize": bufsize,
|
|
882
|
+
"runtime_debug": config.get("function_runtime_debug"),
|
|
883
|
+
}
|
|
884
|
+
# NB: This must come after the task ID is set, since the sandbox must be
|
|
885
|
+
# scheduled before we can create a router client.
|
|
886
|
+
if (command_router_client := await self._get_command_router_client(task_id)) is not None:
|
|
887
|
+
kwargs["command_router_client"] = command_router_client
|
|
888
|
+
return await self._exec_through_command_router(*args, **kwargs)
|
|
889
|
+
else:
|
|
890
|
+
return await self._exec_through_server(*args, **kwargs)
|
|
891
|
+
|
|
892
|
+
async def _exec_through_server(
|
|
893
|
+
self,
|
|
894
|
+
*args: str,
|
|
895
|
+
task_id: str,
|
|
896
|
+
pty_info: Optional[api_pb2.PTYInfo] = None,
|
|
897
|
+
stdout: StreamType = StreamType.PIPE,
|
|
898
|
+
stderr: StreamType = StreamType.PIPE,
|
|
899
|
+
timeout: Optional[int] = None,
|
|
900
|
+
workdir: Optional[str] = None,
|
|
901
|
+
secret_ids: Optional[Collection[str]] = None,
|
|
902
|
+
text: bool = True,
|
|
903
|
+
bufsize: Literal[-1, 1] = -1,
|
|
904
|
+
runtime_debug: bool = False,
|
|
905
|
+
) -> Union[_ContainerProcess[bytes], _ContainerProcess[str]]:
|
|
906
|
+
"""Execute a command through the Modal server."""
|
|
858
907
|
req = api_pb2.ContainerExecRequest(
|
|
859
908
|
task_id=task_id,
|
|
860
909
|
command=args,
|
|
861
910
|
pty_info=pty_info,
|
|
862
|
-
runtime_debug=
|
|
911
|
+
runtime_debug=runtime_debug,
|
|
863
912
|
timeout_secs=timeout or 0,
|
|
864
913
|
workdir=workdir,
|
|
865
|
-
secret_ids=
|
|
914
|
+
secret_ids=secret_ids,
|
|
866
915
|
)
|
|
867
916
|
resp = await retry_transient_errors(self._client.stub.ContainerExec, req)
|
|
868
917
|
by_line = bufsize == 1
|
|
@@ -879,6 +928,75 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
879
928
|
by_line=by_line,
|
|
880
929
|
)
|
|
881
930
|
|
|
931
|
+
async def _exec_through_command_router(
|
|
932
|
+
self,
|
|
933
|
+
*args: str,
|
|
934
|
+
task_id: str,
|
|
935
|
+
command_router_client: TaskCommandRouterClient,
|
|
936
|
+
pty_info: Optional[api_pb2.PTYInfo] = None,
|
|
937
|
+
stdout: StreamType = StreamType.PIPE,
|
|
938
|
+
stderr: StreamType = StreamType.PIPE,
|
|
939
|
+
timeout: Optional[int] = None,
|
|
940
|
+
workdir: Optional[str] = None,
|
|
941
|
+
secret_ids: Optional[Collection[str]] = None,
|
|
942
|
+
text: bool = True,
|
|
943
|
+
bufsize: Literal[-1, 1] = -1,
|
|
944
|
+
runtime_debug: bool = False,
|
|
945
|
+
) -> Union[_ContainerProcess[bytes], _ContainerProcess[str]]:
|
|
946
|
+
"""Execute a command through a task command router running on the Modal worker."""
|
|
947
|
+
|
|
948
|
+
# Generate a random process ID to use as a combination of idempotency key/process identifier.
|
|
949
|
+
process_id = str(uuid.uuid4())
|
|
950
|
+
if stdout == StreamType.PIPE:
|
|
951
|
+
stdout_config = sr_pb2.TaskExecStdoutConfig.TASK_EXEC_STDOUT_CONFIG_PIPE
|
|
952
|
+
elif stdout == StreamType.DEVNULL:
|
|
953
|
+
stdout_config = sr_pb2.TaskExecStdoutConfig.TASK_EXEC_STDOUT_CONFIG_DEVNULL
|
|
954
|
+
elif stdout == StreamType.STDOUT:
|
|
955
|
+
# TODO(saltzm): This is a behavior change from the old implementation. We should
|
|
956
|
+
# probably implement the old behavior of printing to stdout before moving out of beta.
|
|
957
|
+
raise NotImplementedError(
|
|
958
|
+
"Currently the STDOUT stream type is not supported when using exec "
|
|
959
|
+
"through a task command router, which is currently in beta."
|
|
960
|
+
)
|
|
961
|
+
else:
|
|
962
|
+
raise ValueError("Unsupported StreamType for stdout")
|
|
963
|
+
|
|
964
|
+
if stderr == StreamType.PIPE:
|
|
965
|
+
stderr_config = sr_pb2.TaskExecStderrConfig.TASK_EXEC_STDERR_CONFIG_PIPE
|
|
966
|
+
elif stderr == StreamType.DEVNULL:
|
|
967
|
+
stderr_config = sr_pb2.TaskExecStderrConfig.TASK_EXEC_STDERR_CONFIG_DEVNULL
|
|
968
|
+
elif stderr == StreamType.STDOUT:
|
|
969
|
+
stderr_config = sr_pb2.TaskExecStderrConfig.TASK_EXEC_STDERR_CONFIG_STDOUT
|
|
970
|
+
else:
|
|
971
|
+
raise ValueError("Unsupported StreamType for stderr")
|
|
972
|
+
|
|
973
|
+
# Start the process.
|
|
974
|
+
start_req = sr_pb2.TaskExecStartRequest(
|
|
975
|
+
task_id=task_id,
|
|
976
|
+
exec_id=process_id,
|
|
977
|
+
command_args=args,
|
|
978
|
+
stdout_config=stdout_config,
|
|
979
|
+
stderr_config=stderr_config,
|
|
980
|
+
timeout_secs=timeout,
|
|
981
|
+
workdir=workdir,
|
|
982
|
+
secret_ids=secret_ids,
|
|
983
|
+
pty_info=pty_info,
|
|
984
|
+
runtime_debug=runtime_debug,
|
|
985
|
+
)
|
|
986
|
+
_ = await command_router_client.exec_start(start_req)
|
|
987
|
+
|
|
988
|
+
return _ContainerProcess(
|
|
989
|
+
process_id,
|
|
990
|
+
task_id,
|
|
991
|
+
self._client,
|
|
992
|
+
command_router_client=command_router_client,
|
|
993
|
+
stdout=stdout,
|
|
994
|
+
stderr=stderr,
|
|
995
|
+
text=text,
|
|
996
|
+
by_line=bufsize == 1,
|
|
997
|
+
exec_deadline=time.monotonic() + int(timeout) if timeout else None,
|
|
998
|
+
)
|
|
999
|
+
|
|
882
1000
|
async def _experimental_snapshot(self) -> _SandboxSnapshot:
|
|
883
1001
|
await self._get_task_id()
|
|
884
1002
|
snap_req = api_pb2.SandboxSnapshotRequest(sandbox_id=self.object_id)
|
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
|
|
@@ -83,6 +84,7 @@ class _Sandbox(modal._object._Object):
|
|
|
83
84
|
_task_id: typing.Optional[str]
|
|
84
85
|
_tunnels: typing.Optional[dict[int, modal._tunnel.Tunnel]]
|
|
85
86
|
_enable_snapshot: bool
|
|
87
|
+
_command_router_client: typing.Optional[modal._utils.task_command_router_client.TaskCommandRouterClient]
|
|
86
88
|
|
|
87
89
|
@staticmethod
|
|
88
90
|
def _default_pty_info() -> modal_proto.api_pb2.PTYInfo: ...
|
|
@@ -305,6 +307,9 @@ class _Sandbox(modal._object._Object):
|
|
|
305
307
|
...
|
|
306
308
|
|
|
307
309
|
async def _get_task_id(self) -> str: ...
|
|
310
|
+
async def _get_command_router_client(
|
|
311
|
+
self, task_id: str
|
|
312
|
+
) -> typing.Optional[modal._utils.task_command_router_client.TaskCommandRouterClient]: ...
|
|
308
313
|
@typing.overload
|
|
309
314
|
async def exec(
|
|
310
315
|
self,
|
|
@@ -356,6 +361,41 @@ class _Sandbox(modal._object._Object):
|
|
|
356
361
|
"""
|
|
357
362
|
...
|
|
358
363
|
|
|
364
|
+
async def _exec_through_server(
|
|
365
|
+
self,
|
|
366
|
+
*args: str,
|
|
367
|
+
task_id: str,
|
|
368
|
+
pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
|
|
369
|
+
stdout: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
|
370
|
+
stderr: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
|
371
|
+
timeout: typing.Optional[int] = None,
|
|
372
|
+
workdir: typing.Optional[str] = None,
|
|
373
|
+
secret_ids: typing.Optional[collections.abc.Collection[str]] = None,
|
|
374
|
+
text: bool = True,
|
|
375
|
+
bufsize: typing.Literal[-1, 1] = -1,
|
|
376
|
+
runtime_debug: bool = False,
|
|
377
|
+
) -> typing.Union[modal.container_process._ContainerProcess[bytes], modal.container_process._ContainerProcess[str]]:
|
|
378
|
+
"""Execute a command through the Modal server."""
|
|
379
|
+
...
|
|
380
|
+
|
|
381
|
+
async def _exec_through_command_router(
|
|
382
|
+
self,
|
|
383
|
+
*args: str,
|
|
384
|
+
task_id: str,
|
|
385
|
+
command_router_client: modal._utils.task_command_router_client.TaskCommandRouterClient,
|
|
386
|
+
pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
|
|
387
|
+
stdout: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
|
388
|
+
stderr: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
|
389
|
+
timeout: typing.Optional[int] = None,
|
|
390
|
+
workdir: typing.Optional[str] = None,
|
|
391
|
+
secret_ids: typing.Optional[collections.abc.Collection[str]] = None,
|
|
392
|
+
text: bool = True,
|
|
393
|
+
bufsize: typing.Literal[-1, 1] = -1,
|
|
394
|
+
runtime_debug: bool = False,
|
|
395
|
+
) -> typing.Union[modal.container_process._ContainerProcess[bytes], modal.container_process._ContainerProcess[str]]:
|
|
396
|
+
"""Execute a command through a task command router running on the Modal worker."""
|
|
397
|
+
...
|
|
398
|
+
|
|
359
399
|
async def _experimental_snapshot(self) -> modal.snapshot._SandboxSnapshot: ...
|
|
360
400
|
@staticmethod
|
|
361
401
|
async def _experimental_from_snapshot(
|
|
@@ -444,6 +484,7 @@ class Sandbox(modal.object.Object):
|
|
|
444
484
|
_task_id: typing.Optional[str]
|
|
445
485
|
_tunnels: typing.Optional[dict[int, modal._tunnel.Tunnel]]
|
|
446
486
|
_enable_snapshot: bool
|
|
487
|
+
_command_router_client: typing.Optional[modal._utils.task_command_router_client.TaskCommandRouterClient]
|
|
447
488
|
|
|
448
489
|
def __init__(self, *args, **kwargs):
|
|
449
490
|
"""mdmd:hidden"""
|
|
@@ -907,6 +948,16 @@ class Sandbox(modal.object.Object):
|
|
|
907
948
|
|
|
908
949
|
_get_task_id: ___get_task_id_spec[typing_extensions.Self]
|
|
909
950
|
|
|
951
|
+
class ___get_command_router_client_spec(typing_extensions.Protocol[SUPERSELF]):
|
|
952
|
+
def __call__(
|
|
953
|
+
self, /, task_id: str
|
|
954
|
+
) -> typing.Optional[modal._utils.task_command_router_client.TaskCommandRouterClient]: ...
|
|
955
|
+
async def aio(
|
|
956
|
+
self, /, task_id: str
|
|
957
|
+
) -> typing.Optional[modal._utils.task_command_router_client.TaskCommandRouterClient]: ...
|
|
958
|
+
|
|
959
|
+
_get_command_router_client: ___get_command_router_client_spec[typing_extensions.Self]
|
|
960
|
+
|
|
910
961
|
class __exec_spec(typing_extensions.Protocol[SUPERSELF]):
|
|
911
962
|
@typing.overload
|
|
912
963
|
def __call__(
|
|
@@ -1026,6 +1077,94 @@ class Sandbox(modal.object.Object):
|
|
|
1026
1077
|
|
|
1027
1078
|
_exec: ___exec_spec[typing_extensions.Self]
|
|
1028
1079
|
|
|
1080
|
+
class ___exec_through_server_spec(typing_extensions.Protocol[SUPERSELF]):
|
|
1081
|
+
def __call__(
|
|
1082
|
+
self,
|
|
1083
|
+
/,
|
|
1084
|
+
*args: str,
|
|
1085
|
+
task_id: str,
|
|
1086
|
+
pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
|
|
1087
|
+
stdout: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
|
1088
|
+
stderr: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
|
1089
|
+
timeout: typing.Optional[int] = None,
|
|
1090
|
+
workdir: typing.Optional[str] = None,
|
|
1091
|
+
secret_ids: typing.Optional[collections.abc.Collection[str]] = None,
|
|
1092
|
+
text: bool = True,
|
|
1093
|
+
bufsize: typing.Literal[-1, 1] = -1,
|
|
1094
|
+
runtime_debug: bool = False,
|
|
1095
|
+
) -> typing.Union[
|
|
1096
|
+
modal.container_process.ContainerProcess[bytes], modal.container_process.ContainerProcess[str]
|
|
1097
|
+
]:
|
|
1098
|
+
"""Execute a command through the Modal server."""
|
|
1099
|
+
...
|
|
1100
|
+
|
|
1101
|
+
async def aio(
|
|
1102
|
+
self,
|
|
1103
|
+
/,
|
|
1104
|
+
*args: str,
|
|
1105
|
+
task_id: str,
|
|
1106
|
+
pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
|
|
1107
|
+
stdout: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
|
1108
|
+
stderr: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
|
1109
|
+
timeout: typing.Optional[int] = None,
|
|
1110
|
+
workdir: typing.Optional[str] = None,
|
|
1111
|
+
secret_ids: typing.Optional[collections.abc.Collection[str]] = None,
|
|
1112
|
+
text: bool = True,
|
|
1113
|
+
bufsize: typing.Literal[-1, 1] = -1,
|
|
1114
|
+
runtime_debug: bool = False,
|
|
1115
|
+
) -> typing.Union[
|
|
1116
|
+
modal.container_process.ContainerProcess[bytes], modal.container_process.ContainerProcess[str]
|
|
1117
|
+
]:
|
|
1118
|
+
"""Execute a command through the Modal server."""
|
|
1119
|
+
...
|
|
1120
|
+
|
|
1121
|
+
_exec_through_server: ___exec_through_server_spec[typing_extensions.Self]
|
|
1122
|
+
|
|
1123
|
+
class ___exec_through_command_router_spec(typing_extensions.Protocol[SUPERSELF]):
|
|
1124
|
+
def __call__(
|
|
1125
|
+
self,
|
|
1126
|
+
/,
|
|
1127
|
+
*args: str,
|
|
1128
|
+
task_id: str,
|
|
1129
|
+
command_router_client: modal._utils.task_command_router_client.TaskCommandRouterClient,
|
|
1130
|
+
pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
|
|
1131
|
+
stdout: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
|
1132
|
+
stderr: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
|
1133
|
+
timeout: typing.Optional[int] = None,
|
|
1134
|
+
workdir: typing.Optional[str] = None,
|
|
1135
|
+
secret_ids: typing.Optional[collections.abc.Collection[str]] = None,
|
|
1136
|
+
text: bool = True,
|
|
1137
|
+
bufsize: typing.Literal[-1, 1] = -1,
|
|
1138
|
+
runtime_debug: bool = False,
|
|
1139
|
+
) -> typing.Union[
|
|
1140
|
+
modal.container_process.ContainerProcess[bytes], modal.container_process.ContainerProcess[str]
|
|
1141
|
+
]:
|
|
1142
|
+
"""Execute a command through a task command router running on the Modal worker."""
|
|
1143
|
+
...
|
|
1144
|
+
|
|
1145
|
+
async def aio(
|
|
1146
|
+
self,
|
|
1147
|
+
/,
|
|
1148
|
+
*args: str,
|
|
1149
|
+
task_id: str,
|
|
1150
|
+
command_router_client: modal._utils.task_command_router_client.TaskCommandRouterClient,
|
|
1151
|
+
pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
|
|
1152
|
+
stdout: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
|
1153
|
+
stderr: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
|
1154
|
+
timeout: typing.Optional[int] = None,
|
|
1155
|
+
workdir: typing.Optional[str] = None,
|
|
1156
|
+
secret_ids: typing.Optional[collections.abc.Collection[str]] = None,
|
|
1157
|
+
text: bool = True,
|
|
1158
|
+
bufsize: typing.Literal[-1, 1] = -1,
|
|
1159
|
+
runtime_debug: bool = False,
|
|
1160
|
+
) -> typing.Union[
|
|
1161
|
+
modal.container_process.ContainerProcess[bytes], modal.container_process.ContainerProcess[str]
|
|
1162
|
+
]:
|
|
1163
|
+
"""Execute a command through a task command router running on the Modal worker."""
|
|
1164
|
+
...
|
|
1165
|
+
|
|
1166
|
+
_exec_through_command_router: ___exec_through_command_router_spec[typing_extensions.Self]
|
|
1167
|
+
|
|
1029
1168
|
class ___experimental_snapshot_spec(typing_extensions.Protocol[SUPERSELF]):
|
|
1030
1169
|
def __call__(self, /) -> modal.snapshot.SandboxSnapshot: ...
|
|
1031
1170
|
async def aio(self, /) -> modal.snapshot.SandboxSnapshot: ...
|
|
@@ -24,14 +24,14 @@ modal/app.pyi,sha256=AUV5Rp8qQrZJTP2waoKHFY7rYgsXNMYibMcCAQKuSeo,50544
|
|
|
24
24
|
modal/billing.py,sha256=zmQ3bcCJlwa4KD1IA_QgdWpm1pn13c-7qfy79iEauYI,195
|
|
25
25
|
modal/call_graph.py,sha256=1g2DGcMIJvRy-xKicuf63IVE98gJSnQsr8R_NVMptNc,2581
|
|
26
26
|
modal/client.py,sha256=kyAIVB3Ay-XKJizQ_1ufUFB__EagV0MLmHJpyYyJ7J0,18636
|
|
27
|
-
modal/client.pyi,sha256=
|
|
27
|
+
modal/client.pyi,sha256=w4D59FS-waDxl9dip8AM6LuabB6haDqnmGykntaCSmI,15831
|
|
28
28
|
modal/cloud_bucket_mount.py,sha256=I2GRXYhOWLIz2kJZjXu75jAm9EJkBNcutGc6jR2ReUw,5928
|
|
29
29
|
modal/cloud_bucket_mount.pyi,sha256=VuUOipMIHqFXMkD-3g2bsoqpSxV5qswlFHDOqPQzYAo,7405
|
|
30
30
|
modal/cls.py,sha256=ZxzivE3fNci4-A5uyBYNAzXMXtdqDg3gnYvgbdy5fhg,40384
|
|
31
31
|
modal/cls.pyi,sha256=jJsDPFoqzM4ht-V-e-xEJKJ5TINLF0fYtoBm_UeAW5Y,27281
|
|
32
32
|
modal/config.py,sha256=hpgkgQKbjzo6gVbRzXQrky72_KpdSEm65RNi1M2iNjc,13038
|
|
33
|
-
modal/container_process.py,sha256=
|
|
34
|
-
modal/container_process.pyi,sha256=
|
|
33
|
+
modal/container_process.py,sha256=S-JgzAqEBlYWw7f5gwbb_RVKA2APn-VAnInrntIWBL0,16948
|
|
34
|
+
modal/container_process.pyi,sha256=xMKr-VbQsydS8AbhAys9UTpHHnH2QRyINpPtPG7NwmI,8373
|
|
35
35
|
modal/dict.py,sha256=XkaxuojMVtcc4bZvCjJcd6DedU5xxfF8H4w-mDzFPCo,21580
|
|
36
36
|
modal/dict.pyi,sha256=deOiwuwZtwXqedC3h19SwoQIWc4mUnDTBM5XkONt48Y,31712
|
|
37
37
|
modal/environments.py,sha256=xXYDfgzd20CuFdww_zQ53OB0qANQG-j_ls_fT7mGdoQ,6028
|
|
@@ -41,11 +41,11 @@ modal/file_io.py,sha256=OSKr77TujcXGJW1iikzYiHckLSmv07QBgBHcxxYEkoI,21456
|
|
|
41
41
|
modal/file_io.pyi,sha256=xtO6Glf_BFwDE7QiQQo24QqcMf_Vv-iz7WojcGVlLBU,15932
|
|
42
42
|
modal/file_pattern_matcher.py,sha256=A_Kdkej6q7YQyhM_2-BvpFmPqJ0oHb54B6yf9VqvPVE,8116
|
|
43
43
|
modal/functions.py,sha256=kcNHvqeGBxPI7Cgd57NIBBghkfbeFJzXO44WW0jSmao,325
|
|
44
|
-
modal/functions.pyi,sha256=
|
|
44
|
+
modal/functions.pyi,sha256=CMwApS396tdElFrjnV6RuL2DTCz4C3jYzYoq1y_LPUQ,37988
|
|
45
45
|
modal/gpu.py,sha256=Fe5ORvVPDIstSq1xjmM6OoNgLYFWvogP9r5BgmD3hYg,6769
|
|
46
46
|
modal/image.py,sha256=HDkOnhIAN8g63a8LTN4J5SjC9ciReFQQJIxTS2z5KFM,107216
|
|
47
47
|
modal/image.pyi,sha256=dMvMwAuvWkNN2BRYJFijkEy2m_xtEXgCKK0T7FVldsc,77514
|
|
48
|
-
modal/io_streams.py,sha256=
|
|
48
|
+
modal/io_streams.py,sha256=6fTMyPt8wCdoWFH5EuEBoW1Ye0dHITaxxMmzDPA-sdM,29565
|
|
49
49
|
modal/io_streams.pyi,sha256=h7qtAbj8LsN-eJKAGjBhnMBegvWprc_0AmwVFi6rj2Y,18084
|
|
50
50
|
modal/mount.py,sha256=G7_xhQMZqokgfsaFLMch0YR3fs-OUNqYUm3f4jHTSMQ,33161
|
|
51
51
|
modal/mount.pyi,sha256=MD_zV2M7eCWxbOpQRjU60aHevN-bmbiywaCX82QoFlw,15380
|
|
@@ -67,8 +67,8 @@ modal/retries.py,sha256=IvNLDM0f_GLUDD5VgEDoN09C88yoxSrCquinAuxT1Sc,5205
|
|
|
67
67
|
modal/runner.py,sha256=Ni54hwa42SEBxLPpqFwKMsUPYY8Dv-I-Kz3_jL1StCI,25220
|
|
68
68
|
modal/runner.pyi,sha256=DV3Z7h0owgRyOu9W5KU5O3UbRftX99KGrZQId91fpsU,8671
|
|
69
69
|
modal/running_app.py,sha256=v61mapYNV1-O-Uaho5EfJlryMLvIT9We0amUOSvSGx8,1188
|
|
70
|
-
modal/sandbox.py,sha256=
|
|
71
|
-
modal/sandbox.pyi,sha256=
|
|
70
|
+
modal/sandbox.py,sha256=QHpnp7ifmlVSzJcJyRCEHYmhvu5SrLBVjIx6gaTnlXg,51071
|
|
71
|
+
modal/sandbox.pyi,sha256=VqGO59NZX5fSU1tnA_g0pAd7eq6GvV6lNtC8TH9Xlo8,57478
|
|
72
72
|
modal/schedule.py,sha256=ng0g0AqNY5GQI9KhkXZQ5Wam5G42glbkqVQsNpBtbDE,3078
|
|
73
73
|
modal/scheduler_placement.py,sha256=BAREdOY5HzHpzSBqt6jDVR6YC_jYfHMVqOzkyqQfngU,1235
|
|
74
74
|
modal/secret.py,sha256=ThwP-PkwUZwiYkygqumh15n8P_77-N5ZyRWLc6I3r28,18323
|
|
@@ -113,7 +113,7 @@ modal/_utils/package_utils.py,sha256=LcL2olGN4xaUzu2Tbv-C-Ft9Qp6bsLxEfETOAVd-mjU
|
|
|
113
113
|
modal/_utils/pattern_utils.py,sha256=ZUffaECfe2iYBhH6cvCB-0-UWhmEBTZEl_TwG_So3ag,6714
|
|
114
114
|
modal/_utils/rand_pb_testing.py,sha256=mmVPk1rZldHwHZx0DnHTuHQlRLAiiAYdxjwEJpxvT9c,3900
|
|
115
115
|
modal/_utils/shell_utils.py,sha256=hWHzv730Br2Xyj6cGPiMZ-198Z3RZuOu3pDXhFSZ22c,2157
|
|
116
|
-
modal/_utils/task_command_router_client.py,sha256=
|
|
116
|
+
modal/_utils/task_command_router_client.py,sha256=ugWyExVncfs_9SbcPaWjMi3gmXPaQWI-8LuL-xHah7M,23589
|
|
117
117
|
modal/_utils/time_utils.py,sha256=43tpFVwT7ykOjlETIFLVt9auMsRZqYYRYBEKxGCrRSA,1212
|
|
118
118
|
modal/_vendor/__init__.py,sha256=MIEP8jhXUeGq_eCjYFcqN5b1bxBM4fdk0VESpjWR0fc,28
|
|
119
119
|
modal/_vendor/a2wsgi_wsgi.py,sha256=Q1AsjpV_Q_vzQsz_cSqmP9jWzsGsB-ARFU6vpQYml8k,21878
|
|
@@ -156,7 +156,7 @@ modal/experimental/__init__.py,sha256=9gkVuDmu3m4TlKoU3MzEtTOemUSs8EEOWba40s7Aa0
|
|
|
156
156
|
modal/experimental/flash.py,sha256=-lSyFBbeT6UT-uB29L955SNh6L6ISg_uBDy5gF4ZpLo,26919
|
|
157
157
|
modal/experimental/flash.pyi,sha256=uwinKAYxpunNNfBj58FP88DXb535Qik4F6tnJKPAIwQ,14696
|
|
158
158
|
modal/experimental/ipython.py,sha256=TrCfmol9LGsRZMeDoeMPx3Hv3BFqQhYnmD_iH0pqdhk,2904
|
|
159
|
-
modal-1.2.1.
|
|
159
|
+
modal-1.2.1.dev16.dist-info/licenses/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
|
|
160
160
|
modal_docs/__init__.py,sha256=svYKtV8HDwDCN86zbdWqyq5T8sMdGDj0PVlzc2tIxDM,28
|
|
161
161
|
modal_docs/gen_cli_docs.py,sha256=c1yfBS_x--gL5bs0N4ihMwqwX8l3IBWSkBAKNNIi6bQ,3801
|
|
162
162
|
modal_docs/gen_reference_docs.py,sha256=d_CQUGQ0rfw28u75I2mov9AlS773z9rG40-yq5o7g2U,6359
|
|
@@ -184,10 +184,10 @@ modal_proto/task_command_router_pb2.py,sha256=_pD2ZpU0bNzhwBdzmLoLyLtAtftI_Agxwn
|
|
|
184
184
|
modal_proto/task_command_router_pb2.pyi,sha256=EyDgXPLr7alqjXYERV8w_MPuO404x0uCppmSkrfE9IE,14589
|
|
185
185
|
modal_proto/task_command_router_pb2_grpc.py,sha256=uEQ0HdrCp8v-9bB5yIic9muA8spCShLHY6Bz9cCgOUE,10114
|
|
186
186
|
modal_proto/task_command_router_pb2_grpc.pyi,sha256=s3Yxsrawdj4nr8vqQqsAxyX6ilWaGbdECy425KKbLIA,3301
|
|
187
|
-
modal_version/__init__.py,sha256=
|
|
187
|
+
modal_version/__init__.py,sha256=3gamILnSS1yoiqvQH-M3ton5KUFBv4m7Kc5tIOOJTsU,121
|
|
188
188
|
modal_version/__main__.py,sha256=2FO0yYQQwDTh6udt1h-cBnGd1c4ZyHnHSI4BksxzVac,105
|
|
189
|
-
modal-1.2.1.
|
|
190
|
-
modal-1.2.1.
|
|
191
|
-
modal-1.2.1.
|
|
192
|
-
modal-1.2.1.
|
|
193
|
-
modal-1.2.1.
|
|
189
|
+
modal-1.2.1.dev16.dist-info/METADATA,sha256=JezoR7gj50q88E7bk4WMlmG8CFOGmgzVjfD6BviUXiE,2484
|
|
190
|
+
modal-1.2.1.dev16.dist-info/WHEEL,sha256=1tXe9gY0PYatrMPMDd6jXqjfpz_B-Wqm32CPfRC58XU,91
|
|
191
|
+
modal-1.2.1.dev16.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
|
|
192
|
+
modal-1.2.1.dev16.dist-info/top_level.txt,sha256=4BWzoKYREKUZ5iyPzZpjqx4G8uB5TWxXPDwibLcVa7k,43
|
|
193
|
+
modal-1.2.1.dev16.dist-info/RECORD,,
|
modal_version/__init__.py
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|