modal 1.1.5.dev44__py3-none-any.whl → 1.1.5.dev46__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/_container_entrypoint.py +19 -41
- modal/_functions.py +21 -14
- modal/_runtime/container_io_manager.py +252 -150
- modal/_runtime/container_io_manager.pyi +32 -48
- modal/_runtime/user_code_imports.py +15 -5
- modal/_serialization.py +57 -1
- modal/_utils/blob_utils.py +4 -0
- modal/_utils/function_utils.py +22 -8
- modal/app.py +4 -0
- modal/app.pyi +4 -0
- modal/client.pyi +2 -2
- modal/config.py +5 -0
- modal/functions.pyi +1 -0
- modal/image.py +10 -3
- modal/parallel_map.py +2 -4
- {modal-1.1.5.dev44.dist-info → modal-1.1.5.dev46.dist-info}/METADATA +2 -1
- {modal-1.1.5.dev44.dist-info → modal-1.1.5.dev46.dist-info}/RECORD +29 -29
- modal_proto/api.proto +13 -0
- modal_proto/api_grpc.py +16 -0
- modal_proto/api_pb2.py +343 -323
- modal_proto/api_pb2.pyi +36 -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/__init__.py +1 -1
- {modal-1.1.5.dev44.dist-info → modal-1.1.5.dev46.dist-info}/WHEEL +0 -0
- {modal-1.1.5.dev44.dist-info → modal-1.1.5.dev46.dist-info}/entry_points.txt +0 -0
- {modal-1.1.5.dev44.dist-info → modal-1.1.5.dev46.dist-info}/licenses/LICENSE +0 -0
- {modal-1.1.5.dev44.dist-info → modal-1.1.5.dev46.dist-info}/top_level.txt +0 -0
|
@@ -29,7 +29,7 @@ class FinalizedFunction:
|
|
|
29
29
|
callable: Callable[..., Any]
|
|
30
30
|
is_async: bool
|
|
31
31
|
is_generator: bool
|
|
32
|
-
|
|
32
|
+
supported_output_formats: Sequence["api_pb2.DataFormat.ValueType"]
|
|
33
33
|
lifespan_manager: Optional["LifespanManager"] = None
|
|
34
34
|
|
|
35
35
|
|
|
@@ -108,6 +108,7 @@ class ImportedFunction(Service):
|
|
|
108
108
|
is_generator = fun_def.function_type == api_pb2.Function.FUNCTION_TYPE_GENERATOR
|
|
109
109
|
|
|
110
110
|
webhook_config = fun_def.webhook_config
|
|
111
|
+
|
|
111
112
|
if not webhook_config.type:
|
|
112
113
|
# for non-webhooks, the runnable is straight forward:
|
|
113
114
|
return {
|
|
@@ -115,7 +116,10 @@ class ImportedFunction(Service):
|
|
|
115
116
|
callable=self._user_defined_callable,
|
|
116
117
|
is_async=is_async,
|
|
117
118
|
is_generator=is_generator,
|
|
118
|
-
|
|
119
|
+
supported_output_formats=fun_def.supported_output_formats
|
|
120
|
+
# FIXME (elias): the following `or [api_pb2.DATA_FORMAT_PICKLE, api_pb2.DATA_FORMAT_CBOR]` is only
|
|
121
|
+
# needed for tests
|
|
122
|
+
or [api_pb2.DATA_FORMAT_PICKLE, api_pb2.DATA_FORMAT_CBOR],
|
|
119
123
|
)
|
|
120
124
|
}
|
|
121
125
|
|
|
@@ -129,7 +133,8 @@ class ImportedFunction(Service):
|
|
|
129
133
|
lifespan_manager=lifespan_manager,
|
|
130
134
|
is_async=True,
|
|
131
135
|
is_generator=True,
|
|
132
|
-
|
|
136
|
+
# FIXME (elias): the following `or [api_pb2.DATA_FORMAT_ASGI]` is only needed for tests
|
|
137
|
+
supported_output_formats=fun_def.supported_output_formats or [api_pb2.DATA_FORMAT_ASGI],
|
|
133
138
|
)
|
|
134
139
|
}
|
|
135
140
|
|
|
@@ -154,6 +159,7 @@ class ImportedClass(Service):
|
|
|
154
159
|
# Use the function definition for whether this is a generator (overriden by webhooks)
|
|
155
160
|
is_generator = _partial.params.is_generator
|
|
156
161
|
webhook_config = _partial.params.webhook_config
|
|
162
|
+
method_def = fun_def.method_definitions[method_name]
|
|
157
163
|
|
|
158
164
|
bound_func = user_func.__get__(self.user_cls_instance)
|
|
159
165
|
|
|
@@ -163,7 +169,10 @@ class ImportedClass(Service):
|
|
|
163
169
|
callable=bound_func,
|
|
164
170
|
is_async=is_async,
|
|
165
171
|
is_generator=bool(is_generator),
|
|
166
|
-
|
|
172
|
+
# FIXME (elias): the following `or [api_pb2.DATA_FORMAT_PICKLE, api_pb2.DATA_FORMAT_CBOR]` is only
|
|
173
|
+
# needed for tests
|
|
174
|
+
supported_output_formats=method_def.supported_output_formats
|
|
175
|
+
or [api_pb2.DATA_FORMAT_PICKLE, api_pb2.DATA_FORMAT_CBOR],
|
|
167
176
|
)
|
|
168
177
|
else:
|
|
169
178
|
web_callable, lifespan_manager = construct_webhook_callable(
|
|
@@ -174,7 +183,8 @@ class ImportedClass(Service):
|
|
|
174
183
|
lifespan_manager=lifespan_manager,
|
|
175
184
|
is_async=True,
|
|
176
185
|
is_generator=True,
|
|
177
|
-
|
|
186
|
+
# FIXME (elias): the following `or [api_pb2.DATA_FORMAT_ASGI]` is only needed for tests
|
|
187
|
+
supported_output_formats=method_def.supported_output_formats or [api_pb2.DATA_FORMAT_ASGI],
|
|
178
188
|
)
|
|
179
189
|
finalized_functions[method_name] = finalized_function
|
|
180
190
|
return finalized_functions
|
modal/_serialization.py
CHANGED
|
@@ -6,6 +6,14 @@ import typing
|
|
|
6
6
|
from inspect import Parameter
|
|
7
7
|
from typing import Any
|
|
8
8
|
|
|
9
|
+
from modal._traceback import extract_traceback
|
|
10
|
+
from modal.config import config
|
|
11
|
+
|
|
12
|
+
try:
|
|
13
|
+
import cbor2 # type: ignore
|
|
14
|
+
except ImportError: # pragma: no cover - optional dependency
|
|
15
|
+
cbor2 = None
|
|
16
|
+
|
|
9
17
|
import google.protobuf.message
|
|
10
18
|
|
|
11
19
|
from modal._utils.async_utils import synchronizer
|
|
@@ -15,7 +23,7 @@ from ._object import _Object
|
|
|
15
23
|
from ._type_manager import parameter_serde_registry, schema_registry
|
|
16
24
|
from ._vendor import cloudpickle
|
|
17
25
|
from .config import logger
|
|
18
|
-
from .exception import DeserializationError, ExecutionError, InvalidError
|
|
26
|
+
from .exception import DeserializationError, ExecutionError, InvalidError, SerializationError
|
|
19
27
|
from .object import Object
|
|
20
28
|
|
|
21
29
|
if typing.TYPE_CHECKING:
|
|
@@ -346,6 +354,12 @@ def _deserialize_asgi(asgi: api_pb2.Asgi) -> Any:
|
|
|
346
354
|
return None
|
|
347
355
|
|
|
348
356
|
|
|
357
|
+
def get_preferred_payload_format() -> "api_pb2.DataFormat.ValueType":
|
|
358
|
+
payload_format = (config.get("payload_format") or "pickle").lower()
|
|
359
|
+
data_format = api_pb2.DATA_FORMAT_CBOR if payload_format == "cbor" else api_pb2.DATA_FORMAT_PICKLE
|
|
360
|
+
return data_format
|
|
361
|
+
|
|
362
|
+
|
|
349
363
|
def serialize_data_format(obj: Any, data_format: int) -> bytes:
|
|
350
364
|
"""Similar to serialize(), but supports other data formats."""
|
|
351
365
|
if data_format == api_pb2.DATA_FORMAT_PICKLE:
|
|
@@ -355,6 +369,21 @@ def serialize_data_format(obj: Any, data_format: int) -> bytes:
|
|
|
355
369
|
elif data_format == api_pb2.DATA_FORMAT_GENERATOR_DONE:
|
|
356
370
|
assert isinstance(obj, api_pb2.GeneratorDone)
|
|
357
371
|
return obj.SerializeToString(deterministic=True)
|
|
372
|
+
elif data_format == api_pb2.DATA_FORMAT_CBOR:
|
|
373
|
+
if cbor2 is None:
|
|
374
|
+
raise InvalidError("CBOR support requires the 'cbor2' package to be installed.")
|
|
375
|
+
try:
|
|
376
|
+
return cbor2.dumps(obj)
|
|
377
|
+
except cbor2.CBOREncodeTypeError:
|
|
378
|
+
try:
|
|
379
|
+
typename = f"{type(obj).__module__}.{type(obj).__name__}"
|
|
380
|
+
except Exception:
|
|
381
|
+
typename = str(type(obj))
|
|
382
|
+
raise SerializationError(
|
|
383
|
+
# TODO (elias): add documentation link for more information on this
|
|
384
|
+
f"Can not serialize type {typename} as cbor. If you need to use a custom data type, "
|
|
385
|
+
"try to serialize it yourself e.g. by using pickle.dumps(my_data)"
|
|
386
|
+
)
|
|
358
387
|
else:
|
|
359
388
|
raise InvalidError(f"Unknown data format {data_format!r}")
|
|
360
389
|
|
|
@@ -366,6 +395,10 @@ def deserialize_data_format(s: bytes, data_format: int, client) -> Any:
|
|
|
366
395
|
return _deserialize_asgi(api_pb2.Asgi.FromString(s))
|
|
367
396
|
elif data_format == api_pb2.DATA_FORMAT_GENERATOR_DONE:
|
|
368
397
|
return api_pb2.GeneratorDone.FromString(s)
|
|
398
|
+
elif data_format == api_pb2.DATA_FORMAT_CBOR:
|
|
399
|
+
if cbor2 is None:
|
|
400
|
+
raise InvalidError("CBOR support requires the 'cbor2' package to be installed.")
|
|
401
|
+
return cbor2.loads(s)
|
|
369
402
|
else:
|
|
370
403
|
raise InvalidError(f"Unknown data format {data_format!r}")
|
|
371
404
|
|
|
@@ -579,3 +612,26 @@ def get_callable_schema(
|
|
|
579
612
|
arguments=arguments,
|
|
580
613
|
return_type=return_type_proto,
|
|
581
614
|
)
|
|
615
|
+
|
|
616
|
+
|
|
617
|
+
def pickle_exception(exc: BaseException) -> bytes:
|
|
618
|
+
try:
|
|
619
|
+
return serialize(exc)
|
|
620
|
+
except Exception as serialization_exc:
|
|
621
|
+
# We can't always serialize exceptions.
|
|
622
|
+
err = f"Failed to serialize exception {exc} of type {type(exc)}: {serialization_exc}"
|
|
623
|
+
logger.info(err)
|
|
624
|
+
return serialize(SerializationError(err))
|
|
625
|
+
|
|
626
|
+
|
|
627
|
+
def pickle_traceback(exc: BaseException, task_id: str) -> tuple[bytes, bytes]:
|
|
628
|
+
serialized_tb, tb_line_cache = b"", b""
|
|
629
|
+
|
|
630
|
+
try:
|
|
631
|
+
tb_dict, line_cache = extract_traceback(exc, task_id)
|
|
632
|
+
serialized_tb = serialize(tb_dict)
|
|
633
|
+
tb_line_cache = serialize(line_cache)
|
|
634
|
+
except Exception:
|
|
635
|
+
logger.info("Failed to serialize exception traceback.")
|
|
636
|
+
|
|
637
|
+
return serialized_tb, tb_line_cache
|
modal/_utils/blob_utils.py
CHANGED
|
@@ -300,6 +300,10 @@ async def blob_upload(payload: bytes, stub: ModalClientModal) -> str:
|
|
|
300
300
|
return blob_id
|
|
301
301
|
|
|
302
302
|
|
|
303
|
+
async def format_blob_data(data: bytes, api_stub: ModalClientModal) -> dict[str, Any]:
|
|
304
|
+
return {"data_blob_id": await blob_upload(data, api_stub)} if len(data) > MAX_OBJECT_SIZE_BYTES else {"data": data}
|
|
305
|
+
|
|
306
|
+
|
|
303
307
|
async def blob_upload_file(
|
|
304
308
|
file_obj: BinaryIO,
|
|
305
309
|
stub: ModalClientModal,
|
modal/_utils/function_utils.py
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import asyncio
|
|
3
3
|
import inspect
|
|
4
4
|
import os
|
|
5
|
+
import typing
|
|
5
6
|
from collections.abc import AsyncGenerator
|
|
6
7
|
from enum import Enum
|
|
7
8
|
from pathlib import Path, PurePosixPath
|
|
@@ -17,7 +18,9 @@ from modal_proto.modal_api_grpc import ModalClientModal
|
|
|
17
18
|
from .._serialization import (
|
|
18
19
|
deserialize,
|
|
19
20
|
deserialize_data_format,
|
|
21
|
+
get_preferred_payload_format,
|
|
20
22
|
serialize,
|
|
23
|
+
serialize_data_format as _serialize_data_format,
|
|
21
24
|
signature_to_parameter_specs,
|
|
22
25
|
)
|
|
23
26
|
from .._traceback import append_modal_tb
|
|
@@ -38,6 +41,9 @@ from .blob_utils import (
|
|
|
38
41
|
)
|
|
39
42
|
from .grpc_utils import RETRYABLE_GRPC_STATUS_CODES
|
|
40
43
|
|
|
44
|
+
if typing.TYPE_CHECKING:
|
|
45
|
+
import modal._functions
|
|
46
|
+
|
|
41
47
|
|
|
42
48
|
class FunctionInfoType(Enum):
|
|
43
49
|
PACKAGE = "package"
|
|
@@ -486,7 +492,7 @@ async def _process_result(result: api_pb2.GenericResult, data_format: int, stub,
|
|
|
486
492
|
elif result.status == api_pb2.GenericResult.GENERIC_STATUS_INTERNAL_FAILURE:
|
|
487
493
|
raise InternalFailure(result.exception)
|
|
488
494
|
elif result.status != api_pb2.GenericResult.GENERIC_STATUS_SUCCESS:
|
|
489
|
-
if data:
|
|
495
|
+
if data and data_format == api_pb2.DATA_FORMAT_PICKLE:
|
|
490
496
|
try:
|
|
491
497
|
exc = deserialize(data, client)
|
|
492
498
|
except DeserializationError as deser_exc:
|
|
@@ -549,27 +555,35 @@ async def _create_input(
|
|
|
549
555
|
kwargs,
|
|
550
556
|
stub: ModalClientModal,
|
|
551
557
|
*,
|
|
552
|
-
|
|
558
|
+
function: "modal._functions._Function",
|
|
553
559
|
idx: Optional[int] = None,
|
|
554
|
-
method_name: Optional[str] = None,
|
|
555
560
|
function_call_invocation_type: Optional["api_pb2.FunctionCallInvocationType.ValueType"] = None,
|
|
556
561
|
) -> api_pb2.FunctionPutInputsItem:
|
|
557
562
|
"""Serialize function arguments and create a FunctionInput protobuf,
|
|
558
563
|
uploading to blob storage if needed.
|
|
559
564
|
"""
|
|
565
|
+
method_name = function._use_method_name
|
|
566
|
+
max_object_size_bytes = function._max_object_size_bytes
|
|
567
|
+
|
|
560
568
|
if idx is None:
|
|
561
569
|
idx = 0
|
|
562
|
-
if method_name is None:
|
|
563
|
-
method_name = "" # proto compatible
|
|
564
570
|
|
|
565
|
-
|
|
571
|
+
data_format = get_preferred_payload_format()
|
|
572
|
+
if not function._metadata:
|
|
573
|
+
raise ExecutionError("Attempted to call function that has not been hydrated with metadata")
|
|
574
|
+
|
|
575
|
+
supported_input_formats = function._metadata.supported_input_formats or [api_pb2.DATA_FORMAT_PICKLE]
|
|
576
|
+
if data_format not in supported_input_formats:
|
|
577
|
+
data_format = supported_input_formats[0]
|
|
578
|
+
|
|
579
|
+
args_serialized = _serialize_data_format((args, kwargs), data_format)
|
|
566
580
|
|
|
567
581
|
if should_upload(len(args_serialized), max_object_size_bytes, function_call_invocation_type):
|
|
568
582
|
args_blob_id, r2_failed, r2_throughput_bytes_s = await blob_upload_with_r2_failure_info(args_serialized, stub)
|
|
569
583
|
return api_pb2.FunctionPutInputsItem(
|
|
570
584
|
input=api_pb2.FunctionInput(
|
|
571
585
|
args_blob_id=args_blob_id,
|
|
572
|
-
data_format=
|
|
586
|
+
data_format=data_format,
|
|
573
587
|
method_name=method_name,
|
|
574
588
|
),
|
|
575
589
|
idx=idx,
|
|
@@ -580,7 +594,7 @@ async def _create_input(
|
|
|
580
594
|
return api_pb2.FunctionPutInputsItem(
|
|
581
595
|
input=api_pb2.FunctionInput(
|
|
582
596
|
args=args_serialized,
|
|
583
|
-
data_format=
|
|
597
|
+
data_format=data_format,
|
|
584
598
|
method_name=method_name,
|
|
585
599
|
),
|
|
586
600
|
idx=idx,
|
modal/app.py
CHANGED
|
@@ -667,6 +667,7 @@ class _App:
|
|
|
667
667
|
] = None, # Experimental controls over fine-grained scheduling (alpha).
|
|
668
668
|
_experimental_proxy_ip: Optional[str] = None, # IP address of proxy
|
|
669
669
|
_experimental_custom_scaling_factor: Optional[float] = None, # Custom scaling factor
|
|
670
|
+
_experimental_restrict_output: bool = False, # Don't use pickle for return values
|
|
670
671
|
# Parameters below here are deprecated. Please update your code as suggested
|
|
671
672
|
keep_warm: Optional[int] = None, # Replaced with `min_containers`
|
|
672
673
|
concurrency_limit: Optional[int] = None, # Replaced with `max_containers`
|
|
@@ -835,6 +836,7 @@ class _App:
|
|
|
835
836
|
include_source=include_source if include_source is not None else self._include_source_default,
|
|
836
837
|
experimental_options={k: str(v) for k, v in (experimental_options or {}).items()},
|
|
837
838
|
_experimental_proxy_ip=_experimental_proxy_ip,
|
|
839
|
+
restrict_output=_experimental_restrict_output,
|
|
838
840
|
)
|
|
839
841
|
|
|
840
842
|
self._add_function(function, webhook_config is not None)
|
|
@@ -895,6 +897,7 @@ class _App:
|
|
|
895
897
|
] = None, # Experimental controls over fine-grained scheduling (alpha).
|
|
896
898
|
_experimental_proxy_ip: Optional[str] = None, # IP address of proxy
|
|
897
899
|
_experimental_custom_scaling_factor: Optional[float] = None, # Custom scaling factor
|
|
900
|
+
_experimental_restrict_output: bool = False, # Don't use pickle for return values
|
|
898
901
|
# Parameters below here are deprecated. Please update your code as suggested
|
|
899
902
|
keep_warm: Optional[int] = None, # Replaced with `min_containers`
|
|
900
903
|
concurrency_limit: Optional[int] = None, # Replaced with `max_containers`
|
|
@@ -1028,6 +1031,7 @@ class _App:
|
|
|
1028
1031
|
experimental_options={k: str(v) for k, v in (experimental_options or {}).items()},
|
|
1029
1032
|
_experimental_proxy_ip=_experimental_proxy_ip,
|
|
1030
1033
|
_experimental_custom_scaling_factor=_experimental_custom_scaling_factor,
|
|
1034
|
+
restrict_output=_experimental_restrict_output,
|
|
1031
1035
|
)
|
|
1032
1036
|
|
|
1033
1037
|
self._add_function(cls_func, is_web_endpoint=False)
|
modal/app.pyi
CHANGED
|
@@ -427,6 +427,7 @@ class _App:
|
|
|
427
427
|
_experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
|
|
428
428
|
_experimental_proxy_ip: typing.Optional[str] = None,
|
|
429
429
|
_experimental_custom_scaling_factor: typing.Optional[float] = None,
|
|
430
|
+
_experimental_restrict_output: bool = False,
|
|
430
431
|
keep_warm: typing.Optional[int] = None,
|
|
431
432
|
concurrency_limit: typing.Optional[int] = None,
|
|
432
433
|
container_idle_timeout: typing.Optional[int] = None,
|
|
@@ -480,6 +481,7 @@ class _App:
|
|
|
480
481
|
_experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
|
|
481
482
|
_experimental_proxy_ip: typing.Optional[str] = None,
|
|
482
483
|
_experimental_custom_scaling_factor: typing.Optional[float] = None,
|
|
484
|
+
_experimental_restrict_output: bool = False,
|
|
483
485
|
keep_warm: typing.Optional[int] = None,
|
|
484
486
|
concurrency_limit: typing.Optional[int] = None,
|
|
485
487
|
container_idle_timeout: typing.Optional[int] = None,
|
|
@@ -1034,6 +1036,7 @@ class App:
|
|
|
1034
1036
|
_experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
|
|
1035
1037
|
_experimental_proxy_ip: typing.Optional[str] = None,
|
|
1036
1038
|
_experimental_custom_scaling_factor: typing.Optional[float] = None,
|
|
1039
|
+
_experimental_restrict_output: bool = False,
|
|
1037
1040
|
keep_warm: typing.Optional[int] = None,
|
|
1038
1041
|
concurrency_limit: typing.Optional[int] = None,
|
|
1039
1042
|
container_idle_timeout: typing.Optional[int] = None,
|
|
@@ -1087,6 +1090,7 @@ class App:
|
|
|
1087
1090
|
_experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
|
|
1088
1091
|
_experimental_proxy_ip: typing.Optional[str] = None,
|
|
1089
1092
|
_experimental_custom_scaling_factor: typing.Optional[float] = None,
|
|
1093
|
+
_experimental_restrict_output: bool = False,
|
|
1090
1094
|
keep_warm: typing.Optional[int] = None,
|
|
1091
1095
|
concurrency_limit: typing.Optional[int] = None,
|
|
1092
1096
|
container_idle_timeout: typing.Optional[int] = None,
|
modal/client.pyi
CHANGED
|
@@ -33,7 +33,7 @@ class _Client:
|
|
|
33
33
|
server_url: str,
|
|
34
34
|
client_type: int,
|
|
35
35
|
credentials: typing.Optional[tuple[str, str]],
|
|
36
|
-
version: str = "1.1.5.
|
|
36
|
+
version: str = "1.1.5.dev46",
|
|
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.1.5.
|
|
167
|
+
version: str = "1.1.5.dev46",
|
|
168
168
|
):
|
|
169
169
|
"""mdmd:hidden
|
|
170
170
|
The Modal client object is not intended to be instantiated directly by users.
|
modal/config.py
CHANGED
|
@@ -239,6 +239,11 @@ _SETTINGS = {
|
|
|
239
239
|
"snapshot_debug": _Setting(False, transform=_to_boolean),
|
|
240
240
|
"cuda_checkpoint_path": _Setting("/__modal/.bin/cuda-checkpoint"), # Used for snapshotting GPU memory.
|
|
241
241
|
"build_validation": _Setting("error", transform=_check_value(["error", "warn", "ignore"])),
|
|
242
|
+
# Payload format for function inputs/outputs: 'pickle' (default) or 'cbor'
|
|
243
|
+
"payload_format": _Setting(
|
|
244
|
+
"pickle",
|
|
245
|
+
transform=lambda s: _check_value(["pickle", "cbor"])(s.lower()),
|
|
246
|
+
),
|
|
242
247
|
}
|
|
243
248
|
|
|
244
249
|
|
modal/functions.pyi
CHANGED
|
@@ -111,6 +111,7 @@ class Function(
|
|
|
111
111
|
experimental_options: typing.Optional[dict[str, str]] = None,
|
|
112
112
|
_experimental_proxy_ip: typing.Optional[str] = None,
|
|
113
113
|
_experimental_custom_scaling_factor: typing.Optional[float] = None,
|
|
114
|
+
restrict_output: bool = False,
|
|
114
115
|
) -> Function:
|
|
115
116
|
"""mdmd:hidden
|
|
116
117
|
|
modal/image.py
CHANGED
|
@@ -25,11 +25,12 @@ from google.protobuf.message import Message
|
|
|
25
25
|
from grpclib.exceptions import GRPCError, StreamTerminatedError
|
|
26
26
|
from typing_extensions import Self
|
|
27
27
|
|
|
28
|
+
from modal._serialization import serialize_data_format
|
|
28
29
|
from modal_proto import api_pb2
|
|
29
30
|
|
|
30
31
|
from ._object import _Object, live_method_gen
|
|
31
32
|
from ._resolver import Resolver
|
|
32
|
-
from ._serialization import serialize
|
|
33
|
+
from ._serialization import get_preferred_payload_format, serialize
|
|
33
34
|
from ._utils.async_utils import synchronize_api
|
|
34
35
|
from ._utils.blob_utils import MAX_OBJECT_SIZE_BYTES
|
|
35
36
|
from ._utils.deprecation import deprecation_warning
|
|
@@ -2318,13 +2319,19 @@ class _Image(_Object, type_prefix="im"):
|
|
|
2318
2319
|
include_source=include_source,
|
|
2319
2320
|
)
|
|
2320
2321
|
if len(args) + len(kwargs) > 0:
|
|
2321
|
-
|
|
2322
|
+
data_format = get_preferred_payload_format()
|
|
2323
|
+
args_serialized = serialize_data_format((args, kwargs), data_format)
|
|
2324
|
+
|
|
2322
2325
|
if len(args_serialized) > MAX_OBJECT_SIZE_BYTES:
|
|
2323
2326
|
raise InvalidError(
|
|
2324
2327
|
f"Arguments to `run_function` are too large ({len(args_serialized)} bytes). "
|
|
2325
2328
|
f"Maximum size is {MAX_OBJECT_SIZE_BYTES} bytes."
|
|
2326
2329
|
)
|
|
2327
|
-
|
|
2330
|
+
|
|
2331
|
+
build_function_input = api_pb2.FunctionInput(
|
|
2332
|
+
args=args_serialized,
|
|
2333
|
+
data_format=data_format,
|
|
2334
|
+
)
|
|
2328
2335
|
else:
|
|
2329
2336
|
build_function_input = None
|
|
2330
2337
|
return _Image._from_args(
|
modal/parallel_map.py
CHANGED
|
@@ -128,9 +128,8 @@ class InputPreprocessor:
|
|
|
128
128
|
args,
|
|
129
129
|
kwargs,
|
|
130
130
|
self.client.stub,
|
|
131
|
-
max_object_size_bytes=self.function._max_object_size_bytes,
|
|
132
131
|
idx=idx,
|
|
133
|
-
|
|
132
|
+
function=self.function,
|
|
134
133
|
)
|
|
135
134
|
|
|
136
135
|
return create_input
|
|
@@ -728,9 +727,8 @@ async def _map_invocation_inputplane(
|
|
|
728
727
|
args,
|
|
729
728
|
kwargs,
|
|
730
729
|
client.stub,
|
|
731
|
-
max_object_size_bytes=function._max_object_size_bytes,
|
|
732
730
|
idx=idx,
|
|
733
|
-
|
|
731
|
+
function=function,
|
|
734
732
|
)
|
|
735
733
|
return api_pb2.MapStartOrContinueItem(input=put_item)
|
|
736
734
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: modal
|
|
3
|
-
Version: 1.1.5.
|
|
3
|
+
Version: 1.1.5.dev46
|
|
4
4
|
Summary: Python client library for Modal
|
|
5
5
|
Author-email: Modal Labs <support@modal.com>
|
|
6
6
|
License: Apache-2.0
|
|
@@ -17,6 +17,7 @@ Requires-Python: >=3.9
|
|
|
17
17
|
Description-Content-Type: text/markdown
|
|
18
18
|
License-File: LICENSE
|
|
19
19
|
Requires-Dist: aiohttp
|
|
20
|
+
Requires-Dist: cbor2
|
|
20
21
|
Requires-Dist: certifi
|
|
21
22
|
Requires-Dist: click~=8.1
|
|
22
23
|
Requires-Dist: grpclib<0.4.9,>=0.4.7
|
|
@@ -2,8 +2,8 @@ modal/__init__.py,sha256=WMaRW-2IJRGA9ioNAaBhJYuyLvu-GS01L8wQD90fKBs,2682
|
|
|
2
2
|
modal/__main__.py,sha256=45H-GtwzaDfN-1nP4_HYvzN3s7AG_HXR4-ynrsjO_OI,2803
|
|
3
3
|
modal/_clustered_functions.py,sha256=Sy4Sf_17EO8OL-FUe8LYcm4hrqLyQFCssNhr3p0SroU,3013
|
|
4
4
|
modal/_clustered_functions.pyi,sha256=JmYwAGOLEnD5AF-gYF9O5tu-SgGjeoJz-X1j48b1Ijg,1157
|
|
5
|
-
modal/_container_entrypoint.py,sha256=
|
|
6
|
-
modal/_functions.py,sha256=
|
|
5
|
+
modal/_container_entrypoint.py,sha256=B_fIKKjWposiNsYOePifX7S6cR9hf5LRPhDfVums5O8,27867
|
|
6
|
+
modal/_functions.py,sha256=6e4rFdl8thTnRuhUOj_4ehOzC1wdvJHhYSoIwB0LXhU,91783
|
|
7
7
|
modal/_ipython.py,sha256=TW1fkVOmZL3YYqdS2YlM1hqpf654Yf8ZyybHdBnlhSw,301
|
|
8
8
|
modal/_location.py,sha256=joiX-0ZeutEUDTrrqLF1GHXCdVLF-rHzstocbMcd_-k,366
|
|
9
9
|
modal/_object.py,sha256=gwsLdXb-Ecd8nH8LVCo8oVZPzzdyo9BrN1DjgQmsSuM,11967
|
|
@@ -12,22 +12,22 @@ modal/_partial_function.py,sha256=Yqk97hLS6vi8nWWVpzS5TSWbndWMdCtkhccdnyDJgBk,37
|
|
|
12
12
|
modal/_pty.py,sha256=E58MQ8d5-wkbMatRKpQR-G9FdbCRcZGiZxOpGy__VuY,1481
|
|
13
13
|
modal/_resolver.py,sha256=2RWvm34cNSnbv1v7izJMNZgfvpLDD6LzaBlr0lIrLnY,7364
|
|
14
14
|
modal/_resources.py,sha256=NMAp0GCLutiZI4GuKSIVnRHVlstoD3hNGUabjTUtzf4,1794
|
|
15
|
-
modal/_serialization.py,sha256=
|
|
15
|
+
modal/_serialization.py,sha256=_3-Z9jSoleDnv2HghH2kfo0m_WG8Iajs1wop1Iqnam8,26341
|
|
16
16
|
modal/_traceback.py,sha256=muKP7RbAXq74UGwkaVIdOxDdfDug0UcDKr9fe4LL3m8,6503
|
|
17
17
|
modal/_tunnel.py,sha256=zTBxBiuH1O22tS1OliAJdIsSmaZS8PlnifS_6S5z-mk,6320
|
|
18
18
|
modal/_tunnel.pyi,sha256=rvC7USR2BcKkbZIeCJXwf7-UfGE-LPLjKsGNiK7Lxa4,13366
|
|
19
19
|
modal/_type_manager.py,sha256=DWjgmjYJuOagw2erin506UUbG2H5UzZCFEekS-7hmfA,9087
|
|
20
20
|
modal/_watcher.py,sha256=K6LYnlmSGQB4tWWI9JADv-tvSvQ1j522FwT71B51CX8,3584
|
|
21
|
-
modal/app.py,sha256=
|
|
22
|
-
modal/app.pyi,sha256=
|
|
21
|
+
modal/app.py,sha256=Escm3cNiy0cXnVazO85BQgBItGeNXSfxqNEFiqcxqXk,49159
|
|
22
|
+
modal/app.pyi,sha256=KzBPGM8nJc-y_79jNYlSXb6iseG0Sn0Mk73Lq5zTlfA,44167
|
|
23
23
|
modal/call_graph.py,sha256=1g2DGcMIJvRy-xKicuf63IVE98gJSnQsr8R_NVMptNc,2581
|
|
24
24
|
modal/client.py,sha256=kyAIVB3Ay-XKJizQ_1ufUFB__EagV0MLmHJpyYyJ7J0,18636
|
|
25
|
-
modal/client.pyi,sha256=
|
|
25
|
+
modal/client.pyi,sha256=_t1pvWcz5lYgrbG1pwRcAYGSrJeL6LqLvza6ya_vgjc,15831
|
|
26
26
|
modal/cloud_bucket_mount.py,sha256=I2GRXYhOWLIz2kJZjXu75jAm9EJkBNcutGc6jR2ReUw,5928
|
|
27
27
|
modal/cloud_bucket_mount.pyi,sha256=VuUOipMIHqFXMkD-3g2bsoqpSxV5qswlFHDOqPQzYAo,7405
|
|
28
28
|
modal/cls.py,sha256=R1uLQbdqWRRjvxs0I57a4hZZELZkBVCxOKxvKryU5_s,41639
|
|
29
29
|
modal/cls.pyi,sha256=PRvC9lWIBL-L4cMc9cIt8I_ZDXI7oFttitKaFWWwhUk,29709
|
|
30
|
-
modal/config.py,sha256=
|
|
30
|
+
modal/config.py,sha256=OLxJU1K7ijiV_65g700QcHX8hIPH-dgzuybyQAOf6cg,12333
|
|
31
31
|
modal/container_process.py,sha256=Mutkl7sg_WR5zP4oJiWSC-3UdYRqp0zdKi1shZbi-bk,6996
|
|
32
32
|
modal/container_process.pyi,sha256=9m-st3hCUlNN1GOTctfPPvIvoLtEl7FbuGWwif5-7YU,6037
|
|
33
33
|
modal/dict.py,sha256=PGtZWy1F72qkoYu6_6chXLFQczobZwZyCxYle0vEd-o,22988
|
|
@@ -39,9 +39,9 @@ modal/file_io.py,sha256=OSKr77TujcXGJW1iikzYiHckLSmv07QBgBHcxxYEkoI,21456
|
|
|
39
39
|
modal/file_io.pyi,sha256=xtO6Glf_BFwDE7QiQQo24QqcMf_Vv-iz7WojcGVlLBU,15932
|
|
40
40
|
modal/file_pattern_matcher.py,sha256=A_Kdkej6q7YQyhM_2-BvpFmPqJ0oHb54B6yf9VqvPVE,8116
|
|
41
41
|
modal/functions.py,sha256=kcNHvqeGBxPI7Cgd57NIBBghkfbeFJzXO44WW0jSmao,325
|
|
42
|
-
modal/functions.pyi,sha256=
|
|
42
|
+
modal/functions.pyi,sha256=FU1F_75_-Y-YEWo6UNxvmuQ8P3T8TNgpqEqhgED4dhc,39597
|
|
43
43
|
modal/gpu.py,sha256=Fe5ORvVPDIstSq1xjmM6OoNgLYFWvogP9r5BgmD3hYg,6769
|
|
44
|
-
modal/image.py,sha256=
|
|
44
|
+
modal/image.py,sha256=pCiIeDt-YDpzBZ7_uqPcuizRniZYG34Z_NDMCsIIjas,108084
|
|
45
45
|
modal/image.pyi,sha256=ZNp48mVPzcQ6XNvxin1iO5XrZ89vfEZvU1Bi-V57jq0,76835
|
|
46
46
|
modal/io_streams.py,sha256=hZOVc5beOAm8S_VQQmmKUbk_BJ9OltN83RY0yMPqUDo,16545
|
|
47
47
|
modal/io_streams.pyi,sha256=aOun_jUFKHSJyUY6-7gKvNoxzcULsa8_hxdtEO7v-gk,13980
|
|
@@ -52,7 +52,7 @@ modal/network_file_system.pyi,sha256=Zg5Wg2c-EGOn2xTo2zgPbmtdyt51eda5E63UefI9yes
|
|
|
52
52
|
modal/object.py,sha256=bTeskuY8JFrESjU4_UL_nTwYlBQdOLmVaOX3X6EMxsg,164
|
|
53
53
|
modal/object.pyi,sha256=qlyVVMezW3XgJe_iqhtzWRSki3Nuk-KrpXc1g-r8ujA,6944
|
|
54
54
|
modal/output.py,sha256=q4T9uHduunj4NwY-YSwkHGgjZlCXMuJbfQ5UFaAGRAc,1968
|
|
55
|
-
modal/parallel_map.py,sha256=
|
|
55
|
+
modal/parallel_map.py,sha256=BkAQER2p3uus2VaODO6r_NhYDGtrh6dBF4AK2AhfIGI,69110
|
|
56
56
|
modal/parallel_map.pyi,sha256=NZrtfZljig59hcMKU7Cz8lYZZFOiwK9l7oWrBtX6Oy8,15838
|
|
57
57
|
modal/partial_function.py,sha256=aIdlGfTjjgqY6Fpr-biCjvRU9W542_S5N2xkNN_rYGM,1127
|
|
58
58
|
modal/partial_function.pyi,sha256=lqqOzZ9-QvHTDWKQ_oAYYOvsXgTOBKhO9u-RI98JbUk,13986
|
|
@@ -82,22 +82,22 @@ modal/volume.py,sha256=bPC8632-LyeLOjJu2fKOFyod0QG7Hd5bb-UIJ5syCjo,53303
|
|
|
82
82
|
modal/volume.pyi,sha256=5VppIgoqoJqpivESYt5_oWgVTL__zlmpNZkOPk43JF8,54443
|
|
83
83
|
modal/_runtime/__init__.py,sha256=MIEP8jhXUeGq_eCjYFcqN5b1bxBM4fdk0VESpjWR0fc,28
|
|
84
84
|
modal/_runtime/asgi.py,sha256=AOcduIlijmlxhXVWo7AIUhigo-bqm6nDkHj4Q4JLy6o,22607
|
|
85
|
-
modal/_runtime/container_io_manager.py,sha256=
|
|
86
|
-
modal/_runtime/container_io_manager.pyi,sha256=
|
|
85
|
+
modal/_runtime/container_io_manager.py,sha256=HZJsAC7Vn1a3EXpyJAMuOibsFulHpWlqTE420_jJRWw,51775
|
|
86
|
+
modal/_runtime/container_io_manager.pyi,sha256=GDNLirCcPMRc6gckInYKmGmJZY3LNcgUVXKftt9P9jI,23493
|
|
87
87
|
modal/_runtime/execution_context.py,sha256=AYrNQRHHXEqX2MwMf8zxelKZnYf25RE_B-NRLWf93n8,3521
|
|
88
88
|
modal/_runtime/execution_context.pyi,sha256=FVzakehz72ndL-ufe8-EC7TM4IHO_MEBcAdgWuU4W9k,2426
|
|
89
89
|
modal/_runtime/gpu_memory_snapshot.py,sha256=BWIMKkH-UXTQOJJuXbM15UWCHHSYlJ0XxGlZunKb0Ug,11877
|
|
90
90
|
modal/_runtime/telemetry.py,sha256=T1RoAGyjBDr1swiM6pPsGRSITm7LI5FDK18oNXxY08U,5163
|
|
91
|
-
modal/_runtime/user_code_imports.py,sha256=
|
|
91
|
+
modal/_runtime/user_code_imports.py,sha256=1MlOgw810aj0MeDvFPvHBIz-aHd7jUX6dwRfIcM3-KE,16498
|
|
92
92
|
modal/_utils/__init__.py,sha256=waLjl5c6IPDhSsdWAm9Bji4e2PVxamYABKAze6CHVXY,28
|
|
93
93
|
modal/_utils/app_utils.py,sha256=88BT4TPLWfYAQwKTHcyzNQRHg8n9B-QE2UyJs96iV-0,108
|
|
94
94
|
modal/_utils/async_utils.py,sha256=7uA4KJV7XRgak5nXZSGRE-RN1h91UOyNwK6v_ilUQMQ,29737
|
|
95
95
|
modal/_utils/auth_token_manager.py,sha256=i-kfLgDd4BMAw6wouO5aKfNGHo27VAZoVOsbEWqDr2I,5252
|
|
96
|
-
modal/_utils/blob_utils.py,sha256=
|
|
96
|
+
modal/_utils/blob_utils.py,sha256=bmPPHfLy8Kdna8e2xS3lvKwnN5pJUUt_rN39kVIYPFM,22874
|
|
97
97
|
modal/_utils/bytes_io_segment_payload.py,sha256=vaXPq8b52-x6G2hwE7SrjS58pg_aRm7gV3bn3yjmTzQ,4261
|
|
98
98
|
modal/_utils/deprecation.py,sha256=-Bgg7jZdcJU8lROy18YyVnQYbM8hue-hVmwJqlWAGH0,5504
|
|
99
99
|
modal/_utils/docker_utils.py,sha256=h1uETghR40mp_y3fSWuZAfbIASH1HMzuphJHghAL6DU,3722
|
|
100
|
-
modal/_utils/function_utils.py,sha256=
|
|
100
|
+
modal/_utils/function_utils.py,sha256=6PLmt4U_Kpi-cXvPvIgjDCeYJoFMkf0XzpEJ_0QczdQ,28070
|
|
101
101
|
modal/_utils/git_utils.py,sha256=qtUU6JAttF55ZxYq51y55OR58B0tDPZsZWK5dJe6W5g,3182
|
|
102
102
|
modal/_utils/grpc_testing.py,sha256=H1zHqthv19eGPJz2HKXDyWXWGSqO4BRsxah3L5Xaa8A,8619
|
|
103
103
|
modal/_utils/grpc_utils.py,sha256=1dQgTvdHG9KSfyVTc26HhKjGnIDJpdDEJ0xZARklOrU,10205
|
|
@@ -153,7 +153,7 @@ modal/experimental/__init__.py,sha256=fCqzo_f3vcY750vHtd7CtLs5dvdM_C0ZLLGb3zXuK9
|
|
|
153
153
|
modal/experimental/flash.py,sha256=7qRAL2Nrwbb60YKobcnpM0zJ8vw4xGJqabLPFgEzMZE,28295
|
|
154
154
|
modal/experimental/flash.pyi,sha256=R9VV0UDotiY9BRUjacB-xI4qhR3yBymAvEZFRFHztLs,15143
|
|
155
155
|
modal/experimental/ipython.py,sha256=TrCfmol9LGsRZMeDoeMPx3Hv3BFqQhYnmD_iH0pqdhk,2904
|
|
156
|
-
modal-1.1.5.
|
|
156
|
+
modal-1.1.5.dev46.dist-info/licenses/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
|
|
157
157
|
modal_docs/__init__.py,sha256=svYKtV8HDwDCN86zbdWqyq5T8sMdGDj0PVlzc2tIxDM,28
|
|
158
158
|
modal_docs/gen_cli_docs.py,sha256=c1yfBS_x--gL5bs0N4ihMwqwX8l3IBWSkBAKNNIi6bQ,3801
|
|
159
159
|
modal_docs/gen_reference_docs.py,sha256=d_CQUGQ0rfw28u75I2mov9AlS773z9rG40-yq5o7g2U,6359
|
|
@@ -161,13 +161,13 @@ modal_docs/mdmd/__init__.py,sha256=svYKtV8HDwDCN86zbdWqyq5T8sMdGDj0PVlzc2tIxDM,2
|
|
|
161
161
|
modal_docs/mdmd/mdmd.py,sha256=tUTImNd4UMFk1opkaw8J672gX8AkBO5gbY2S_NMxsxs,7140
|
|
162
162
|
modal_docs/mdmd/signatures.py,sha256=XJaZrK7Mdepk5fdX51A8uENiLFNil85Ud0d4MH8H5f0,3218
|
|
163
163
|
modal_proto/__init__.py,sha256=MIEP8jhXUeGq_eCjYFcqN5b1bxBM4fdk0VESpjWR0fc,28
|
|
164
|
-
modal_proto/api.proto,sha256=
|
|
165
|
-
modal_proto/api_grpc.py,sha256
|
|
166
|
-
modal_proto/api_pb2.py,sha256=
|
|
167
|
-
modal_proto/api_pb2.pyi,sha256=
|
|
168
|
-
modal_proto/api_pb2_grpc.py,sha256=
|
|
169
|
-
modal_proto/api_pb2_grpc.pyi,sha256=
|
|
170
|
-
modal_proto/modal_api_grpc.py,sha256=
|
|
164
|
+
modal_proto/api.proto,sha256=W1qPmNr6nIQvouOOwvA-PMAk-nbc7YRRfg52JG6ekkM,108734
|
|
165
|
+
modal_proto/api_grpc.py,sha256=2KC4gGgqj7FahTrmZD5Gvxs2yV9_5l65yWjLuEd5dNQ,132154
|
|
166
|
+
modal_proto/api_pb2.py,sha256=BUb2UKt_whSE3eZxCHOsTpWI15F8VwIlnV1nBl9vzsE,378988
|
|
167
|
+
modal_proto/api_pb2.pyi,sha256=T-FAXdzqDeQ9kDOurkF-nPyRkxQY45dqydQ5kda-XFY,523763
|
|
168
|
+
modal_proto/api_pb2_grpc.py,sha256=nh3_94du1FMglF7sgVfk-s3XCl4vc07Mu-6qe6e0DdY,284763
|
|
169
|
+
modal_proto/api_pb2_grpc.pyi,sha256=7X2WZeHyKJWsyEXyzoOdLlU3NT7jhWbaWDZw_-C6EeU,66726
|
|
170
|
+
modal_proto/modal_api_grpc.py,sha256=UTgAj4GMOSZmwJBgrhZYnKOyWP1rQQS_HSnlfKkKT5s,19929
|
|
171
171
|
modal_proto/modal_options_grpc.py,sha256=qJ1cuwA54oRqrdTyPTbvfhFZYd9HhJKK5UCwt523r3Y,120
|
|
172
172
|
modal_proto/options.proto,sha256=zp9h5r61ivsp0XwEWwNBsVqNTbRA1VSY_UtN7sEcHtE,549
|
|
173
173
|
modal_proto/options_grpc.py,sha256=M18X3d-8F_cNYSVM3I25dUTO5rZ0rd-vCCfynfh13Nc,125
|
|
@@ -182,10 +182,10 @@ modal_proto/sandbox_router_pb2.py,sha256=INd9izYaIYqllESQt4MSv2Rj9Hf5bMjAvtCc9b4
|
|
|
182
182
|
modal_proto/sandbox_router_pb2.pyi,sha256=YCK0WnCgRos3-p7t4USQQ7x6WAuM278yeQX2IeU5mLg,13295
|
|
183
183
|
modal_proto/sandbox_router_pb2_grpc.py,sha256=zonC5flvCwxeZYJPENj1IJo2Mr0J58DpoC1_8IdPYik,8243
|
|
184
184
|
modal_proto/sandbox_router_pb2_grpc.pyi,sha256=4QgCB9b7_ykvH8YD-hfnogVH9CLyHVDC5QNb03l4_X8,2735
|
|
185
|
-
modal_version/__init__.py,sha256=
|
|
185
|
+
modal_version/__init__.py,sha256=inTfu4X_ktIniXSpovrFrc423h5EFEfdFuAIr8vSaIs,121
|
|
186
186
|
modal_version/__main__.py,sha256=2FO0yYQQwDTh6udt1h-cBnGd1c4ZyHnHSI4BksxzVac,105
|
|
187
|
-
modal-1.1.5.
|
|
188
|
-
modal-1.1.5.
|
|
189
|
-
modal-1.1.5.
|
|
190
|
-
modal-1.1.5.
|
|
191
|
-
modal-1.1.5.
|
|
187
|
+
modal-1.1.5.dev46.dist-info/METADATA,sha256=TUAblWf8HEoo1eyE0NlwOnXfPl5WAn1NJt5eVm8WIr8,2481
|
|
188
|
+
modal-1.1.5.dev46.dist-info/WHEEL,sha256=1tXe9gY0PYatrMPMDd6jXqjfpz_B-Wqm32CPfRC58XU,91
|
|
189
|
+
modal-1.1.5.dev46.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
|
|
190
|
+
modal-1.1.5.dev46.dist-info/top_level.txt,sha256=4BWzoKYREKUZ5iyPzZpjqx4G8uB5TWxXPDwibLcVa7k,43
|
|
191
|
+
modal-1.1.5.dev46.dist-info/RECORD,,
|
modal_proto/api.proto
CHANGED
|
@@ -2729,6 +2729,18 @@ message SandboxCreateResponse {
|
|
|
2729
2729
|
string sandbox_id = 1;
|
|
2730
2730
|
}
|
|
2731
2731
|
|
|
2732
|
+
// Used to get a JWT and URL for direct access to a sandbox router server
|
|
2733
|
+
// running on the modal-worker, so the client can issue exec commands (and other
|
|
2734
|
+
// operations as they become available) directly to the worker.
|
|
2735
|
+
message SandboxGetCommandRouterAccessRequest {
|
|
2736
|
+
string sandbox_id = 1;
|
|
2737
|
+
}
|
|
2738
|
+
|
|
2739
|
+
message SandboxGetCommandRouterAccessResponse {
|
|
2740
|
+
string jwt = 1;
|
|
2741
|
+
string url = 2;
|
|
2742
|
+
}
|
|
2743
|
+
|
|
2732
2744
|
message SandboxGetFromNameRequest {
|
|
2733
2745
|
string sandbox_name = 1;
|
|
2734
2746
|
string environment_name = 2;
|
|
@@ -3679,6 +3691,7 @@ service ModalClient {
|
|
|
3679
3691
|
// Sandboxes
|
|
3680
3692
|
rpc SandboxCreate(SandboxCreateRequest) returns (SandboxCreateResponse);
|
|
3681
3693
|
rpc SandboxCreateConnectToken(SandboxCreateConnectTokenRequest) returns (SandboxCreateConnectTokenResponse);
|
|
3694
|
+
rpc SandboxGetCommandRouterAccess(SandboxGetCommandRouterAccessRequest) returns (SandboxGetCommandRouterAccessResponse);
|
|
3682
3695
|
rpc SandboxGetFromName(SandboxGetFromNameRequest) returns (SandboxGetFromNameResponse);
|
|
3683
3696
|
rpc SandboxGetLogs(SandboxGetLogsRequest) returns (stream TaskLogsBatch);
|
|
3684
3697
|
rpc SandboxGetResourceUsage(SandboxGetResourceUsageRequest) returns (SandboxGetResourceUsageResponse);
|
modal_proto/api_grpc.py
CHANGED
|
@@ -470,6 +470,10 @@ class ModalClientBase(abc.ABC):
|
|
|
470
470
|
async def SandboxCreateConnectToken(self, stream: 'grpclib.server.Stream[modal_proto.api_pb2.SandboxCreateConnectTokenRequest, modal_proto.api_pb2.SandboxCreateConnectTokenResponse]') -> None:
|
|
471
471
|
pass
|
|
472
472
|
|
|
473
|
+
@abc.abstractmethod
|
|
474
|
+
async def SandboxGetCommandRouterAccess(self, stream: 'grpclib.server.Stream[modal_proto.api_pb2.SandboxGetCommandRouterAccessRequest, modal_proto.api_pb2.SandboxGetCommandRouterAccessResponse]') -> None:
|
|
475
|
+
pass
|
|
476
|
+
|
|
473
477
|
@abc.abstractmethod
|
|
474
478
|
async def SandboxGetFromName(self, stream: 'grpclib.server.Stream[modal_proto.api_pb2.SandboxGetFromNameRequest, modal_proto.api_pb2.SandboxGetFromNameResponse]') -> None:
|
|
475
479
|
pass
|
|
@@ -1378,6 +1382,12 @@ class ModalClientBase(abc.ABC):
|
|
|
1378
1382
|
modal_proto.api_pb2.SandboxCreateConnectTokenRequest,
|
|
1379
1383
|
modal_proto.api_pb2.SandboxCreateConnectTokenResponse,
|
|
1380
1384
|
),
|
|
1385
|
+
'/modal.client.ModalClient/SandboxGetCommandRouterAccess': grpclib.const.Handler(
|
|
1386
|
+
self.SandboxGetCommandRouterAccess,
|
|
1387
|
+
grpclib.const.Cardinality.UNARY_UNARY,
|
|
1388
|
+
modal_proto.api_pb2.SandboxGetCommandRouterAccessRequest,
|
|
1389
|
+
modal_proto.api_pb2.SandboxGetCommandRouterAccessResponse,
|
|
1390
|
+
),
|
|
1381
1391
|
'/modal.client.ModalClient/SandboxGetFromName': grpclib.const.Handler(
|
|
1382
1392
|
self.SandboxGetFromName,
|
|
1383
1393
|
grpclib.const.Cardinality.UNARY_UNARY,
|
|
@@ -2404,6 +2414,12 @@ class ModalClientStub:
|
|
|
2404
2414
|
modal_proto.api_pb2.SandboxCreateConnectTokenRequest,
|
|
2405
2415
|
modal_proto.api_pb2.SandboxCreateConnectTokenResponse,
|
|
2406
2416
|
)
|
|
2417
|
+
self.SandboxGetCommandRouterAccess = grpclib.client.UnaryUnaryMethod(
|
|
2418
|
+
channel,
|
|
2419
|
+
'/modal.client.ModalClient/SandboxGetCommandRouterAccess',
|
|
2420
|
+
modal_proto.api_pb2.SandboxGetCommandRouterAccessRequest,
|
|
2421
|
+
modal_proto.api_pb2.SandboxGetCommandRouterAccessResponse,
|
|
2422
|
+
)
|
|
2407
2423
|
self.SandboxGetFromName = grpclib.client.UnaryUnaryMethod(
|
|
2408
2424
|
channel,
|
|
2409
2425
|
'/modal.client.ModalClient/SandboxGetFromName',
|