modAL 1.4.4.dev6__py3-none-any.whl → 1.4.4.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.
- modal/_runtime/asgi.py +1 -1
- modal/cli/shell.py +12 -10
- modal/client.pyi +2 -2
- modal/io_streams.py +1 -1
- modal/io_streams.pyi +2 -0
- modal/sandbox.py +78 -20
- modal/sandbox.pyi +88 -33
- modal/sandbox_fs.py +21 -16
- modal/sandbox_fs.pyi +9 -2
- {modal-1.4.4.dev6.dist-info → modal-1.4.4.dev8.dist-info}/METADATA +1 -1
- {modal-1.4.4.dev6.dist-info → modal-1.4.4.dev8.dist-info}/RECORD +16 -16
- modal_version/__init__.py +1 -1
- {modal-1.4.4.dev6.dist-info → modal-1.4.4.dev8.dist-info}/WHEEL +0 -0
- {modal-1.4.4.dev6.dist-info → modal-1.4.4.dev8.dist-info}/entry_points.txt +0 -0
- {modal-1.4.4.dev6.dist-info → modal-1.4.4.dev8.dist-info}/licenses/LICENSE +0 -0
- {modal-1.4.4.dev6.dist-info → modal-1.4.4.dev8.dist-info}/top_level.txt +0 -0
modal/_runtime/asgi.py
CHANGED
|
@@ -285,7 +285,7 @@ def wait_for_web_server(host: str, port: int, *, timeout: float) -> None:
|
|
|
285
285
|
start_time = time.monotonic()
|
|
286
286
|
while True:
|
|
287
287
|
try:
|
|
288
|
-
with socket.create_connection((host, port), timeout=timeout):
|
|
288
|
+
with socket.create_connection((host, port), timeout=min(timeout, 1.0)):
|
|
289
289
|
break
|
|
290
290
|
except OSError as ex:
|
|
291
291
|
time.sleep(0.01)
|
modal/cli/shell.py
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import platform
|
|
3
3
|
import shlex
|
|
4
4
|
from pathlib import Path, PurePosixPath
|
|
5
|
-
from typing import Any, Callable, Iterable, Optional
|
|
5
|
+
from typing import Any, Callable, Iterable, Optional, Union
|
|
6
6
|
|
|
7
7
|
import click
|
|
8
8
|
from click import ClickException
|
|
@@ -10,12 +10,13 @@ from click import ClickException
|
|
|
10
10
|
from .._environments import ensure_env
|
|
11
11
|
from .._functions import _FunctionSpec
|
|
12
12
|
from ..app import App
|
|
13
|
+
from ..container_process import ContainerProcess
|
|
13
14
|
from ..exception import InvalidError, NotFoundError
|
|
14
15
|
from ..functions import Function
|
|
15
16
|
from ..image import Image
|
|
16
17
|
from ..mount import _Mount
|
|
17
18
|
from ..runner import interactive_shell
|
|
18
|
-
from ..sandbox import Sandbox
|
|
19
|
+
from ..sandbox import _MAIN_CONTAINER_NAME, Sandbox
|
|
19
20
|
from ..secret import Secret
|
|
20
21
|
from ..stream_type import StreamType
|
|
21
22
|
from ..volume import Volume
|
|
@@ -105,8 +106,8 @@ def _is_running_container_ref(ref: Optional[str]) -> bool:
|
|
|
105
106
|
return _is_valid_modal_id(sandbox_id, "sb-") or _is_valid_modal_id(ref, "ta-")
|
|
106
107
|
|
|
107
108
|
|
|
108
|
-
def
|
|
109
|
-
"""Shell into a
|
|
109
|
+
def _start_shell_in_sidecar_container(sandbox_id: str, container_name: str, cmd: str, pty: bool) -> None:
|
|
110
|
+
"""Shell into a sidecar container within a sandbox."""
|
|
110
111
|
try:
|
|
111
112
|
sandbox = Sandbox.from_id(sandbox_id)
|
|
112
113
|
except NotFoundError:
|
|
@@ -115,18 +116,19 @@ def _start_shell_in_sandbox_container(sandbox_id: str, container_name: str, cmd:
|
|
|
115
116
|
raise ClickException(f"Error connecting to Sandbox '{sandbox_id}': {str(e)}")
|
|
116
117
|
|
|
117
118
|
try:
|
|
118
|
-
sandbox_container = sandbox.
|
|
119
|
+
sandbox_container = sandbox._experimental_sidecars.get(name=container_name)
|
|
120
|
+
process: Union[ContainerProcess[bytes], ContainerProcess[str]]
|
|
119
121
|
if pty:
|
|
120
122
|
# PTY output is raw terminal bytes, not text; strict UTF-8 decode
|
|
121
123
|
# crashes on the first non-UTF-8 byte (e.g. vim drawing a Latin-1
|
|
122
124
|
# file under LC_CTYPE=C). See the matching call in `_exec_impl`.
|
|
123
|
-
process = sandbox_container.exec(*shlex.split(cmd), pty=
|
|
125
|
+
process = sandbox_container.exec(*shlex.split(cmd), pty=True, text=False)
|
|
124
126
|
process.attach()
|
|
125
127
|
else:
|
|
126
128
|
process = sandbox_container.exec(
|
|
127
|
-
*shlex.split(cmd), pty=
|
|
129
|
+
*shlex.split(cmd), pty=False, text=False, stdout=StreamType.STDOUT, stderr=StreamType.STDOUT
|
|
128
130
|
)
|
|
129
|
-
process.wait()
|
|
131
|
+
_ = process.wait()
|
|
130
132
|
except NotFoundError:
|
|
131
133
|
raise ClickException(f"Container '{container_name}' not found in Sandbox '{sandbox_id}'.")
|
|
132
134
|
except Exception as e:
|
|
@@ -136,8 +138,8 @@ def _start_shell_in_sandbox_container(sandbox_id: str, container_name: str, cmd:
|
|
|
136
138
|
def _start_shell_in_running_container(ref: str, cmd: str, pty: bool) -> None:
|
|
137
139
|
sandbox_id, container_name = _parse_sandbox_container_ref(ref)
|
|
138
140
|
|
|
139
|
-
if container_name is not None:
|
|
140
|
-
return
|
|
141
|
+
if container_name is not None and container_name != _MAIN_CONTAINER_NAME:
|
|
142
|
+
return _start_shell_in_sidecar_container(sandbox_id, container_name, cmd, pty)
|
|
141
143
|
|
|
142
144
|
if _is_valid_modal_id(sandbox_id, "sb-"):
|
|
143
145
|
try:
|
modal/client.pyi
CHANGED
|
@@ -35,7 +35,7 @@ class _Client:
|
|
|
35
35
|
server_url: str,
|
|
36
36
|
client_type: int,
|
|
37
37
|
credentials: typing.Optional[tuple[str, str]],
|
|
38
|
-
version: str = "1.4.4.
|
|
38
|
+
version: str = "1.4.4.dev8",
|
|
39
39
|
):
|
|
40
40
|
"""mdmd:hidden
|
|
41
41
|
The Modal client object is not intended to be instantiated directly by users.
|
|
@@ -175,7 +175,7 @@ class Client:
|
|
|
175
175
|
server_url: str,
|
|
176
176
|
client_type: int,
|
|
177
177
|
credentials: typing.Optional[tuple[str, str]],
|
|
178
|
-
version: str = "1.4.4.
|
|
178
|
+
version: str = "1.4.4.dev8",
|
|
179
179
|
):
|
|
180
180
|
"""mdmd:hidden
|
|
181
181
|
The Modal client object is not intended to be instantiated directly by users.
|
modal/io_streams.py
CHANGED
|
@@ -501,7 +501,7 @@ class _StreamReader(Generic[T]):
|
|
|
501
501
|
MAX_BUFFER_SIZE = 2 * 1024 * 1024
|
|
502
502
|
# Larger buffer limit for the exec path via the task command router.
|
|
503
503
|
# This applies only to task_exec_stdin_write; sandbox stdin via the server keeps MAX_BUFFER_SIZE.
|
|
504
|
-
TASK_COMMAND_ROUTER_MAX_BUFFER_SIZE = 16 * 1024 * 1024
|
|
504
|
+
TASK_COMMAND_ROUTER_MAX_BUFFER_SIZE: int = 16 * 1024 * 1024
|
|
505
505
|
|
|
506
506
|
|
|
507
507
|
@dataclass(frozen=True)
|
modal/io_streams.pyi
CHANGED
modal/sandbox.py
CHANGED
|
@@ -5,6 +5,7 @@ import enum
|
|
|
5
5
|
import json
|
|
6
6
|
import os
|
|
7
7
|
import time
|
|
8
|
+
import typing
|
|
8
9
|
import uuid
|
|
9
10
|
from collections.abc import AsyncGenerator, Collection, Sequence
|
|
10
11
|
from dataclasses import dataclass
|
|
@@ -1385,10 +1386,10 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
1385
1386
|
return self._command_router_client
|
|
1386
1387
|
|
|
1387
1388
|
@property
|
|
1388
|
-
def
|
|
1389
|
-
"""Manage
|
|
1389
|
+
def _experimental_sidecars(self) -> "_SidecarManager":
|
|
1390
|
+
"""Manage sidecar containers running in this Sandbox."""
|
|
1390
1391
|
self._ensure_attached()
|
|
1391
|
-
return
|
|
1392
|
+
return _SidecarManager(self)
|
|
1392
1393
|
|
|
1393
1394
|
@overload
|
|
1394
1395
|
async def exec(
|
|
@@ -1853,10 +1854,11 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
1853
1854
|
before_timestamp = resp.sandboxes[-1].created_at
|
|
1854
1855
|
|
|
1855
1856
|
|
|
1856
|
-
class
|
|
1857
|
+
class _SidecarContainer:
|
|
1857
1858
|
"""Handle to an additional container running in a Sandbox."""
|
|
1858
1859
|
|
|
1859
1860
|
_result: Optional[api_pb2.GenericResult]
|
|
1861
|
+
_filesystem: Optional[_SandboxFilesystem]
|
|
1860
1862
|
|
|
1861
1863
|
def __init__(
|
|
1862
1864
|
self,
|
|
@@ -1869,6 +1871,7 @@ class _SandboxContainer:
|
|
|
1869
1871
|
self._container_id = container_id
|
|
1870
1872
|
self._container_name = container_name
|
|
1871
1873
|
self._result = result
|
|
1874
|
+
self._filesystem = None
|
|
1872
1875
|
|
|
1873
1876
|
@property
|
|
1874
1877
|
def object_id(self) -> str:
|
|
@@ -1879,9 +1882,9 @@ class _SandboxContainer:
|
|
|
1879
1882
|
return self._container_name
|
|
1880
1883
|
|
|
1881
1884
|
@staticmethod
|
|
1882
|
-
def _from_container_info(sandbox: "_Sandbox", container_info: sr_pb2.TaskContainerInfo) -> "
|
|
1885
|
+
def _from_container_info(sandbox: "_Sandbox", container_info: sr_pb2.TaskContainerInfo) -> "_SidecarContainer":
|
|
1883
1886
|
result = container_info.result if container_info.HasField("result") else None
|
|
1884
|
-
return
|
|
1887
|
+
return _SidecarContainer(sandbox, container_info.container_id, container_info.container_name, result)
|
|
1885
1888
|
|
|
1886
1889
|
async def _get_command_router(self) -> tuple[str, "TaskCommandRouterClient"]:
|
|
1887
1890
|
"""Get task ID and command router client."""
|
|
@@ -1889,6 +1892,40 @@ class _SandboxContainer:
|
|
|
1889
1892
|
command_router_client = await self._sandbox._get_command_router_client(task_id)
|
|
1890
1893
|
return task_id, command_router_client
|
|
1891
1894
|
|
|
1895
|
+
@typing.overload
|
|
1896
|
+
async def exec(
|
|
1897
|
+
self,
|
|
1898
|
+
*args: str,
|
|
1899
|
+
stdout: StreamType = StreamType.PIPE,
|
|
1900
|
+
stderr: StreamType = StreamType.PIPE,
|
|
1901
|
+
timeout: Optional[int] = None,
|
|
1902
|
+
workdir: Optional[str] = None,
|
|
1903
|
+
env: Optional[dict[str, Optional[str]]] = None,
|
|
1904
|
+
secrets: Optional[Collection[_Secret]] = None,
|
|
1905
|
+
text: Literal[True] = True,
|
|
1906
|
+
bufsize: Literal[-1, 1] = -1,
|
|
1907
|
+
# Enable a PTY for the command. When enabled, all output (stdout and stderr from the
|
|
1908
|
+
# process) is multiplexed into stdout, and the stderr stream is effectively empty.
|
|
1909
|
+
pty: bool = False,
|
|
1910
|
+
) -> _ContainerProcess[str]: ...
|
|
1911
|
+
|
|
1912
|
+
@typing.overload
|
|
1913
|
+
async def exec(
|
|
1914
|
+
self,
|
|
1915
|
+
*args: str,
|
|
1916
|
+
stdout: StreamType = StreamType.PIPE,
|
|
1917
|
+
stderr: StreamType = StreamType.PIPE,
|
|
1918
|
+
timeout: Optional[int] = None,
|
|
1919
|
+
workdir: Optional[str] = None,
|
|
1920
|
+
env: Optional[dict[str, Optional[str]]] = None,
|
|
1921
|
+
secrets: Optional[Collection[_Secret]] = None,
|
|
1922
|
+
text: Literal[False],
|
|
1923
|
+
bufsize: Literal[-1, 1] = -1,
|
|
1924
|
+
# Enable a PTY for the command. When enabled, all output (stdout and stderr from the
|
|
1925
|
+
# process) is multiplexed into stdout, and the stderr stream is effectively empty.
|
|
1926
|
+
pty: bool = False,
|
|
1927
|
+
) -> _ContainerProcess[bytes]: ...
|
|
1928
|
+
|
|
1892
1929
|
async def exec(
|
|
1893
1930
|
self,
|
|
1894
1931
|
*args: str,
|
|
@@ -1919,6 +1956,13 @@ class _SandboxContainer:
|
|
|
1919
1956
|
container_id=self._container_id,
|
|
1920
1957
|
)
|
|
1921
1958
|
|
|
1959
|
+
@property
|
|
1960
|
+
def filesystem(self) -> _SandboxFilesystem:
|
|
1961
|
+
"""Namespace for filesystem APIs."""
|
|
1962
|
+
if self._filesystem is None:
|
|
1963
|
+
self._filesystem = _SandboxFilesystem(self)
|
|
1964
|
+
return self._filesystem
|
|
1965
|
+
|
|
1922
1966
|
async def wait(self, raise_on_termination: bool = True) -> None:
|
|
1923
1967
|
if self._result is not None and self._result.status != api_pb2.GenericResult.GENERIC_STATUS_UNSPECIFIED:
|
|
1924
1968
|
if self._result.status == api_pb2.GenericResult.GENERIC_STATUS_TERMINATED and raise_on_termination:
|
|
@@ -1987,8 +2031,11 @@ class _SandboxContainer:
|
|
|
1987
2031
|
return _result_returncode(self._result)
|
|
1988
2032
|
|
|
1989
2033
|
|
|
1990
|
-
|
|
1991
|
-
|
|
2034
|
+
_MAIN_CONTAINER_NAME: str = "main"
|
|
2035
|
+
|
|
2036
|
+
|
|
2037
|
+
class _SidecarManager:
|
|
2038
|
+
"""Creates and manages sidecar containers in a Sandbox."""
|
|
1992
2039
|
|
|
1993
2040
|
def __init__(self, sandbox: _Sandbox) -> None:
|
|
1994
2041
|
self._sandbox = sandbox
|
|
@@ -2007,22 +2054,24 @@ class _SandboxContainerManager:
|
|
|
2007
2054
|
env: Optional[dict[str, str]] = None,
|
|
2008
2055
|
secrets: Optional[Collection[_Secret]] = None,
|
|
2009
2056
|
workdir: Optional[str] = None,
|
|
2010
|
-
) ->
|
|
2057
|
+
) -> _SidecarContainer:
|
|
2058
|
+
if name == _MAIN_CONTAINER_NAME:
|
|
2059
|
+
raise InvalidError(f"The name {_MAIN_CONTAINER_NAME!r} is reserved for the sandbox's main container.")
|
|
2011
2060
|
if workdir is not None and not workdir.startswith("/"):
|
|
2012
2061
|
raise InvalidError(f"workdir must be an absolute path, got: {workdir}")
|
|
2013
2062
|
_validate_exec_args(args)
|
|
2014
2063
|
|
|
2015
2064
|
if image._mount_layers:
|
|
2016
2065
|
raise InvalidError(
|
|
2017
|
-
"Sandbox.
|
|
2066
|
+
"Sandbox._experimental_sidecars.create(image=...) only supports pre-built images. "
|
|
2018
2067
|
"When using `add_local*` methods, specify `copy=True` and call `.build()` before passing "
|
|
2019
|
-
"the image to `.
|
|
2068
|
+
"the image to `._experimental_sidecars.create()`:\n\nE.g.\n"
|
|
2020
2069
|
'img = modal.Image.debian_slim().add_local_file("foo", "/foo", copy=True).build(app)\n'
|
|
2021
|
-
'sandbox.
|
|
2070
|
+
'sandbox._experimental_sidecars.create(name="worker", image=img)'
|
|
2022
2071
|
)
|
|
2023
2072
|
if not image._object_id:
|
|
2024
2073
|
raise InvalidError(
|
|
2025
|
-
"Sandbox.
|
|
2074
|
+
"Sandbox._experimental_sidecars.create(image=...) currently only supports Images that are "
|
|
2026
2075
|
"either:\n"
|
|
2027
2076
|
"- prebuilt using `image.build()`\n"
|
|
2028
2077
|
"- referenced by id, e.g. `Image.from_id()`\n"
|
|
@@ -2048,9 +2097,14 @@ class _SandboxContainerManager:
|
|
|
2048
2097
|
create_resp = await command_router_client.container_create(create_req)
|
|
2049
2098
|
container_id = create_resp.container_id
|
|
2050
2099
|
container_name = create_resp.container_name or name
|
|
2051
|
-
return
|
|
2100
|
+
return _SidecarContainer(self._sandbox, container_id, container_name)
|
|
2052
2101
|
|
|
2053
|
-
async def get(self, *, name: str, include_terminated: bool = False) -> "
|
|
2102
|
+
async def get(self, *, name: str, include_terminated: bool = False) -> "_SidecarContainer":
|
|
2103
|
+
if name == _MAIN_CONTAINER_NAME:
|
|
2104
|
+
raise InvalidError(
|
|
2105
|
+
"Cannot get the main sandbox container through the sidecars API. "
|
|
2106
|
+
"Use Sandbox methods directly to interact with the main container."
|
|
2107
|
+
)
|
|
2054
2108
|
task_id, command_router_client = await self._get_command_router()
|
|
2055
2109
|
resp = await command_router_client.container_get(
|
|
2056
2110
|
sr_pb2.TaskContainerGetRequest(
|
|
@@ -2059,16 +2113,20 @@ class _SandboxContainerManager:
|
|
|
2059
2113
|
include_terminated=include_terminated,
|
|
2060
2114
|
)
|
|
2061
2115
|
)
|
|
2062
|
-
return
|
|
2116
|
+
return _SidecarContainer._from_container_info(self._sandbox, resp.container)
|
|
2063
2117
|
|
|
2064
|
-
async def list(self, include_terminated: bool = False) -> builtins.list[
|
|
2118
|
+
async def list(self, include_terminated: bool = False) -> builtins.list[_SidecarContainer]:
|
|
2065
2119
|
task_id, command_router_client = await self._get_command_router()
|
|
2066
2120
|
resp = await command_router_client.container_list(
|
|
2067
2121
|
sr_pb2.TaskContainerListRequest(task_id=task_id, include_terminated=include_terminated)
|
|
2068
2122
|
)
|
|
2069
|
-
return [
|
|
2123
|
+
return [
|
|
2124
|
+
_SidecarContainer._from_container_info(self._sandbox, container)
|
|
2125
|
+
for container in resp.containers
|
|
2126
|
+
if container.container_name != _MAIN_CONTAINER_NAME
|
|
2127
|
+
]
|
|
2070
2128
|
|
|
2071
2129
|
|
|
2072
|
-
|
|
2073
|
-
|
|
2130
|
+
SidecarContainer = synchronize_api(_SidecarContainer)
|
|
2131
|
+
SidecarManager = synchronize_api(_SidecarManager)
|
|
2074
2132
|
Sandbox = synchronize_api(_Sandbox)
|
modal/sandbox.pyi
CHANGED
|
@@ -533,8 +533,8 @@ class _Sandbox(modal._object._Object):
|
|
|
533
533
|
self, task_id: str
|
|
534
534
|
) -> modal._utils.task_command_router_client.TaskCommandRouterClient: ...
|
|
535
535
|
@property
|
|
536
|
-
def
|
|
537
|
-
"""Manage
|
|
536
|
+
def _experimental_sidecars(self) -> _SidecarManager:
|
|
537
|
+
"""Manage sidecar containers running in this Sandbox."""
|
|
538
538
|
...
|
|
539
539
|
|
|
540
540
|
@typing.overload
|
|
@@ -697,10 +697,11 @@ class _Sandbox(modal._object._Object):
|
|
|
697
697
|
"""
|
|
698
698
|
...
|
|
699
699
|
|
|
700
|
-
class
|
|
700
|
+
class _SidecarContainer:
|
|
701
701
|
"""Handle to an additional container running in a Sandbox."""
|
|
702
702
|
|
|
703
703
|
_result: typing.Optional[modal_proto.api_pb2.GenericResult]
|
|
704
|
+
_filesystem: typing.Optional[modal.sandbox_fs._SandboxFilesystem]
|
|
704
705
|
|
|
705
706
|
def __init__(
|
|
706
707
|
self,
|
|
@@ -719,11 +720,12 @@ class _SandboxContainer:
|
|
|
719
720
|
@staticmethod
|
|
720
721
|
def _from_container_info(
|
|
721
722
|
sandbox: _Sandbox, container_info: modal_proto.task_command_router_pb2.TaskContainerInfo
|
|
722
|
-
) ->
|
|
723
|
+
) -> _SidecarContainer: ...
|
|
723
724
|
async def _get_command_router(self) -> tuple[str, modal._utils.task_command_router_client.TaskCommandRouterClient]:
|
|
724
725
|
"""Get task ID and command router client."""
|
|
725
726
|
...
|
|
726
727
|
|
|
728
|
+
@typing.overload
|
|
727
729
|
async def exec(
|
|
728
730
|
self,
|
|
729
731
|
*args: str,
|
|
@@ -733,12 +735,29 @@ class _SandboxContainer:
|
|
|
733
735
|
workdir: typing.Optional[str] = None,
|
|
734
736
|
env: typing.Optional[dict[str, typing.Optional[str]]] = None,
|
|
735
737
|
secrets: typing.Optional[collections.abc.Collection[modal.secret._Secret]] = None,
|
|
736
|
-
text:
|
|
738
|
+
text: typing.Literal[True] = True,
|
|
739
|
+
bufsize: typing.Literal[-1, 1] = -1,
|
|
740
|
+
pty: bool = False,
|
|
741
|
+
) -> modal.container_process._ContainerProcess[str]: ...
|
|
742
|
+
@typing.overload
|
|
743
|
+
async def exec(
|
|
744
|
+
self,
|
|
745
|
+
*args: str,
|
|
746
|
+
stdout: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
|
747
|
+
stderr: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
|
748
|
+
timeout: typing.Optional[int] = None,
|
|
749
|
+
workdir: typing.Optional[str] = None,
|
|
750
|
+
env: typing.Optional[dict[str, typing.Optional[str]]] = None,
|
|
751
|
+
secrets: typing.Optional[collections.abc.Collection[modal.secret._Secret]] = None,
|
|
752
|
+
text: typing.Literal[False],
|
|
737
753
|
bufsize: typing.Literal[-1, 1] = -1,
|
|
738
754
|
pty: bool = False,
|
|
739
|
-
) ->
|
|
740
|
-
|
|
741
|
-
|
|
755
|
+
) -> modal.container_process._ContainerProcess[bytes]: ...
|
|
756
|
+
@property
|
|
757
|
+
def filesystem(self) -> modal.sandbox_fs._SandboxFilesystem:
|
|
758
|
+
"""Namespace for filesystem APIs."""
|
|
759
|
+
...
|
|
760
|
+
|
|
742
761
|
async def wait(self, raise_on_termination: bool = True) -> None: ...
|
|
743
762
|
async def poll(self) -> typing.Optional[int]: ...
|
|
744
763
|
@typing.overload
|
|
@@ -746,8 +765,8 @@ class _SandboxContainer:
|
|
|
746
765
|
@typing.overload
|
|
747
766
|
async def terminate(self, *, wait: typing.Literal[False] = False) -> None: ...
|
|
748
767
|
|
|
749
|
-
class
|
|
750
|
-
"""Creates and manages
|
|
768
|
+
class _SidecarManager:
|
|
769
|
+
"""Creates and manages sidecar containers in a Sandbox."""
|
|
751
770
|
def __init__(self, sandbox: _Sandbox) -> None:
|
|
752
771
|
"""Initialize self. See help(type(self)) for accurate signature."""
|
|
753
772
|
...
|
|
@@ -764,14 +783,15 @@ class _SandboxContainerManager:
|
|
|
764
783
|
env: typing.Optional[dict[str, str]] = None,
|
|
765
784
|
secrets: typing.Optional[collections.abc.Collection[modal.secret._Secret]] = None,
|
|
766
785
|
workdir: typing.Optional[str] = None,
|
|
767
|
-
) ->
|
|
768
|
-
async def get(self, *, name: str, include_terminated: bool = False) ->
|
|
769
|
-
async def list(self, include_terminated: bool = False) -> list[
|
|
786
|
+
) -> _SidecarContainer: ...
|
|
787
|
+
async def get(self, *, name: str, include_terminated: bool = False) -> _SidecarContainer: ...
|
|
788
|
+
async def list(self, include_terminated: bool = False) -> list[_SidecarContainer]: ...
|
|
770
789
|
|
|
771
|
-
class
|
|
790
|
+
class SidecarContainer:
|
|
772
791
|
"""Handle to an additional container running in a Sandbox."""
|
|
773
792
|
|
|
774
793
|
_result: typing.Optional[modal_proto.api_pb2.GenericResult]
|
|
794
|
+
_filesystem: typing.Optional[modal.sandbox_fs.SandboxFilesystem]
|
|
775
795
|
|
|
776
796
|
def __init__(
|
|
777
797
|
self,
|
|
@@ -787,7 +807,7 @@ class SandboxContainer:
|
|
|
787
807
|
@staticmethod
|
|
788
808
|
def _from_container_info(
|
|
789
809
|
sandbox: Sandbox, container_info: modal_proto.task_command_router_pb2.TaskContainerInfo
|
|
790
|
-
) ->
|
|
810
|
+
) -> SidecarContainer: ...
|
|
791
811
|
|
|
792
812
|
class ___get_command_router_spec(typing_extensions.Protocol):
|
|
793
813
|
def __call__(self, /) -> tuple[str, modal._utils.task_command_router_client.TaskCommandRouterClient]:
|
|
@@ -801,6 +821,7 @@ class SandboxContainer:
|
|
|
801
821
|
_get_command_router: ___get_command_router_spec
|
|
802
822
|
|
|
803
823
|
class __exec_spec(typing_extensions.Protocol):
|
|
824
|
+
@typing.overload
|
|
804
825
|
def __call__(
|
|
805
826
|
self,
|
|
806
827
|
/,
|
|
@@ -811,12 +832,26 @@ class SandboxContainer:
|
|
|
811
832
|
workdir: typing.Optional[str] = None,
|
|
812
833
|
env: typing.Optional[dict[str, typing.Optional[str]]] = None,
|
|
813
834
|
secrets: typing.Optional[collections.abc.Collection[modal.secret.Secret]] = None,
|
|
814
|
-
text:
|
|
835
|
+
text: typing.Literal[True] = True,
|
|
815
836
|
bufsize: typing.Literal[-1, 1] = -1,
|
|
816
837
|
pty: bool = False,
|
|
817
|
-
) ->
|
|
818
|
-
|
|
819
|
-
|
|
838
|
+
) -> modal.container_process.ContainerProcess[str]: ...
|
|
839
|
+
@typing.overload
|
|
840
|
+
def __call__(
|
|
841
|
+
self,
|
|
842
|
+
/,
|
|
843
|
+
*args: str,
|
|
844
|
+
stdout: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
|
845
|
+
stderr: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
|
846
|
+
timeout: typing.Optional[int] = None,
|
|
847
|
+
workdir: typing.Optional[str] = None,
|
|
848
|
+
env: typing.Optional[dict[str, typing.Optional[str]]] = None,
|
|
849
|
+
secrets: typing.Optional[collections.abc.Collection[modal.secret.Secret]] = None,
|
|
850
|
+
text: typing.Literal[False],
|
|
851
|
+
bufsize: typing.Literal[-1, 1] = -1,
|
|
852
|
+
pty: bool = False,
|
|
853
|
+
) -> modal.container_process.ContainerProcess[bytes]: ...
|
|
854
|
+
@typing.overload
|
|
820
855
|
async def aio(
|
|
821
856
|
self,
|
|
822
857
|
/,
|
|
@@ -827,15 +862,33 @@ class SandboxContainer:
|
|
|
827
862
|
workdir: typing.Optional[str] = None,
|
|
828
863
|
env: typing.Optional[dict[str, typing.Optional[str]]] = None,
|
|
829
864
|
secrets: typing.Optional[collections.abc.Collection[modal.secret.Secret]] = None,
|
|
830
|
-
text:
|
|
865
|
+
text: typing.Literal[True] = True,
|
|
831
866
|
bufsize: typing.Literal[-1, 1] = -1,
|
|
832
867
|
pty: bool = False,
|
|
833
|
-
) ->
|
|
834
|
-
|
|
835
|
-
|
|
868
|
+
) -> modal.container_process.ContainerProcess[str]: ...
|
|
869
|
+
@typing.overload
|
|
870
|
+
async def aio(
|
|
871
|
+
self,
|
|
872
|
+
/,
|
|
873
|
+
*args: str,
|
|
874
|
+
stdout: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
|
875
|
+
stderr: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
|
876
|
+
timeout: typing.Optional[int] = None,
|
|
877
|
+
workdir: typing.Optional[str] = None,
|
|
878
|
+
env: typing.Optional[dict[str, typing.Optional[str]]] = None,
|
|
879
|
+
secrets: typing.Optional[collections.abc.Collection[modal.secret.Secret]] = None,
|
|
880
|
+
text: typing.Literal[False],
|
|
881
|
+
bufsize: typing.Literal[-1, 1] = -1,
|
|
882
|
+
pty: bool = False,
|
|
883
|
+
) -> modal.container_process.ContainerProcess[bytes]: ...
|
|
836
884
|
|
|
837
885
|
exec: __exec_spec
|
|
838
886
|
|
|
887
|
+
@property
|
|
888
|
+
def filesystem(self) -> modal.sandbox_fs.SandboxFilesystem:
|
|
889
|
+
"""Namespace for filesystem APIs."""
|
|
890
|
+
...
|
|
891
|
+
|
|
839
892
|
class __wait_spec(typing_extensions.Protocol):
|
|
840
893
|
def __call__(self, /, raise_on_termination: bool = True) -> None: ...
|
|
841
894
|
async def aio(self, /, raise_on_termination: bool = True) -> None: ...
|
|
@@ -860,8 +913,8 @@ class SandboxContainer:
|
|
|
860
913
|
|
|
861
914
|
terminate: __terminate_spec
|
|
862
915
|
|
|
863
|
-
class
|
|
864
|
-
"""Creates and manages
|
|
916
|
+
class SidecarManager:
|
|
917
|
+
"""Creates and manages sidecar containers in a Sandbox."""
|
|
865
918
|
def __init__(self, sandbox: Sandbox) -> None: ...
|
|
866
919
|
|
|
867
920
|
class ___get_command_router_spec(typing_extensions.Protocol):
|
|
@@ -885,7 +938,7 @@ class SandboxContainerManager:
|
|
|
885
938
|
env: typing.Optional[dict[str, str]] = None,
|
|
886
939
|
secrets: typing.Optional[collections.abc.Collection[modal.secret.Secret]] = None,
|
|
887
940
|
workdir: typing.Optional[str] = None,
|
|
888
|
-
) ->
|
|
941
|
+
) -> SidecarContainer: ...
|
|
889
942
|
async def aio(
|
|
890
943
|
self,
|
|
891
944
|
/,
|
|
@@ -895,19 +948,19 @@ class SandboxContainerManager:
|
|
|
895
948
|
env: typing.Optional[dict[str, str]] = None,
|
|
896
949
|
secrets: typing.Optional[collections.abc.Collection[modal.secret.Secret]] = None,
|
|
897
950
|
workdir: typing.Optional[str] = None,
|
|
898
|
-
) ->
|
|
951
|
+
) -> SidecarContainer: ...
|
|
899
952
|
|
|
900
953
|
create: __create_spec
|
|
901
954
|
|
|
902
955
|
class __get_spec(typing_extensions.Protocol):
|
|
903
|
-
def __call__(self, /, *, name: str, include_terminated: bool = False) ->
|
|
904
|
-
async def aio(self, /, *, name: str, include_terminated: bool = False) ->
|
|
956
|
+
def __call__(self, /, *, name: str, include_terminated: bool = False) -> SidecarContainer: ...
|
|
957
|
+
async def aio(self, /, *, name: str, include_terminated: bool = False) -> SidecarContainer: ...
|
|
905
958
|
|
|
906
959
|
get: __get_spec
|
|
907
960
|
|
|
908
961
|
class __list_spec(typing_extensions.Protocol):
|
|
909
|
-
def __call__(self, /, include_terminated: bool = False) -> list[
|
|
910
|
-
async def aio(self, /, include_terminated: bool = False) -> list[
|
|
962
|
+
def __call__(self, /, include_terminated: bool = False) -> list[SidecarContainer]: ...
|
|
963
|
+
async def aio(self, /, include_terminated: bool = False) -> list[SidecarContainer]: ...
|
|
911
964
|
|
|
912
965
|
list: __list_spec
|
|
913
966
|
|
|
@@ -1707,8 +1760,8 @@ class Sandbox(modal.object.Object):
|
|
|
1707
1760
|
_get_command_router_client: ___get_command_router_client_spec
|
|
1708
1761
|
|
|
1709
1762
|
@property
|
|
1710
|
-
def
|
|
1711
|
-
"""Manage
|
|
1763
|
+
def _experimental_sidecars(self) -> SidecarManager:
|
|
1764
|
+
"""Manage sidecar containers running in this Sandbox."""
|
|
1712
1765
|
...
|
|
1713
1766
|
|
|
1714
1767
|
class __exec_spec(typing_extensions.Protocol):
|
|
@@ -2060,3 +2113,5 @@ class Sandbox(modal.object.Object):
|
|
|
2060
2113
|
list: typing.ClassVar[__list_spec]
|
|
2061
2114
|
|
|
2062
2115
|
_default_image: modal.image._Image
|
|
2116
|
+
|
|
2117
|
+
_MAIN_CONTAINER_NAME: str
|
modal/sandbox_fs.py
CHANGED
|
@@ -9,7 +9,10 @@ import time
|
|
|
9
9
|
import weakref
|
|
10
10
|
from dataclasses import dataclass
|
|
11
11
|
from pathlib import Path
|
|
12
|
-
from typing import Union, cast
|
|
12
|
+
from typing import TYPE_CHECKING, Union, cast
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
import modal.sandbox
|
|
13
16
|
|
|
14
17
|
from ._utils.async_utils import synchronize_api
|
|
15
18
|
from ._utils.logger import logger
|
|
@@ -84,14 +87,14 @@ class _SandboxFilesystem:
|
|
|
84
87
|
"""mdmd:namespace
|
|
85
88
|
Namespace for Sandbox filesystem APIs."""
|
|
86
89
|
|
|
87
|
-
|
|
90
|
+
_container: Union["modal.sandbox._Sandbox", "modal.sandbox._SidecarContainer"]
|
|
91
|
+
|
|
92
|
+
def __init__(self, container: Union["modal.sandbox._Sandbox", "modal.sandbox._SidecarContainer"]) -> None:
|
|
88
93
|
"""mdmd:hidden"""
|
|
89
|
-
from modal.sandbox import _Sandbox
|
|
94
|
+
from modal.sandbox import _Sandbox, _SidecarContainer
|
|
90
95
|
|
|
91
|
-
#
|
|
92
|
-
|
|
93
|
-
# Use a weakref proxy to avoid circular references between Sandbox and SandboxFilesystem.
|
|
94
|
-
self._sandbox = cast(_Sandbox, weakref.proxy(sandbox))
|
|
96
|
+
# Use a weakref proxy to avoid circular references between Sandbox/SidecarContainer and SandboxFilesystem.
|
|
97
|
+
self._container = cast(Union[_Sandbox, _SidecarContainer], weakref.proxy(container))
|
|
95
98
|
|
|
96
99
|
async def copy_from_local(self, local_path: Union[str, os.PathLike], remote_path: str) -> None:
|
|
97
100
|
"""Copy a local file into the Sandbox.
|
|
@@ -127,7 +130,7 @@ class _SandboxFilesystem:
|
|
|
127
130
|
total_bytes = 0
|
|
128
131
|
with open(local_path, "rb") as file_obj:
|
|
129
132
|
with translate_exec_errors("copy_from_local", remote_path):
|
|
130
|
-
process = await self.
|
|
133
|
+
process = await self._container.exec(_SANDBOX_FS_TOOLS_PATH, make_write_file_command(remote_path))
|
|
131
134
|
try:
|
|
132
135
|
while True:
|
|
133
136
|
# TODO(saltzm): If this fails, the ContainerProcess will remain alive indefinitely since
|
|
@@ -190,7 +193,7 @@ class _SandboxFilesystem:
|
|
|
190
193
|
t0 = time.monotonic()
|
|
191
194
|
try:
|
|
192
195
|
with translate_exec_errors("copy_to_local", remote_path):
|
|
193
|
-
process = await self.
|
|
196
|
+
process = await self._container.exec(
|
|
194
197
|
_SANDBOX_FS_TOOLS_PATH, make_read_file_command(remote_path), text=False
|
|
195
198
|
)
|
|
196
199
|
|
|
@@ -243,7 +246,7 @@ class _SandboxFilesystem:
|
|
|
243
246
|
|
|
244
247
|
t0 = time.monotonic()
|
|
245
248
|
with translate_exec_errors("list_files", remote_path):
|
|
246
|
-
process = await self.
|
|
249
|
+
process = await self._container.exec(_SANDBOX_FS_TOOLS_PATH, make_list_files_command(remote_path))
|
|
247
250
|
stdout, stderr, returncode = await asyncio.gather(
|
|
248
251
|
process.stdout.read(), process.stderr.read(), process.wait()
|
|
249
252
|
)
|
|
@@ -299,7 +302,7 @@ class _SandboxFilesystem:
|
|
|
299
302
|
validate_absolute_remote_path(remote_path, "make_directory")
|
|
300
303
|
|
|
301
304
|
with translate_exec_errors("make_directory", remote_path):
|
|
302
|
-
process = await self.
|
|
305
|
+
process = await self._container.exec(
|
|
303
306
|
_SANDBOX_FS_TOOLS_PATH, make_make_directory_command(remote_path, create_parents)
|
|
304
307
|
)
|
|
305
308
|
stderr, returncode = await asyncio.gather(process.stderr.read(), process.wait())
|
|
@@ -331,7 +334,9 @@ class _SandboxFilesystem:
|
|
|
331
334
|
|
|
332
335
|
t0 = time.monotonic()
|
|
333
336
|
with translate_exec_errors("read_bytes", remote_path):
|
|
334
|
-
process = await self.
|
|
337
|
+
process = await self._container.exec(
|
|
338
|
+
_SANDBOX_FS_TOOLS_PATH, make_read_file_command(remote_path), text=False
|
|
339
|
+
)
|
|
335
340
|
stdout, stderr, returncode = await asyncio.gather(
|
|
336
341
|
process.stdout.read(), process.stderr.read(), process.wait()
|
|
337
342
|
)
|
|
@@ -367,7 +372,7 @@ class _SandboxFilesystem:
|
|
|
367
372
|
|
|
368
373
|
t0 = time.monotonic()
|
|
369
374
|
with translate_exec_errors("read_text", remote_path):
|
|
370
|
-
process = await self.
|
|
375
|
+
process = await self._container.exec(_SANDBOX_FS_TOOLS_PATH, make_read_file_command(remote_path))
|
|
371
376
|
stdout, stderr, returncode = await asyncio.gather(
|
|
372
377
|
process.stdout.read(), process.stderr.read(), process.wait()
|
|
373
378
|
)
|
|
@@ -421,7 +426,7 @@ class _SandboxFilesystem:
|
|
|
421
426
|
validate_absolute_remote_path(remote_path, "remove")
|
|
422
427
|
|
|
423
428
|
with translate_exec_errors("remove", remote_path):
|
|
424
|
-
process = await self.
|
|
429
|
+
process = await self._container.exec(_SANDBOX_FS_TOOLS_PATH, make_remove_command(remote_path, recursive))
|
|
425
430
|
stderr, returncode = await asyncio.gather(process.stderr.read(), process.wait())
|
|
426
431
|
|
|
427
432
|
if returncode != 0:
|
|
@@ -452,7 +457,7 @@ class _SandboxFilesystem:
|
|
|
452
457
|
|
|
453
458
|
t0 = time.monotonic()
|
|
454
459
|
with translate_exec_errors("stat", remote_path):
|
|
455
|
-
process = await self.
|
|
460
|
+
process = await self._container.exec(_SANDBOX_FS_TOOLS_PATH, make_stat_command(remote_path))
|
|
456
461
|
stdout, stderr, returncode = await asyncio.gather(
|
|
457
462
|
process.stdout.read(), process.stderr.read(), process.wait()
|
|
458
463
|
)
|
|
@@ -504,7 +509,7 @@ class _SandboxFilesystem:
|
|
|
504
509
|
|
|
505
510
|
t0 = time.monotonic()
|
|
506
511
|
with translate_exec_errors("write_bytes", remote_path):
|
|
507
|
-
process = await self.
|
|
512
|
+
process = await self._container.exec(_SANDBOX_FS_TOOLS_PATH, make_write_file_command(remote_path))
|
|
508
513
|
try:
|
|
509
514
|
for offset in range(0, max(len(data), 1), TASK_COMMAND_ROUTER_MAX_BUFFER_SIZE):
|
|
510
515
|
process.stdin.write(data[offset : offset + TASK_COMMAND_ROUTER_MAX_BUFFER_SIZE])
|
modal/sandbox_fs.pyi
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import enum
|
|
2
|
+
import modal.sandbox
|
|
2
3
|
import os
|
|
3
4
|
import typing
|
|
4
5
|
import typing_extensions
|
|
@@ -78,7 +79,10 @@ class _SandboxFilesystem:
|
|
|
78
79
|
"""mdmd:namespace
|
|
79
80
|
Namespace for Sandbox filesystem APIs.
|
|
80
81
|
"""
|
|
81
|
-
|
|
82
|
+
|
|
83
|
+
_container: typing.Union[modal.sandbox._Sandbox, modal.sandbox._SidecarContainer]
|
|
84
|
+
|
|
85
|
+
def __init__(self, container: typing.Union[modal.sandbox._Sandbox, modal.sandbox._SidecarContainer]) -> None:
|
|
82
86
|
"""mdmd:hidden"""
|
|
83
87
|
...
|
|
84
88
|
|
|
@@ -341,7 +345,10 @@ class SandboxFilesystem:
|
|
|
341
345
|
"""mdmd:namespace
|
|
342
346
|
Namespace for Sandbox filesystem APIs.
|
|
343
347
|
"""
|
|
344
|
-
|
|
348
|
+
|
|
349
|
+
_container: typing.Union[modal.sandbox.Sandbox, modal.sandbox.SidecarContainer]
|
|
350
|
+
|
|
351
|
+
def __init__(self, container: typing.Union[modal.sandbox.Sandbox, modal.sandbox.SidecarContainer]) -> None:
|
|
345
352
|
"""mdmd:hidden"""
|
|
346
353
|
...
|
|
347
354
|
|
|
@@ -28,7 +28,7 @@ modal/app.pyi,sha256=KgYfkXXrwF31zvS0U-O3gpLCyPf-aenwOg_g97eMSoA,54010
|
|
|
28
28
|
modal/billing.py,sha256=B2zXa7KeMnpqi2AQINycEk-KSXVYaLTTTAQTtuf2Gfs,257
|
|
29
29
|
modal/call_graph.py,sha256=1g2DGcMIJvRy-xKicuf63IVE98gJSnQsr8R_NVMptNc,2581
|
|
30
30
|
modal/client.py,sha256=jjT4eLFHGcvIF6Xw4kPptIx-VmExtphRN8XJ1JA7fWI,15502
|
|
31
|
-
modal/client.pyi,sha256=
|
|
31
|
+
modal/client.pyi,sha256=WUA0I1OfCbHYE9Au3nuKfYoNfTEvM58qCcnSXowZsPg,15701
|
|
32
32
|
modal/cloud_bucket_mount.py,sha256=KkaJVy5vpO_u2NtDYtv1JM-M3y4J0UtWBapTDKpQRcA,6034
|
|
33
33
|
modal/cloud_bucket_mount.pyi,sha256=mGDeEd1XvxGpCE6O5jRBSfIvMXvZ5AtIybea5k-0w9w,7560
|
|
34
34
|
modal/cls.py,sha256=UTtp9W3SuFIbkYEE2D94SUzKiMXM5BYgfHGzBQD6CEk,38304
|
|
@@ -48,8 +48,8 @@ modal/functions.py,sha256=EZRcHFfnoYbvawUJnAHF5nIvoo9GX2Djy7mUmOCXmXc,258
|
|
|
48
48
|
modal/functions.pyi,sha256=oQbuXhpMhPmOvDK5YvDaC19iGqa_gbtPG8yTe8MOhz4,37940
|
|
49
49
|
modal/image.py,sha256=1iHT8KmdWtvIfusupTf_AJGBMUI4PQuAciBp-f_uYL0,113221
|
|
50
50
|
modal/image.pyi,sha256=FUAY23rnaUmpRBVazrzh3Z3b9tYTMikbyk2SbuIpihI,81004
|
|
51
|
-
modal/io_streams.py,sha256=
|
|
52
|
-
modal/io_streams.pyi,sha256=
|
|
51
|
+
modal/io_streams.py,sha256=_rxW4ZfypqTKCCZkfONOsKxO6PY-e95iqR6r08moKiw,25005
|
|
52
|
+
modal/io_streams.pyi,sha256=LerhD5XhMqSWXbPDrUhrX7YSko9DzhvPSlEzyOtaX5s,19274
|
|
53
53
|
modal/mount.py,sha256=rJq9925KwmSYaojWOnG4XD1vpSjSKBclpx-75C58rBU,34746
|
|
54
54
|
modal/mount.pyi,sha256=HVNPL8po23Hulaj7Kdl5goakZbirN0ADv2nkLc8Hpn4,15748
|
|
55
55
|
modal/network_file_system.py,sha256=uyBdVuCLARJrxmD-EsQfzv5gmQxFUXnp65qesPKULvs,13331
|
|
@@ -70,10 +70,10 @@ modal/retries.py,sha256=vPWWKP-FRolJwTBuLPXdWqHV7aJfSQFgEW7vhlBBXRQ,5067
|
|
|
70
70
|
modal/runner.py,sha256=GLx_JwZ2hpA5yuHMY2b2Gt8Ri-KxJZHF2Zp1N_qVLD4,30144
|
|
71
71
|
modal/runner.pyi,sha256=7QHbZawq1P5N9DiSrrEYtXtBCDAWlRibNonBO0q6MdM,9570
|
|
72
72
|
modal/running_app.py,sha256=v61mapYNV1-O-Uaho5EfJlryMLvIT9We0amUOSvSGx8,1188
|
|
73
|
-
modal/sandbox.py,sha256=
|
|
74
|
-
modal/sandbox.pyi,sha256=
|
|
75
|
-
modal/sandbox_fs.py,sha256=
|
|
76
|
-
modal/sandbox_fs.pyi,sha256=
|
|
73
|
+
modal/sandbox.py,sha256=eKNQJ6iRnsGnJHgnNA785H9a8-05qS4R648r4eAuz88,89397
|
|
74
|
+
modal/sandbox.pyi,sha256=vXEcf0TVoS-5NfQMVxxdJf_psCAKY4ZtDNP_TH0UcX8,91119
|
|
75
|
+
modal/sandbox_fs.py,sha256=RmkXSRI27PA-xoUeYgg31oDsIIRctUIVwzjjM76mvIY,22677
|
|
76
|
+
modal/sandbox_fs.pyi,sha256=ATdPtiJTCU-qaS8X59zJQc36fOL6-m14599E1UL8Zz0,35391
|
|
77
77
|
modal/schedule.py,sha256=ng0g0AqNY5GQI9KhkXZQ5Wam5G42glbkqVQsNpBtbDE,3078
|
|
78
78
|
modal/scheduler_placement.py,sha256=BAREdOY5HzHpzSBqt6jDVR6YC_jYfHMVqOzkyqQfngU,1235
|
|
79
79
|
modal/secret.py,sha256=iQKigzV6tI8K7IlsVF4yF4A376fyovN11v_8ej2wsHc,18649
|
|
@@ -95,7 +95,7 @@ modal/_output/pty.py,sha256=wniYe_MW9_pEhCjDgRyrruYJNNtZoAJ0MuOOl3UrGI0,10174
|
|
|
95
95
|
modal/_output/rich.py,sha256=5x4NJlH0gtnVC4HvCp63P7wKcubS53WyRRSZM6QDlrg,31818
|
|
96
96
|
modal/_output/status.py,sha256=WrYh60v6pUQ-Z2SM_lIpYtK4CFyA40kvYrkTBQuZUp8,4524
|
|
97
97
|
modal/_runtime/__init__.py,sha256=MIEP8jhXUeGq_eCjYFcqN5b1bxBM4fdk0VESpjWR0fc,28
|
|
98
|
-
modal/_runtime/asgi.py,sha256=
|
|
98
|
+
modal/_runtime/asgi.py,sha256=qaw2A6NykgTIGp7BUysXlIU-v_cI1ByqbR8A76kNBIQ,22818
|
|
99
99
|
modal/_runtime/container_io_manager.py,sha256=KoIe2z0F4LLOH6LO45-SUxrn2neDKhILs3HUmd_XWwQ,51901
|
|
100
100
|
modal/_runtime/container_io_manager.pyi,sha256=7dSzbTp7lnO4q0sBoOHuC76nnofLowehkq8n1jb1yos,22082
|
|
101
101
|
modal/_runtime/execution_context.py,sha256=vanzJeaTpknTB2-DJQIpPjCJGTfn8gqiQlqGOfkxn2g,3665
|
|
@@ -167,7 +167,7 @@ modal/cli/queues.py,sha256=Nz_gkmlz8c2DqbL3GZnIcdmaHjC8Sj5wl55qq17kty4,6565
|
|
|
167
167
|
modal/cli/run.py,sha256=aTfa5P44_W2LbUVdjYND4kvr8-G1qLHCSYUNilHkLwA,22656
|
|
168
168
|
modal/cli/secret.py,sha256=_YEeQ0HSRXXZgf7Bx990D4B7kzRamNDLlEd92uqK6O4,8252
|
|
169
169
|
modal/cli/selector.py,sha256=OJr9Ua3K_l-qu3N3-I8z8oVq8lBakws2-XgfheR5p-c,4741
|
|
170
|
-
modal/cli/shell.py,sha256=
|
|
170
|
+
modal/cli/shell.py,sha256=qS941iX1XPQuM7-Lsj7SlF8dGw-9ZFRu70Gljbb_i0o,16343
|
|
171
171
|
modal/cli/token.py,sha256=Km7V7pHXsNKyjOCEdioQT8-o04Rh2-PzmNpiL1_i8tw,4352
|
|
172
172
|
modal/cli/utils.py,sha256=CUNFXLcV8EJymZCTXettHDJTDBJi73uHMywayr0ytow,6305
|
|
173
173
|
modal/cli/volume.py,sha256=pP1yqWCwzy1IP-_BbUKZKysdx7sMI5RT5jZUkj1DPsc,11514
|
|
@@ -178,7 +178,7 @@ modal/experimental/__init__.py,sha256=Wb1YoAKAnNxH_0c2wA0T12I7bSu9PSO2nS_LuLska7
|
|
|
178
178
|
modal/experimental/flash.py,sha256=3k7Co0JrrVMjUQxTmi1VPXJX4jgRWetlAJnwm_kxhqg,34301
|
|
179
179
|
modal/experimental/flash.pyi,sha256=lpTqJFZRMGWscw0xpYZVdBMnAYjj16asXE4_64A6itQ,17774
|
|
180
180
|
modal/experimental/ipython.py,sha256=TrCfmol9LGsRZMeDoeMPx3Hv3BFqQhYnmD_iH0pqdhk,2904
|
|
181
|
-
modal-1.4.4.
|
|
181
|
+
modal-1.4.4.dev8.dist-info/licenses/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
|
|
182
182
|
modal_docs/__init__.py,sha256=svYKtV8HDwDCN86zbdWqyq5T8sMdGDj0PVlzc2tIxDM,28
|
|
183
183
|
modal_docs/gen_cli_docs.py,sha256=bfUSLscHfoQoKkKjIqJvQMe3fURzqcQK7gF1h9WQLtM,3742
|
|
184
184
|
modal_docs/gen_cli_docs_main.py,sha256=UPGr7O1DYTIRLwfINe2rbdh89J3cPVTU1OWL-SjxnOQ,198
|
|
@@ -200,10 +200,10 @@ modal_proto/task_command_router_pb2.py,sha256=-K4H-C7N-ILpdvFyM4PQMZcGZvXV1J89mf
|
|
|
200
200
|
modal_proto/task_command_router_pb2.pyi,sha256=KNM7lPtngiv0_Ni_1zRg1rl65ynyjN8vpzd3XISxMGo,37281
|
|
201
201
|
modal_proto/task_command_router_pb2_grpc.py,sha256=368j8b_h19L7bidFTRGSdSG4bK0zU9Y_Oq46_B2ACDg,34666
|
|
202
202
|
modal_proto/task_command_router_pb2_grpc.pyi,sha256=PbzkCj-uSlN1inYSdhncPQ1-04vhBnj3Wzvb-D2pLHY,11226
|
|
203
|
-
modal_version/__init__.py,sha256
|
|
203
|
+
modal_version/__init__.py,sha256=-QYB0OB3-MFO-bxkFMDgdqFdDY6mByoO9cgSi26Y1HU,120
|
|
204
204
|
modal_version/__main__.py,sha256=nLUbubxKx7GXNzJIkTB7M7_u8080LyLM0IS0rzFkC_c,119
|
|
205
|
-
modal-1.4.4.
|
|
206
|
-
modal-1.4.4.
|
|
207
|
-
modal-1.4.4.
|
|
208
|
-
modal-1.4.4.
|
|
209
|
-
modal-1.4.4.
|
|
205
|
+
modal-1.4.4.dev8.dist-info/METADATA,sha256=0txUaxhuST31P84xhfU-vPLoLhjvX4WKK2V_6vjcgP8,2338
|
|
206
|
+
modal-1.4.4.dev8.dist-info/WHEEL,sha256=1tXe9gY0PYatrMPMDd6jXqjfpz_B-Wqm32CPfRC58XU,91
|
|
207
|
+
modal-1.4.4.dev8.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
|
|
208
|
+
modal-1.4.4.dev8.dist-info/top_level.txt,sha256=4BWzoKYREKUZ5iyPzZpjqx4G8uB5TWxXPDwibLcVa7k,43
|
|
209
|
+
modal-1.4.4.dev8.dist-info/RECORD,,
|
modal_version/__init__.py
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|