modal 0.73.149__py3-none-any.whl → 0.73.151__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/_functions.py +27 -2
- modal/_serialization.py +26 -1
- modal/client.pyi +2 -2
- modal/cls.py +22 -0
- modal/cls.pyi +12 -0
- modal/config.py +1 -0
- modal/functions.pyi +7 -0
- {modal-0.73.149.dist-info → modal-0.73.151.dist-info}/METADATA +1 -1
- {modal-0.73.149.dist-info → modal-0.73.151.dist-info}/RECORD +21 -21
- modal_proto/api.proto +81 -2
- modal_proto/api_grpc.py +16 -0
- modal_proto/api_pb2.py +614 -548
- modal_proto/api_pb2.pyi +196 -10
- 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.73.149.dist-info → modal-0.73.151.dist-info}/LICENSE +0 -0
- {modal-0.73.149.dist-info → modal-0.73.151.dist-info}/WHEEL +0 -0
- {modal-0.73.149.dist-info → modal-0.73.151.dist-info}/entry_points.txt +0 -0
- {modal-0.73.149.dist-info → modal-0.73.151.dist-info}/top_level.txt +0 -0
modal/_functions.py
CHANGED
@@ -27,6 +27,7 @@ from ._resources import convert_fn_config_to_resources_config
|
|
27
27
|
from ._runtime.execution_context import current_input_id, is_local
|
28
28
|
from ._serialization import (
|
29
29
|
apply_defaults,
|
30
|
+
get_callable_schema,
|
30
31
|
serialize,
|
31
32
|
serialize_proto_params,
|
32
33
|
validate_parameter_values,
|
@@ -415,6 +416,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
|
|
415
416
|
_method_handle_metadata: Optional[dict[str, "api_pb2.FunctionHandleMetadata"]] = (
|
416
417
|
None # set for 0.67+ class service functions
|
417
418
|
)
|
419
|
+
_metadata: Optional[api_pb2.FunctionHandleMetadata] = None
|
418
420
|
|
419
421
|
@staticmethod
|
420
422
|
def from_local(
|
@@ -650,10 +652,17 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
|
|
650
652
|
for method_name, partial_function in interface_methods.items():
|
651
653
|
function_type = get_function_type(partial_function.params.is_generator)
|
652
654
|
function_name = f"{info.user_cls.__name__}.{method_name}"
|
655
|
+
method_schema = get_callable_schema(
|
656
|
+
partial_function._get_raw_f(),
|
657
|
+
is_web_endpoint=partial_function._is_web_endpoint(),
|
658
|
+
ignore_first_argument=True,
|
659
|
+
)
|
660
|
+
|
653
661
|
method_definition = api_pb2.MethodDefinition(
|
654
662
|
webhook_config=partial_function.params.webhook_config,
|
655
663
|
function_type=function_type,
|
656
664
|
function_name=function_name,
|
665
|
+
function_schema=method_schema,
|
657
666
|
)
|
658
667
|
method_definitions[method_name] = method_definition
|
659
668
|
|
@@ -695,6 +704,9 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
|
|
695
704
|
function_name=info.function_name,
|
696
705
|
function_type=function_type,
|
697
706
|
existing_function_id=existing_object_id or "",
|
707
|
+
function_schema=get_callable_schema(info.raw_f, is_web_endpoint=bool(webhook_config))
|
708
|
+
if info.raw_f
|
709
|
+
else None,
|
698
710
|
)
|
699
711
|
if method_definitions:
|
700
712
|
for method_name, method_definition in method_definitions.items():
|
@@ -763,8 +775,9 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
|
|
763
775
|
object_dependencies.append(api_pb2.ObjectDependency(object_id=dep.object_id))
|
764
776
|
|
765
777
|
function_data: Optional[api_pb2.FunctionData] = None
|
766
|
-
|
767
|
-
|
778
|
+
function_schema = (
|
779
|
+
get_callable_schema(info.raw_f, is_web_endpoint=bool(webhook_config)) if info.raw_f else None
|
780
|
+
)
|
768
781
|
# Create function remotely
|
769
782
|
function_definition = api_pb2.Function(
|
770
783
|
module_name=info.module_name or "",
|
@@ -823,6 +836,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
|
|
823
836
|
_experimental_buffer_containers=buffer_containers or 0,
|
824
837
|
task_idle_timeout_secs=scaledown_window or 0,
|
825
838
|
# ---
|
839
|
+
function_schema=function_schema,
|
826
840
|
)
|
827
841
|
|
828
842
|
if isinstance(gpu, list):
|
@@ -855,6 +869,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
|
|
855
869
|
_experimental_proxy_ip=function_definition._experimental_proxy_ip,
|
856
870
|
snapshot_debug=function_definition.snapshot_debug,
|
857
871
|
runtime_perf_record=function_definition.runtime_perf_record,
|
872
|
+
function_schema=function_schema,
|
858
873
|
)
|
859
874
|
|
860
875
|
ranked_functions = []
|
@@ -1225,12 +1240,15 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
|
|
1225
1240
|
self._function_name = None
|
1226
1241
|
self._info = None
|
1227
1242
|
self._serve_mounts = frozenset()
|
1243
|
+
self._metadata = None
|
1228
1244
|
|
1229
1245
|
def _hydrate_metadata(self, metadata: Optional[Message]):
|
1230
1246
|
# Overridden concrete implementation of base class method
|
1231
1247
|
assert metadata and isinstance(metadata, api_pb2.FunctionHandleMetadata), (
|
1232
1248
|
f"{type(metadata)} is not FunctionHandleMetadata"
|
1233
1249
|
)
|
1250
|
+
self._metadata = metadata
|
1251
|
+
# TODO: replace usage of all below with direct ._metadata access
|
1234
1252
|
self._is_generator = metadata.function_type == api_pb2.Function.FUNCTION_TYPE_GENERATOR
|
1235
1253
|
self._web_url = metadata.web_url
|
1236
1254
|
self._function_name = metadata.function_name
|
@@ -1252,6 +1270,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
|
|
1252
1270
|
class_parameter_info=self._class_parameter_info,
|
1253
1271
|
definition_id=self._definition_id,
|
1254
1272
|
method_handle_metadata=self._method_handle_metadata,
|
1273
|
+
function_schema=self._metadata.function_schema if self._metadata else None,
|
1255
1274
|
)
|
1256
1275
|
|
1257
1276
|
def _check_no_web_url(self, fn_name: str):
|
@@ -1535,6 +1554,12 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
|
|
1535
1554
|
)
|
1536
1555
|
return FunctionStats(backlog=resp.backlog, num_total_runners=resp.num_total_tasks)
|
1537
1556
|
|
1557
|
+
@live_method
|
1558
|
+
async def _get_schema(self) -> api_pb2.FunctionSchema:
|
1559
|
+
"""Returns recorded schema for function, internal use only for now"""
|
1560
|
+
assert self._metadata
|
1561
|
+
return self._metadata.function_schema
|
1562
|
+
|
1538
1563
|
# A bit hacky - but the map-style functions need to not be synchronicity-wrapped
|
1539
1564
|
# in order to not execute their input iterators on the synchronicity event loop.
|
1540
1565
|
# We still need to wrap them using MethodWithAio to maintain a synchronicity-like
|
modal/_serialization.py
CHANGED
@@ -12,7 +12,7 @@ from modal_proto import api_pb2
|
|
12
12
|
from ._object import _Object
|
13
13
|
from ._type_manager import parameter_serde_registry, schema_registry
|
14
14
|
from ._vendor import cloudpickle
|
15
|
-
from .config import logger
|
15
|
+
from .config import config, logger
|
16
16
|
from .exception import DeserializationError, ExecutionError, InvalidError
|
17
17
|
from .object import Object
|
18
18
|
|
@@ -526,3 +526,28 @@ def signature_to_parameter_specs(signature: inspect.Signature) -> list[api_pb2.C
|
|
526
526
|
field_spec = _signature_parameter_to_spec(param, include_legacy_parameter_fields=True)
|
527
527
|
modal_parameters.append(field_spec)
|
528
528
|
return modal_parameters
|
529
|
+
|
530
|
+
|
531
|
+
def get_callable_schema(
|
532
|
+
callable: typing.Callable, *, is_web_endpoint: bool, ignore_first_argument: bool = False
|
533
|
+
) -> typing.Optional[api_pb2.FunctionSchema]:
|
534
|
+
# ignore_first_argument can be used in case of unbound methods where we want to ignore the first (self) argument
|
535
|
+
if is_web_endpoint or not config.get("function_schemas"):
|
536
|
+
# we don't support schemas on web endpoints for now
|
537
|
+
return None
|
538
|
+
|
539
|
+
sig = inspect.signature(callable)
|
540
|
+
# TODO: treat no return value annotation as None return?
|
541
|
+
return_type_proto = schema_registry.get_proto_generic_type(sig.return_annotation)
|
542
|
+
arguments = []
|
543
|
+
for i, p in enumerate(sig.parameters.values()):
|
544
|
+
if i == 0 and ignore_first_argument:
|
545
|
+
continue
|
546
|
+
|
547
|
+
arguments.append(_signature_parameter_to_spec(p))
|
548
|
+
|
549
|
+
return api_pb2.FunctionSchema(
|
550
|
+
schema_type=api_pb2.FunctionSchema.FUNCTION_SCHEMA_V1,
|
551
|
+
arguments=arguments,
|
552
|
+
return_type=return_type_proto,
|
553
|
+
)
|
modal/client.pyi
CHANGED
@@ -31,7 +31,7 @@ class _Client:
|
|
31
31
|
server_url: str,
|
32
32
|
client_type: int,
|
33
33
|
credentials: typing.Optional[tuple[str, str]],
|
34
|
-
version: str = "0.73.
|
34
|
+
version: str = "0.73.151",
|
35
35
|
): ...
|
36
36
|
def is_closed(self) -> bool: ...
|
37
37
|
@property
|
@@ -93,7 +93,7 @@ class Client:
|
|
93
93
|
server_url: str,
|
94
94
|
client_type: int,
|
95
95
|
credentials: typing.Optional[tuple[str, str]],
|
96
|
-
version: str = "0.73.
|
96
|
+
version: str = "0.73.151",
|
97
97
|
): ...
|
98
98
|
def is_closed(self) -> bool: ...
|
99
99
|
@property
|
modal/cls.py
CHANGED
@@ -719,6 +719,28 @@ class _Cls(_Object, type_prefix="cs"):
|
|
719
719
|
Cls = synchronize_api(_Cls)
|
720
720
|
|
721
721
|
|
722
|
+
@synchronize_api
|
723
|
+
async def _get_constructor_args(cls: _Cls) -> typing.Sequence[api_pb2.ClassParameterSpec]:
|
724
|
+
# for internal use only - defined separately to not clutter Cls namespace
|
725
|
+
await cls.hydrate()
|
726
|
+
service_function = cls._get_class_service_function()
|
727
|
+
metadata = service_function._metadata
|
728
|
+
assert metadata
|
729
|
+
if metadata.class_parameter_info.format != metadata.class_parameter_info.PARAM_SERIALIZATION_FORMAT_PROTO:
|
730
|
+
raise InvalidError("Can only get constructor args for strictly parameterized classes")
|
731
|
+
return metadata.class_parameter_info.schema
|
732
|
+
|
733
|
+
|
734
|
+
@synchronize_api
|
735
|
+
async def _get_method_schemas(cls: _Cls) -> dict[str, api_pb2.FunctionSchema]:
|
736
|
+
# for internal use only - defined separately to not clutter Cls namespace
|
737
|
+
await cls.hydrate()
|
738
|
+
assert cls._method_metadata
|
739
|
+
return {
|
740
|
+
method_name: method_metadata.function_schema for method_name, method_metadata in cls._method_metadata.items()
|
741
|
+
}
|
742
|
+
|
743
|
+
|
722
744
|
class _NO_DEFAULT:
|
723
745
|
def __repr__(self):
|
724
746
|
return "modal.cls._NO_DEFAULT()"
|
modal/cls.pyi
CHANGED
@@ -244,6 +244,18 @@ class Cls(modal.object.Object):
|
|
244
244
|
def __getattr__(self, k): ...
|
245
245
|
def _is_local(self) -> bool: ...
|
246
246
|
|
247
|
+
class ___get_constructor_args_spec(typing_extensions.Protocol):
|
248
|
+
def __call__(self, cls: Cls) -> typing.Sequence[modal_proto.api_pb2.ClassParameterSpec]: ...
|
249
|
+
async def aio(self, cls: Cls) -> typing.Sequence[modal_proto.api_pb2.ClassParameterSpec]: ...
|
250
|
+
|
251
|
+
_get_constructor_args: ___get_constructor_args_spec
|
252
|
+
|
253
|
+
class ___get_method_schemas_spec(typing_extensions.Protocol):
|
254
|
+
def __call__(self, cls: Cls) -> dict[str, modal_proto.api_pb2.FunctionSchema]: ...
|
255
|
+
async def aio(self, cls: Cls) -> dict[str, modal_proto.api_pb2.FunctionSchema]: ...
|
256
|
+
|
257
|
+
_get_method_schemas: ___get_method_schemas_spec
|
258
|
+
|
247
259
|
class _NO_DEFAULT:
|
248
260
|
def __repr__(self): ...
|
249
261
|
|
modal/config.py
CHANGED
@@ -231,6 +231,7 @@ _SETTINGS = {
|
|
231
231
|
"strict_parameters": _Setting(False, transform=_to_boolean), # For internal/experimental use
|
232
232
|
"snapshot_debug": _Setting(False, transform=_to_boolean),
|
233
233
|
"cuda_checkpoint_path": _Setting("/__modal/.bin/cuda-checkpoint"), # Used for snapshotting GPU memory.
|
234
|
+
"function_schemas": _Setting(False, transform=_to_boolean),
|
234
235
|
}
|
235
236
|
|
236
237
|
|
modal/functions.pyi
CHANGED
@@ -52,6 +52,7 @@ class Function(
|
|
52
52
|
_use_method_name: str
|
53
53
|
_class_parameter_info: typing.Optional[modal_proto.api_pb2.ClassParameterInfo]
|
54
54
|
_method_handle_metadata: typing.Optional[dict[str, modal_proto.api_pb2.FunctionHandleMetadata]]
|
55
|
+
_metadata: typing.Optional[modal_proto.api_pb2.FunctionHandleMetadata]
|
55
56
|
|
56
57
|
def __init__(self, *args, **kwargs): ...
|
57
58
|
@staticmethod
|
@@ -240,6 +241,12 @@ class Function(
|
|
240
241
|
|
241
242
|
get_current_stats: __get_current_stats_spec[typing_extensions.Self]
|
242
243
|
|
244
|
+
class ___get_schema_spec(typing_extensions.Protocol[SUPERSELF]):
|
245
|
+
def __call__(self) -> modal_proto.api_pb2.FunctionSchema: ...
|
246
|
+
async def aio(self) -> modal_proto.api_pb2.FunctionSchema: ...
|
247
|
+
|
248
|
+
_get_schema: ___get_schema_spec[typing_extensions.Self]
|
249
|
+
|
243
250
|
class __map_spec(typing_extensions.Protocol[SUPERSELF]):
|
244
251
|
def __call__(
|
245
252
|
self, *input_iterators, kwargs={}, order_outputs: bool = True, return_exceptions: bool = False
|
@@ -3,7 +3,7 @@ modal/__main__.py,sha256=CgIjP8m1xJjjd4AXc-delmR6LdBCZclw2A_V38CFIio,2870
|
|
3
3
|
modal/_clustered_functions.py,sha256=kTf-9YBXY88NutC1akI-gCbvf01RhMPCw-zoOI_YIUE,2700
|
4
4
|
modal/_clustered_functions.pyi,sha256=vllkegc99A0jrUOWa8mdlSbdp6uz36TsHhGxysAOpaQ,771
|
5
5
|
modal/_container_entrypoint.py,sha256=XyqJPvzX0YMqviIIz-9bsD6HMrPsboU4A1yfgTloTSA,29302
|
6
|
-
modal/_functions.py,sha256=
|
6
|
+
modal/_functions.py,sha256=QKH7L7CHS_DN21bkayeQm-XkYFBs92El26RgKNTwqGA,74760
|
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=JBIECWdfpRKCaCxVWZbC3Q1kF5Whk_EKvY9f4Y6AFyg,11446
|
@@ -13,7 +13,7 @@ modal/_proxy_tunnel.py,sha256=gnKyCfmVB7x2d1A6c-JDysNIP3kEFxmXzhcXhPrzPn0,1906
|
|
13
13
|
modal/_pty.py,sha256=JZfPDDpzqICZqtyPI_oMJf_9w-p_lLNuzHhwhodUXio,1329
|
14
14
|
modal/_resolver.py,sha256=RtoXoYzSllPlFu0D1vel_FWiEmDO7RyToiC2bxeN8ZY,6917
|
15
15
|
modal/_resources.py,sha256=5qmcirXUI8dSH926nwkUaeX9H25mqYu9mXD_KuT79-o,1733
|
16
|
-
modal/_serialization.py,sha256=
|
16
|
+
modal/_serialization.py,sha256=kkLmQ6jnPlbLT3FfuyigocHKG7H1HDJ0i24IxYFbgs8,22927
|
17
17
|
modal/_traceback.py,sha256=IZQzB3fVlUfMHOSyKUgw0H6qv4yHnpyq-XVCNZKfUdA,5023
|
18
18
|
modal/_tunnel.py,sha256=zTBxBiuH1O22tS1OliAJdIsSmaZS8PlnifS_6S5z-mk,6320
|
19
19
|
modal/_tunnel.pyi,sha256=JmmDYAy9F1FpgJ_hWx0xkom2nTOFQjn4mTPYlU3PFo4,1245
|
@@ -23,12 +23,12 @@ modal/app.py,sha256=w00bV9cjABAsS2ExE7zb1jY6Q_snXYmdKa3xRFg8iXA,47428
|
|
23
23
|
modal/app.pyi,sha256=pUEqciyGZ446sc_QoG8XcQ_oc6oU-U4dqjkxjhgOX98,26968
|
24
24
|
modal/call_graph.py,sha256=1g2DGcMIJvRy-xKicuf63IVE98gJSnQsr8R_NVMptNc,2581
|
25
25
|
modal/client.py,sha256=j9D3hNis1lfhnz9lVFGgJgowbH3PaGUzNKgHPWYG778,15372
|
26
|
-
modal/client.pyi,sha256=
|
26
|
+
modal/client.pyi,sha256=TXB2eB0HqifVWkvHpWRDccAH40BN4qUq6ozXtYN9uSw,7661
|
27
27
|
modal/cloud_bucket_mount.py,sha256=YOe9nnvSr4ZbeCn587d7_VhE9IioZYRvF9VYQTQux08,5914
|
28
28
|
modal/cloud_bucket_mount.pyi,sha256=30T3K1a89l6wzmEJ_J9iWv9SknoGqaZDx59Xs-ZQcmk,1607
|
29
|
-
modal/cls.py,sha256=
|
30
|
-
modal/cls.pyi,sha256=
|
31
|
-
modal/config.py,sha256=
|
29
|
+
modal/cls.py,sha256=OE6lPrKmaZDvyctfmZ__nCIw-b7AWxSmoOHMqlrrI7A,32723
|
30
|
+
modal/cls.pyi,sha256=pTYO9JsRENmsa5pDgzfoRJGm_NpCvEjEx--vs-jJkj8,10902
|
31
|
+
modal/config.py,sha256=FlqVyh6LVukMahhmEGQVTwWtwtfoPfHqEo3GDn13EOA,11687
|
32
32
|
modal/container_process.py,sha256=vvyK3DVPUMsuqvkKdUiQ49cDLF9JawGrxpglLk5vfgI,6208
|
33
33
|
modal/container_process.pyi,sha256=bXs2KHe7nxVuLAm6RRBqXCvDKelANGX9gFY8qIuZYDs,2898
|
34
34
|
modal/dict.py,sha256=3Pb45IkfqcDGXu3VVStJVbC_QYk6RTRXrMbZxtByAAk,13354
|
@@ -40,7 +40,7 @@ modal/file_io.py,sha256=lcMs_E9Xfm0YX1t9U2wNIBPnqHRxmImqjLW1GHqVmyg,20945
|
|
40
40
|
modal/file_io.pyi,sha256=NTRft1tbPSWf9TlWVeZmTlgB5AZ_Zhu2srWIrWr7brk,9445
|
41
41
|
modal/file_pattern_matcher.py,sha256=trosX-Bp7dOubudN1bLLhRAoidWy1TcoaR4Pv8CedWw,6497
|
42
42
|
modal/functions.py,sha256=kcNHvqeGBxPI7Cgd57NIBBghkfbeFJzXO44WW0jSmao,325
|
43
|
-
modal/functions.pyi,sha256=
|
43
|
+
modal/functions.pyi,sha256=m1PL2pwO-lnGV0uZDVCmzZ_v7Mu8ISRtxmxS15aEIAQ,14785
|
44
44
|
modal/gpu.py,sha256=Kbhs_u49FaC2Zi0TjCdrpstpRtT5eZgecynmQi5IZVE,6752
|
45
45
|
modal/image.py,sha256=HtkKomhX4inozqSRi7lf5Vt9IEqCnVHn5bEo59hD64A,92835
|
46
46
|
modal/image.pyi,sha256=iWclz2rxaP-LSsYMgU0X3ZcN5mEFvpyKzIPKJbohmsg,25591
|
@@ -153,13 +153,13 @@ modal_docs/mdmd/__init__.py,sha256=svYKtV8HDwDCN86zbdWqyq5T8sMdGDj0PVlzc2tIxDM,2
|
|
153
153
|
modal_docs/mdmd/mdmd.py,sha256=Irx49MCCTlBOP4FBdLR--JrpA3-WhsVeriq0LGgsRic,6232
|
154
154
|
modal_docs/mdmd/signatures.py,sha256=XJaZrK7Mdepk5fdX51A8uENiLFNil85Ud0d4MH8H5f0,3218
|
155
155
|
modal_proto/__init__.py,sha256=MIEP8jhXUeGq_eCjYFcqN5b1bxBM4fdk0VESpjWR0fc,28
|
156
|
-
modal_proto/api.proto,sha256=
|
157
|
-
modal_proto/api_grpc.py,sha256=
|
158
|
-
modal_proto/api_pb2.py,sha256=
|
159
|
-
modal_proto/api_pb2.pyi,sha256=
|
160
|
-
modal_proto/api_pb2_grpc.py,sha256=
|
161
|
-
modal_proto/api_pb2_grpc.pyi,sha256=
|
162
|
-
modal_proto/modal_api_grpc.py,sha256=
|
156
|
+
modal_proto/api.proto,sha256=PWLx_gHuGjruhb-x03G619KXkIaoq4973uQvIe6fpcQ,91186
|
157
|
+
modal_proto/api_grpc.py,sha256=9Rs0JyHcz_DSjVKhdtMbDuNt6qDkrE2718KsyA3QL4c,110702
|
158
|
+
modal_proto/api_pb2.py,sha256=UHDLT-LkMVEyTR-uHxMMenpGhtuVVRwPLYnAj9lXMy0,321651
|
159
|
+
modal_proto/api_pb2.pyi,sha256=ufI-SQmXNkrjw_jDNv6un28ihwZzBnhoctmEmRCGHKo,438025
|
160
|
+
modal_proto/api_pb2_grpc.py,sha256=olXvs6OQvy7pqvHP9bkSWC_DdIv0iO38xRlmkLo-ai8,239213
|
161
|
+
modal_proto/api_pb2_grpc.pyi,sha256=ybhcN2nwFBIPd4Z4kkMOv-M8Ejidz93Bl4zScLpYcK0,55706
|
162
|
+
modal_proto/modal_api_grpc.py,sha256=43ujbC_a8YAjuhtEvS-O-5lNpkG5d0K0ZIlryJ4weT4,14766
|
163
163
|
modal_proto/modal_options_grpc.py,sha256=qJ1cuwA54oRqrdTyPTbvfhFZYd9HhJKK5UCwt523r3Y,120
|
164
164
|
modal_proto/options.proto,sha256=a-siq4swVbZPfaFRXAipRZzGP2bq8OsdUvjlyzAeodQ,488
|
165
165
|
modal_proto/options_grpc.py,sha256=M18X3d-8F_cNYSVM3I25dUTO5rZ0rd-vCCfynfh13Nc,125
|
@@ -170,10 +170,10 @@ modal_proto/options_pb2_grpc.pyi,sha256=CImmhxHsYnF09iENPoe8S4J-n93jtgUYD2JPAc0y
|
|
170
170
|
modal_proto/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
171
171
|
modal_version/__init__.py,sha256=wiJQ53c-OMs0Xf1UeXOxQ7FwlV1VzIjnX6o-pRYZ_Pk,470
|
172
172
|
modal_version/__main__.py,sha256=2FO0yYQQwDTh6udt1h-cBnGd1c4ZyHnHSI4BksxzVac,105
|
173
|
-
modal_version/_version_generated.py,sha256=
|
174
|
-
modal-0.73.
|
175
|
-
modal-0.73.
|
176
|
-
modal-0.73.
|
177
|
-
modal-0.73.
|
178
|
-
modal-0.73.
|
179
|
-
modal-0.73.
|
173
|
+
modal_version/_version_generated.py,sha256=KZXRsCy2OlLht4bWbBOqRjtFexrC-QH_9Lv8oc7DDgk,150
|
174
|
+
modal-0.73.151.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
|
175
|
+
modal-0.73.151.dist-info/METADATA,sha256=bzJWJmO2ve_UUdSaJsHNlIvML36c8NQ1PQ2mZFvvlz0,2453
|
176
|
+
modal-0.73.151.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
|
177
|
+
modal-0.73.151.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
|
178
|
+
modal-0.73.151.dist-info/top_level.txt,sha256=4BWzoKYREKUZ5iyPzZpjqx4G8uB5TWxXPDwibLcVa7k,43
|
179
|
+
modal-0.73.151.dist-info/RECORD,,
|
modal_proto/api.proto
CHANGED
@@ -1308,7 +1308,7 @@ message Function {
|
|
1308
1308
|
bool _experimental_enable_gpu_snapshot = 78; // Experimental support for GPU snapshotting
|
1309
1309
|
|
1310
1310
|
AutoscalerSettings autoscaler_settings = 79; // Bundle of parameters related to autoscaling
|
1311
|
-
|
1311
|
+
FunctionSchema function_schema = 80;
|
1312
1312
|
}
|
1313
1313
|
|
1314
1314
|
message FunctionAsyncInvokeRequest {
|
@@ -1457,7 +1457,7 @@ message FunctionData {
|
|
1457
1457
|
bool runtime_perf_record = 29; // For internal debugging use only.
|
1458
1458
|
|
1459
1459
|
AutoscalerSettings autoscaler_settings = 31; // Bundle of parameters related to autoscaling
|
1460
|
-
|
1460
|
+
FunctionSchema function_schema = 32;
|
1461
1461
|
}
|
1462
1462
|
|
1463
1463
|
message FunctionExtended {
|
@@ -1591,6 +1591,7 @@ message FunctionHandleMetadata {
|
|
1591
1591
|
ClassParameterInfo class_parameter_info = 43;
|
1592
1592
|
// Mapping of method names to their metadata, only non-empty for class service functions
|
1593
1593
|
map<string, FunctionHandleMetadata> method_handle_metadata = 44;
|
1594
|
+
FunctionSchema function_schema = 45;
|
1594
1595
|
}
|
1595
1596
|
|
1596
1597
|
message FunctionInput {
|
@@ -1647,6 +1648,7 @@ message FunctionPrecreateRequest {
|
|
1647
1648
|
string use_method_name = 7; // for class methods - this method name needs to be included in the FunctionInput
|
1648
1649
|
// Mapping of method names to method definitions, only non-empty for class service functions
|
1649
1650
|
map<string, MethodDefinition> method_definitions = 8;
|
1651
|
+
FunctionSchema function_schema = 9;
|
1650
1652
|
}
|
1651
1653
|
|
1652
1654
|
message FunctionPrecreateResponse {
|
@@ -1712,6 +1714,16 @@ message FunctionRetryPolicy {
|
|
1712
1714
|
uint32 retries = 18;
|
1713
1715
|
}
|
1714
1716
|
|
1717
|
+
message FunctionSchema {
|
1718
|
+
enum FunctionSchemaType {
|
1719
|
+
FUNCTION_SCHEMA_UNSPECIFIED = 0;
|
1720
|
+
FUNCTION_SCHEMA_V1 = 1;
|
1721
|
+
}
|
1722
|
+
FunctionSchemaType schema_type = 1; // allows easy disambiguation between empty schema and no schema collection etc.
|
1723
|
+
repeated ClassParameterSpec arguments = 2;
|
1724
|
+
GenericPayloadType return_type = 3;
|
1725
|
+
}
|
1726
|
+
|
1715
1727
|
message FunctionStats {
|
1716
1728
|
uint32 backlog = 1;
|
1717
1729
|
uint32 num_total_tasks = 3;
|
@@ -1891,6 +1903,7 @@ message MethodDefinition {
|
|
1891
1903
|
string web_url = 4;
|
1892
1904
|
WebUrlInfo web_url_info = 5;
|
1893
1905
|
repeated CustomDomainInfo custom_domain_info = 6;
|
1906
|
+
FunctionSchema function_schema = 7;
|
1894
1907
|
}
|
1895
1908
|
|
1896
1909
|
message MountFile {
|
@@ -2879,6 +2892,71 @@ message VolumeMount {
|
|
2879
2892
|
bool read_only = 4;
|
2880
2893
|
}
|
2881
2894
|
|
2895
|
+
message VolumePutFiles2Request {
|
2896
|
+
// List of files, sorted lexicographically by `path`.
|
2897
|
+
repeated File files = 1;
|
2898
|
+
|
2899
|
+
// The last time the client called `VolumePutFiles2` for this file, it was
|
2900
|
+
// told that some blocks were missing. This field contains information
|
2901
|
+
// about the client having uploaded those missing blocks.
|
2902
|
+
repeated NewBlock new_blocks = 2;
|
2903
|
+
|
2904
|
+
// If set to true, prevent overwriting existing files. (Note that we don't
|
2905
|
+
// allow overwriting existing directories with uploaded files regardless.)
|
2906
|
+
bool disallow_overwrite_existing_files = 3;
|
2907
|
+
|
2908
|
+
message File {
|
2909
|
+
// Destination path of the file to be uploaded, including any parent dirs
|
2910
|
+
// etc.; for example "foo/bar/baz.txt"
|
2911
|
+
string path = 1;
|
2912
|
+
|
2913
|
+
// The total size of the file, in bytes.
|
2914
|
+
uint64 size = 2;
|
2915
|
+
|
2916
|
+
// SHA-256 checksum of each 8MiB block of the file's contents, in binary
|
2917
|
+
// (ie 32 raw bytes) format for compactness.
|
2918
|
+
repeated bytes blocks_sha256 = 3;
|
2919
|
+
}
|
2920
|
+
|
2921
|
+
message NewBlock {
|
2922
|
+
// Index of the file in the `files` field.
|
2923
|
+
uint64 file_index = 1;
|
2924
|
+
|
2925
|
+
// The index of the block in `files[file_index].blocks_sha256`.
|
2926
|
+
uint64 block_index = 2;
|
2927
|
+
|
2928
|
+
// The raw bytes of the body that was returned from the HTTP PUT request
|
2929
|
+
// when the client made a request for the `put_url` returned in the
|
2930
|
+
// previous `VolumePutFiles2Response`.
|
2931
|
+
bytes put_response = 3;
|
2932
|
+
}
|
2933
|
+
}
|
2934
|
+
|
2935
|
+
message VolumePutFiles2Response {
|
2936
|
+
// Blocks that are currently missing in the volume, because the file did not
|
2937
|
+
// exist, or because the block checksum from `blocks_sha256` in the request
|
2938
|
+
// did not match the current contents of the file.
|
2939
|
+
//
|
2940
|
+
// Values will be returned sorted by `(file_index, block_index)`.
|
2941
|
+
//
|
2942
|
+
// If this field is empty, it means that the files were uploaded successfully
|
2943
|
+
// and/or that the request was an idempotent no-op.
|
2944
|
+
repeated MissingBlock missing_blocks = 1;
|
2945
|
+
|
2946
|
+
message MissingBlock {
|
2947
|
+
// Index of the file in the original `files` field of the request.
|
2948
|
+
uint64 file_index = 1;
|
2949
|
+
|
2950
|
+
// The index of the block in the original
|
2951
|
+
// `files[file_index].blocks_sha256`.
|
2952
|
+
uint64 block_index = 2;
|
2953
|
+
|
2954
|
+
// Make a HTTP PUT request to this endpoint with the blocks' contents as
|
2955
|
+
// the body.
|
2956
|
+
string put_url = 3;
|
2957
|
+
}
|
2958
|
+
}
|
2959
|
+
|
2882
2960
|
message VolumePutFilesRequest {
|
2883
2961
|
string volume_id = 1;
|
2884
2962
|
// TODO(staffan): This is obviously unfortunately named, but provides what we need - consider renaming.
|
@@ -3120,6 +3198,7 @@ service ModalClient {
|
|
3120
3198
|
rpc VolumeList(VolumeListRequest) returns (VolumeListResponse);
|
3121
3199
|
rpc VolumeListFiles(VolumeListFilesRequest) returns (stream VolumeListFilesResponse);
|
3122
3200
|
rpc VolumePutFiles(VolumePutFilesRequest) returns (google.protobuf.Empty);
|
3201
|
+
rpc VolumePutFiles2(VolumePutFiles2Request) returns (VolumePutFiles2Response);
|
3123
3202
|
rpc VolumeReload(VolumeReloadRequest) returns (google.protobuf.Empty);
|
3124
3203
|
rpc VolumeRemoveFile(VolumeRemoveFileRequest) returns (google.protobuf.Empty);
|
3125
3204
|
rpc VolumeRename(VolumeRenameRequest) returns (google.protobuf.Empty);
|
modal_proto/api_grpc.py
CHANGED
@@ -574,6 +574,10 @@ class ModalClientBase(abc.ABC):
|
|
574
574
|
async def VolumePutFiles(self, stream: 'grpclib.server.Stream[modal_proto.api_pb2.VolumePutFilesRequest, google.protobuf.empty_pb2.Empty]') -> None:
|
575
575
|
pass
|
576
576
|
|
577
|
+
@abc.abstractmethod
|
578
|
+
async def VolumePutFiles2(self, stream: 'grpclib.server.Stream[modal_proto.api_pb2.VolumePutFiles2Request, modal_proto.api_pb2.VolumePutFiles2Response]') -> None:
|
579
|
+
pass
|
580
|
+
|
577
581
|
@abc.abstractmethod
|
578
582
|
async def VolumeReload(self, stream: 'grpclib.server.Stream[modal_proto.api_pb2.VolumeReloadRequest, google.protobuf.empty_pb2.Empty]') -> None:
|
579
583
|
pass
|
@@ -1426,6 +1430,12 @@ class ModalClientBase(abc.ABC):
|
|
1426
1430
|
modal_proto.api_pb2.VolumePutFilesRequest,
|
1427
1431
|
google.protobuf.empty_pb2.Empty,
|
1428
1432
|
),
|
1433
|
+
'/modal.client.ModalClient/VolumePutFiles2': grpclib.const.Handler(
|
1434
|
+
self.VolumePutFiles2,
|
1435
|
+
grpclib.const.Cardinality.UNARY_UNARY,
|
1436
|
+
modal_proto.api_pb2.VolumePutFiles2Request,
|
1437
|
+
modal_proto.api_pb2.VolumePutFiles2Response,
|
1438
|
+
),
|
1429
1439
|
'/modal.client.ModalClient/VolumeReload': grpclib.const.Handler(
|
1430
1440
|
self.VolumeReload,
|
1431
1441
|
grpclib.const.Cardinality.UNARY_UNARY,
|
@@ -2290,6 +2300,12 @@ class ModalClientStub:
|
|
2290
2300
|
modal_proto.api_pb2.VolumePutFilesRequest,
|
2291
2301
|
google.protobuf.empty_pb2.Empty,
|
2292
2302
|
)
|
2303
|
+
self.VolumePutFiles2 = grpclib.client.UnaryUnaryMethod(
|
2304
|
+
channel,
|
2305
|
+
'/modal.client.ModalClient/VolumePutFiles2',
|
2306
|
+
modal_proto.api_pb2.VolumePutFiles2Request,
|
2307
|
+
modal_proto.api_pb2.VolumePutFiles2Response,
|
2308
|
+
)
|
2293
2309
|
self.VolumeReload = grpclib.client.UnaryUnaryMethod(
|
2294
2310
|
channel,
|
2295
2311
|
'/modal.client.ModalClient/VolumeReload',
|