modal 0.67.14__py3-none-any.whl → 0.67.19__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/_utils/async_utils.py +6 -3
- modal/_utils/blob_utils.py +18 -4
- modal/client.pyi +2 -2
- modal/sandbox.py +6 -0
- modal/sandbox.pyi +6 -0
- {modal-0.67.14.dist-info → modal-0.67.19.dist-info}/METADATA +1 -1
- {modal-0.67.14.dist-info → modal-0.67.19.dist-info}/RECORD +19 -19
- modal_proto/api.proto +13 -0
- modal_proto/api_grpc.py +16 -0
- modal_proto/api_pb2.py +241 -221
- modal_proto/api_pb2.pyi +41 -0
- modal_proto/api_pb2_grpc.py +33 -0
- modal_proto/api_pb2_grpc.pyi +10 -0
- modal_proto/modal_api_grpc.py +1 -0
- modal_version/_version_generated.py +1 -1
- {modal-0.67.14.dist-info → modal-0.67.19.dist-info}/LICENSE +0 -0
- {modal-0.67.14.dist-info → modal-0.67.19.dist-info}/WHEEL +0 -0
- {modal-0.67.14.dist-info → modal-0.67.19.dist-info}/entry_points.txt +0 -0
- {modal-0.67.14.dist-info → modal-0.67.19.dist-info}/top_level.txt +0 -0
modal/_utils/async_utils.py
CHANGED
@@ -6,7 +6,7 @@ import inspect
|
|
6
6
|
import itertools
|
7
7
|
import time
|
8
8
|
import typing
|
9
|
-
from collections.abc import AsyncGenerator, Awaitable, Iterable, Iterator
|
9
|
+
from collections.abc import AsyncGenerator, AsyncIterable, Awaitable, Iterable, Iterator
|
10
10
|
from contextlib import asynccontextmanager
|
11
11
|
from dataclasses import dataclass
|
12
12
|
from typing import (
|
@@ -484,14 +484,17 @@ class aclosing(typing.Generic[T]): # noqa
|
|
484
484
|
await self.agen.aclose()
|
485
485
|
|
486
486
|
|
487
|
-
async def sync_or_async_iter(iter: Union[Iterable[T],
|
487
|
+
async def sync_or_async_iter(iter: Union[Iterable[T], AsyncIterable[T]]) -> AsyncGenerator[T, None]:
|
488
488
|
if hasattr(iter, "__aiter__"):
|
489
489
|
agen = typing.cast(AsyncGenerator[T, None], iter)
|
490
490
|
try:
|
491
491
|
async for item in agen:
|
492
492
|
yield item
|
493
493
|
finally:
|
494
|
-
|
494
|
+
if hasattr(agen, "aclose"):
|
495
|
+
# All AsyncGenerator's have an aclose method
|
496
|
+
# but some AsyncIterable's don't necessarily
|
497
|
+
await agen.aclose()
|
495
498
|
else:
|
496
499
|
assert hasattr(iter, "__iter__"), "sync_or_async_iter requires an Iterable or AsyncGenerator"
|
497
500
|
# This intentionally could block the event loop for the duration of calling __iter__ and __next__,
|
modal/_utils/blob_utils.py
CHANGED
@@ -5,6 +5,7 @@ import hashlib
|
|
5
5
|
import io
|
6
6
|
import os
|
7
7
|
import platform
|
8
|
+
import time
|
8
9
|
from collections.abc import AsyncIterator
|
9
10
|
from contextlib import AbstractContextManager, contextmanager
|
10
11
|
from pathlib import Path, PurePosixPath
|
@@ -289,11 +290,18 @@ async def _blob_upload(
|
|
289
290
|
|
290
291
|
|
291
292
|
async def blob_upload(payload: bytes, stub: ModalClientModal) -> str:
|
293
|
+
size_mib = len(payload) / 1024 / 1024
|
294
|
+
logger.debug(f"Uploading large blob of size {size_mib:.2f} MiB")
|
295
|
+
t0 = time.time()
|
292
296
|
if isinstance(payload, str):
|
293
297
|
logger.warning("Blob uploading string, not bytes - auto-encoding as utf8")
|
294
298
|
payload = payload.encode("utf8")
|
295
299
|
upload_hashes = get_upload_hashes(payload)
|
296
|
-
|
300
|
+
blob_id = await _blob_upload(upload_hashes, payload, stub)
|
301
|
+
dur_s = max(time.time() - t0, 0.001) # avoid division by zero
|
302
|
+
throughput_mib_s = (size_mib) / dur_s
|
303
|
+
logger.debug(f"Uploaded large blob of size {size_mib:.2f} MiB ({throughput_mib_s:.2f} MiB/s)." f" {blob_id}")
|
304
|
+
return blob_id
|
297
305
|
|
298
306
|
|
299
307
|
async def blob_upload_file(
|
@@ -318,11 +326,17 @@ async def _download_from_url(download_url: str) -> bytes:
|
|
318
326
|
|
319
327
|
|
320
328
|
async def blob_download(blob_id: str, stub: ModalClientModal) -> bytes:
|
321
|
-
|
329
|
+
"""Convenience function for reading all of the downloaded file into memory."""
|
330
|
+
logger.debug(f"Downloading large blob {blob_id}")
|
331
|
+
t0 = time.time()
|
322
332
|
req = api_pb2.BlobGetRequest(blob_id=blob_id)
|
323
333
|
resp = await retry_transient_errors(stub.BlobGet, req)
|
324
|
-
|
325
|
-
|
334
|
+
data = await _download_from_url(resp.download_url)
|
335
|
+
size_mib = len(data) / 1024 / 1024
|
336
|
+
dur_s = max(time.time() - t0, 0.001) # avoid division by zero
|
337
|
+
throughput_mib_s = size_mib / dur_s
|
338
|
+
logger.debug(f"Downloaded large blob {blob_id} of size {size_mib:.2f} MiB ({throughput_mib_s:.2f} MiB/s)")
|
339
|
+
return data
|
326
340
|
|
327
341
|
|
328
342
|
async def blob_iter(blob_id: str, stub: ModalClientModal) -> AsyncIterator[bytes]:
|
modal/client.pyi
CHANGED
@@ -26,7 +26,7 @@ class _Client:
|
|
26
26
|
_stub: typing.Optional[modal_proto.api_grpc.ModalClientStub]
|
27
27
|
|
28
28
|
def __init__(
|
29
|
-
self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.67.
|
29
|
+
self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.67.19"
|
30
30
|
): ...
|
31
31
|
def is_closed(self) -> bool: ...
|
32
32
|
@property
|
@@ -81,7 +81,7 @@ class Client:
|
|
81
81
|
_stub: typing.Optional[modal_proto.api_grpc.ModalClientStub]
|
82
82
|
|
83
83
|
def __init__(
|
84
|
-
self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.67.
|
84
|
+
self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.67.19"
|
85
85
|
): ...
|
86
86
|
def is_closed(self) -> bool: ...
|
87
87
|
@property
|
modal/sandbox.py
CHANGED
@@ -28,6 +28,7 @@ from .io_streams import StreamReader, StreamWriter, _StreamReader, _StreamWriter
|
|
28
28
|
from .mount import _Mount
|
29
29
|
from .network_file_system import _NetworkFileSystem, network_file_system_mount_protos
|
30
30
|
from .object import _get_environment_name, _Object
|
31
|
+
from .proxy import _Proxy
|
31
32
|
from .scheduler_placement import SchedulerPlacement
|
32
33
|
from .secret import _Secret
|
33
34
|
from .stream_type import StreamType
|
@@ -73,6 +74,7 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
73
74
|
pty_info: Optional[api_pb2.PTYInfo] = None,
|
74
75
|
encrypted_ports: Sequence[int] = [],
|
75
76
|
unencrypted_ports: Sequence[int] = [],
|
77
|
+
proxy: Optional[_Proxy] = None,
|
76
78
|
_experimental_scheduler_placement: Optional[SchedulerPlacement] = None,
|
77
79
|
) -> "_Sandbox":
|
78
80
|
"""mdmd:hidden"""
|
@@ -166,6 +168,7 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
166
168
|
worker_id=config.get("worker_id"),
|
167
169
|
open_ports=api_pb2.PortSpecs(ports=open_ports),
|
168
170
|
network_access=network_access,
|
171
|
+
proxy_id=(proxy.object_id if proxy else None),
|
169
172
|
)
|
170
173
|
|
171
174
|
# Note - `resolver.app_id` will be `None` for app-less sandboxes
|
@@ -208,6 +211,8 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
208
211
|
encrypted_ports: Sequence[int] = [],
|
209
212
|
# List of ports to tunnel into the sandbox without encryption.
|
210
213
|
unencrypted_ports: Sequence[int] = [],
|
214
|
+
# Reference to a Modal Proxy to use in front of this Sandbox.
|
215
|
+
proxy: Optional[_Proxy] = None,
|
211
216
|
_experimental_scheduler_placement: Optional[
|
212
217
|
SchedulerPlacement
|
213
218
|
] = None, # Experimental controls over fine-grained scheduling (alpha).
|
@@ -243,6 +248,7 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
243
248
|
pty_info=pty_info,
|
244
249
|
encrypted_ports=encrypted_ports,
|
245
250
|
unencrypted_ports=unencrypted_ports,
|
251
|
+
proxy=proxy,
|
246
252
|
_experimental_scheduler_placement=_experimental_scheduler_placement,
|
247
253
|
)
|
248
254
|
|
modal/sandbox.pyi
CHANGED
@@ -11,6 +11,7 @@ import modal.io_streams
|
|
11
11
|
import modal.mount
|
12
12
|
import modal.network_file_system
|
13
13
|
import modal.object
|
14
|
+
import modal.proxy
|
14
15
|
import modal.scheduler_placement
|
15
16
|
import modal.secret
|
16
17
|
import modal.stream_type
|
@@ -51,6 +52,7 @@ class _Sandbox(modal.object._Object):
|
|
51
52
|
pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
|
52
53
|
encrypted_ports: collections.abc.Sequence[int] = [],
|
53
54
|
unencrypted_ports: collections.abc.Sequence[int] = [],
|
55
|
+
proxy: typing.Optional[modal.proxy._Proxy] = None,
|
54
56
|
_experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
|
55
57
|
) -> _Sandbox: ...
|
56
58
|
@staticmethod
|
@@ -78,6 +80,7 @@ class _Sandbox(modal.object._Object):
|
|
78
80
|
pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
|
79
81
|
encrypted_ports: collections.abc.Sequence[int] = [],
|
80
82
|
unencrypted_ports: collections.abc.Sequence[int] = [],
|
83
|
+
proxy: typing.Optional[modal.proxy._Proxy] = None,
|
81
84
|
_experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
|
82
85
|
client: typing.Optional[modal.client._Client] = None,
|
83
86
|
) -> _Sandbox: ...
|
@@ -165,6 +168,7 @@ class Sandbox(modal.object.Object):
|
|
165
168
|
pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
|
166
169
|
encrypted_ports: collections.abc.Sequence[int] = [],
|
167
170
|
unencrypted_ports: collections.abc.Sequence[int] = [],
|
171
|
+
proxy: typing.Optional[modal.proxy.Proxy] = None,
|
168
172
|
_experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
|
169
173
|
) -> Sandbox: ...
|
170
174
|
|
@@ -196,6 +200,7 @@ class Sandbox(modal.object.Object):
|
|
196
200
|
pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
|
197
201
|
encrypted_ports: collections.abc.Sequence[int] = [],
|
198
202
|
unencrypted_ports: collections.abc.Sequence[int] = [],
|
203
|
+
proxy: typing.Optional[modal.proxy.Proxy] = None,
|
199
204
|
_experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
|
200
205
|
client: typing.Optional[modal.client.Client] = None,
|
201
206
|
) -> Sandbox: ...
|
@@ -226,6 +231,7 @@ class Sandbox(modal.object.Object):
|
|
226
231
|
pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
|
227
232
|
encrypted_ports: collections.abc.Sequence[int] = [],
|
228
233
|
unencrypted_ports: collections.abc.Sequence[int] = [],
|
234
|
+
proxy: typing.Optional[modal.proxy.Proxy] = None,
|
229
235
|
_experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
|
230
236
|
client: typing.Optional[modal.client.Client] = None,
|
231
237
|
) -> Sandbox: ...
|
@@ -19,7 +19,7 @@ modal/app.py,sha256=EJ7FUN6rWnSwLJoYJh8nmKg_t-8hdN8_rt0OrkP7JvQ,46084
|
|
19
19
|
modal/app.pyi,sha256=BE5SlR5tRECuc6-e2lUuOknDdov3zxgZ4N0AsLb5ZVQ,25270
|
20
20
|
modal/call_graph.py,sha256=1g2DGcMIJvRy-xKicuf63IVE98gJSnQsr8R_NVMptNc,2581
|
21
21
|
modal/client.py,sha256=VMg_aIuo_LOEe2ttxBHEND3PLhTp5lo-onH4wELhIyY,16375
|
22
|
-
modal/client.pyi,sha256=
|
22
|
+
modal/client.pyi,sha256=thOQnTpBj0M-83tyx4cAzEtK1hyiaunf2CNsegg9DjM,7354
|
23
23
|
modal/cloud_bucket_mount.py,sha256=G7T7jWLD0QkmrfKR75mSTwdUZ2xNfj7pkVqb4ipmxmI,5735
|
24
24
|
modal/cloud_bucket_mount.pyi,sha256=CEi7vrH3kDUF4LAy4qP6tfImy2UJuFRcRbsgRNM1wo8,1403
|
25
25
|
modal/cls.py,sha256=F2jk5zFCAA8h-GfM0dbdBG3Mu5wiG9k9Z9JLYRYuT2Q,24758
|
@@ -60,8 +60,8 @@ modal/retries.py,sha256=HKR2Q9aNPWkMjQ5nwobqYTuZaSuw0a8lI2zrtY5IW98,5230
|
|
60
60
|
modal/runner.py,sha256=7obU-Gq1ocpBGCuR6pvn1T-D6ggg1T48qFo2TNUGWkU,24089
|
61
61
|
modal/runner.pyi,sha256=RAtCvx_lXWjyFjIaZ3t9-X1c7rqpgAQlhl4Hww53OY8,5038
|
62
62
|
modal/running_app.py,sha256=CshNvGDJtagOdKW54uYjY8HY73j2TpnsL9jkPFZAsfA,560
|
63
|
-
modal/sandbox.py,sha256=
|
64
|
-
modal/sandbox.pyi,sha256=
|
63
|
+
modal/sandbox.py,sha256=25DvTWSgClANvk67HM3FHukRVLig_Fw_aQC1BLMCRhs,25150
|
64
|
+
modal/sandbox.pyi,sha256=JRh6Q-WdY6GgVSOGm0L_pgo5bfsi2UacsZezpT0-cDU,17685
|
65
65
|
modal/schedule.py,sha256=0ZFpKs1bOxeo5n3HZjoL7OE2ktsb-_oGtq-WJEPO4tY,2615
|
66
66
|
modal/scheduler_placement.py,sha256=BAREdOY5HzHpzSBqt6jDVR6YC_jYfHMVqOzkyqQfngU,1235
|
67
67
|
modal/secret.py,sha256=Y1WgybQIkfkxdzH9CQ1h-Wd1DJJpzipigMhyyvSxTww,10007
|
@@ -81,8 +81,8 @@ modal/_runtime/telemetry.py,sha256=T1RoAGyjBDr1swiM6pPsGRSITm7LI5FDK18oNXxY08U,5
|
|
81
81
|
modal/_runtime/user_code_imports.py,sha256=q_3JOYqCPDcVFZWCHEjyEqj8yzdFsQ49HzeqYmFDLbk,14521
|
82
82
|
modal/_utils/__init__.py,sha256=waLjl5c6IPDhSsdWAm9Bji4e2PVxamYABKAze6CHVXY,28
|
83
83
|
modal/_utils/app_utils.py,sha256=88BT4TPLWfYAQwKTHcyzNQRHg8n9B-QE2UyJs96iV-0,108
|
84
|
-
modal/_utils/async_utils.py,sha256=
|
85
|
-
modal/_utils/blob_utils.py,sha256=
|
84
|
+
modal/_utils/async_utils.py,sha256=9ubwMkwiDB4gzOYG2jL9j7Fs-5dxHjcifZe3r7JRg-k,25091
|
85
|
+
modal/_utils/blob_utils.py,sha256=0k_qUpO5GHnz538wjRhyRw4NdJ5O322N7QSilIu32jw,16601
|
86
86
|
modal/_utils/function_utils.py,sha256=SkT5emqGJ8NNASk0BlBmgDfDBUYAkUM851K74qCHL98,24641
|
87
87
|
modal/_utils/grpc_testing.py,sha256=iqM9n5M0cWUUIIWNaEDer_pIfPnzXdZBO4L8FVbNepQ,8309
|
88
88
|
modal/_utils/grpc_utils.py,sha256=PPB5ay-vXencXNIWPVw5modr3EH7gfq2QPcO5YJ1lMU,7737
|
@@ -142,13 +142,13 @@ modal_global_objects/mounts/__init__.py,sha256=MIEP8jhXUeGq_eCjYFcqN5b1bxBM4fdk0
|
|
142
142
|
modal_global_objects/mounts/modal_client_package.py,sha256=W0E_yShsRojPzWm6LtIQqNVolapdnrZkm2hVEQuZK_4,767
|
143
143
|
modal_global_objects/mounts/python_standalone.py,sha256=_vTEX3PECUsatzhDs8lyJmDK0LbFetT1sJB6MIDfFAo,1870
|
144
144
|
modal_proto/__init__.py,sha256=MIEP8jhXUeGq_eCjYFcqN5b1bxBM4fdk0VESpjWR0fc,28
|
145
|
-
modal_proto/api.proto,sha256=
|
146
|
-
modal_proto/api_grpc.py,sha256=
|
147
|
-
modal_proto/api_pb2.py,sha256=
|
148
|
-
modal_proto/api_pb2.pyi,sha256=
|
149
|
-
modal_proto/api_pb2_grpc.py,sha256=
|
150
|
-
modal_proto/api_pb2_grpc.pyi,sha256=
|
151
|
-
modal_proto/modal_api_grpc.py,sha256=
|
145
|
+
modal_proto/api.proto,sha256=I36DzPZ4fs045HqQCEdgEiiJr1Dcd6T6fFA1RbQW7aE,78014
|
146
|
+
modal_proto/api_grpc.py,sha256=cQOfwiGd2Nyj9esTgtu39EK1QKGZJXharISgWG7_lQ8,99814
|
147
|
+
modal_proto/api_pb2.py,sha256=rk-8yxgiqsevrf8ZOQl7Elr5xKKz0nYdI46Yd6S0iJI,284335
|
148
|
+
modal_proto/api_pb2.pyi,sha256=FCMnndhn2lqdFo1kr49PjfOQzxacPg2UHM9hGpatdS8,380051
|
149
|
+
modal_proto/api_pb2_grpc.py,sha256=VTrD72cWvA2SscVVpR7w0swwGJ2O6pY-uASamt9Qm7M,215824
|
150
|
+
modal_proto/api_pb2_grpc.pyi,sha256=SbWtkTeCztsSOz8WaM07UZ5fxfKn7nQG4Dxbp5PQUz8,50356
|
151
|
+
modal_proto/modal_api_grpc.py,sha256=AUfZ2n1xOaCv-NzMp5w91fgsQi5zs79IDLH7RGOg1-o,13340
|
152
152
|
modal_proto/modal_options_grpc.py,sha256=qJ1cuwA54oRqrdTyPTbvfhFZYd9HhJKK5UCwt523r3Y,120
|
153
153
|
modal_proto/options.proto,sha256=a-siq4swVbZPfaFRXAipRZzGP2bq8OsdUvjlyzAeodQ,488
|
154
154
|
modal_proto/options_grpc.py,sha256=M18X3d-8F_cNYSVM3I25dUTO5rZ0rd-vCCfynfh13Nc,125
|
@@ -159,10 +159,10 @@ modal_proto/options_pb2_grpc.pyi,sha256=CImmhxHsYnF09iENPoe8S4J-n93jtgUYD2JPAc0y
|
|
159
159
|
modal_proto/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
160
160
|
modal_version/__init__.py,sha256=3IY-AWLH55r35_mQXIaut0jrJvoPuf1NZJBQQfSbPuo,470
|
161
161
|
modal_version/__main__.py,sha256=2FO0yYQQwDTh6udt1h-cBnGd1c4ZyHnHSI4BksxzVac,105
|
162
|
-
modal_version/_version_generated.py,sha256=
|
163
|
-
modal-0.67.
|
164
|
-
modal-0.67.
|
165
|
-
modal-0.67.
|
166
|
-
modal-0.67.
|
167
|
-
modal-0.67.
|
168
|
-
modal-0.67.
|
162
|
+
modal_version/_version_generated.py,sha256=zYKLeeniwCulLrYJ4NLXigHdUUd3VY_DsZP7BG5Ck7A,149
|
163
|
+
modal-0.67.19.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
|
164
|
+
modal-0.67.19.dist-info/METADATA,sha256=AsTc53FDpIG8sHxoyYC0LDTwQGt3ff6rMtMUuVlV3cw,2329
|
165
|
+
modal-0.67.19.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
|
166
|
+
modal-0.67.19.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
|
167
|
+
modal-0.67.19.dist-info/top_level.txt,sha256=1nvYbOSIKcmU50fNrpnQnrrOpj269ei3LzgB6j9xGqg,64
|
168
|
+
modal-0.67.19.dist-info/RECORD,,
|
modal_proto/api.proto
CHANGED
@@ -2146,6 +2146,18 @@ message SandboxListResponse {
|
|
2146
2146
|
repeated SandboxInfo sandboxes = 1;
|
2147
2147
|
}
|
2148
2148
|
|
2149
|
+
message SandboxSnapshotFsRequest {
|
2150
|
+
string sandbox_id = 1;
|
2151
|
+
float timeout = 2;
|
2152
|
+
}
|
2153
|
+
|
2154
|
+
message SandboxSnapshotFsResponse {
|
2155
|
+
string image_id = 1;
|
2156
|
+
GenericResult result = 2;
|
2157
|
+
// Metadata may be empty since we may skip it for performance reasons.
|
2158
|
+
ImageMetadata image_metadata = 3;
|
2159
|
+
}
|
2160
|
+
|
2149
2161
|
message SandboxStdinWriteRequest {
|
2150
2162
|
string sandbox_id = 1;
|
2151
2163
|
bytes input = 2;
|
@@ -2745,6 +2757,7 @@ service ModalClient {
|
|
2745
2757
|
rpc SandboxGetTaskId(SandboxGetTaskIdRequest) returns (SandboxGetTaskIdResponse); // needed for modal container exec
|
2746
2758
|
rpc SandboxGetTunnels(SandboxGetTunnelsRequest) returns (SandboxGetTunnelsResponse);
|
2747
2759
|
rpc SandboxList(SandboxListRequest) returns (SandboxListResponse);
|
2760
|
+
rpc SandboxSnapshotFs(SandboxSnapshotFsRequest) returns (SandboxSnapshotFsResponse);
|
2748
2761
|
rpc SandboxStdinWrite(SandboxStdinWriteRequest) returns (SandboxStdinWriteResponse);
|
2749
2762
|
rpc SandboxTagsSet(SandboxTagsSetRequest) returns (google.protobuf.Empty);
|
2750
2763
|
rpc SandboxTerminate(SandboxTerminateRequest) returns (SandboxTerminateResponse);
|
modal_proto/api_grpc.py
CHANGED
@@ -389,6 +389,10 @@ class ModalClientBase(abc.ABC):
|
|
389
389
|
async def SandboxList(self, stream: 'grpclib.server.Stream[modal_proto.api_pb2.SandboxListRequest, modal_proto.api_pb2.SandboxListResponse]') -> None:
|
390
390
|
pass
|
391
391
|
|
392
|
+
@abc.abstractmethod
|
393
|
+
async def SandboxSnapshotFs(self, stream: 'grpclib.server.Stream[modal_proto.api_pb2.SandboxSnapshotFsRequest, modal_proto.api_pb2.SandboxSnapshotFsResponse]') -> None:
|
394
|
+
pass
|
395
|
+
|
392
396
|
@abc.abstractmethod
|
393
397
|
async def SandboxStdinWrite(self, stream: 'grpclib.server.Stream[modal_proto.api_pb2.SandboxStdinWriteRequest, modal_proto.api_pb2.SandboxStdinWriteResponse]') -> None:
|
394
398
|
pass
|
@@ -1093,6 +1097,12 @@ class ModalClientBase(abc.ABC):
|
|
1093
1097
|
modal_proto.api_pb2.SandboxListRequest,
|
1094
1098
|
modal_proto.api_pb2.SandboxListResponse,
|
1095
1099
|
),
|
1100
|
+
'/modal.client.ModalClient/SandboxSnapshotFs': grpclib.const.Handler(
|
1101
|
+
self.SandboxSnapshotFs,
|
1102
|
+
grpclib.const.Cardinality.UNARY_UNARY,
|
1103
|
+
modal_proto.api_pb2.SandboxSnapshotFsRequest,
|
1104
|
+
modal_proto.api_pb2.SandboxSnapshotFsResponse,
|
1105
|
+
),
|
1096
1106
|
'/modal.client.ModalClient/SandboxStdinWrite': grpclib.const.Handler(
|
1097
1107
|
self.SandboxStdinWrite,
|
1098
1108
|
grpclib.const.Cardinality.UNARY_UNARY,
|
@@ -1873,6 +1883,12 @@ class ModalClientStub:
|
|
1873
1883
|
modal_proto.api_pb2.SandboxListRequest,
|
1874
1884
|
modal_proto.api_pb2.SandboxListResponse,
|
1875
1885
|
)
|
1886
|
+
self.SandboxSnapshotFs = grpclib.client.UnaryUnaryMethod(
|
1887
|
+
channel,
|
1888
|
+
'/modal.client.ModalClient/SandboxSnapshotFs',
|
1889
|
+
modal_proto.api_pb2.SandboxSnapshotFsRequest,
|
1890
|
+
modal_proto.api_pb2.SandboxSnapshotFsResponse,
|
1891
|
+
)
|
1876
1892
|
self.SandboxStdinWrite = grpclib.client.UnaryUnaryMethod(
|
1877
1893
|
channel,
|
1878
1894
|
'/modal.client.ModalClient/SandboxStdinWrite',
|