modal 0.73.150__py3-none-any.whl → 0.73.152__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 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
- function_definition: Optional[api_pb2.Function] = None
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.150",
34
+ version: str = "0.73.152",
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.150",
96
+ version: str = "0.73.152",
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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: modal
3
- Version: 0.73.150
3
+ Version: 0.73.152
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -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=nUyiCOYcuY_jXJhY5-haHFIUQleCmjh8z6GgXgo5MRY,73556
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=SQMKtmjvjOLM6ErxTboeJiW970LySqjxDWk0humBR1U,21939
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=7uZv9uWQf4FIvAK5rTuUNBrYYa2l_S-nGgvxH6ttlVI,7661
26
+ modal/client.pyi,sha256=TRrXBJ1tKWb__uvy2-rwSu43guCKdMsjiJIECpeDCdQ,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=6MZYzhOcsCG7uWKk_zv_Q7fDcn5dkmK0M4QVRrpfF3Q,31769
30
- modal/cls.pyi,sha256=ZJUwtRaQBGlM6tphvnv49FHBVDSgttMdD_LnYyRSKJM,10302
31
- modal/config.py,sha256=Zx7YsllgIJzMRKeIkaGSLLtMFV4kTUvGxpptnmqlP1U,11623
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=0Au1n37DimTZVvxCIR7HWALuNGxfJ_fcNR-or37eo5k,14438
43
+ modal/functions.pyi,sha256=Bg_zlYSHMYuEXQYLcFU-j1Kwq5zHQ9jggMA_5ZO_du8,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,10 +153,10 @@ 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=KLgOS8GclVSbeNOJcxC2Vyzbns2BHt9AdvQrXBEltvA,90668
156
+ modal_proto/api.proto,sha256=N53PcynS8Lue5GnrYdcqlgzSMayAD4kiV-iLvgqECP8,91004
157
157
  modal_proto/api_grpc.py,sha256=9Rs0JyHcz_DSjVKhdtMbDuNt6qDkrE2718KsyA3QL4c,110702
158
- modal_proto/api_pb2.py,sha256=rl4rGn-Q_AS-Kn_F_T3df0_Lx2rvJMajdcpTkewJ0Ag,320170
159
- modal_proto/api_pb2.pyi,sha256=QLmFaTak-GwdKUhGQGk-DudI3cV7PdluTWSnvxlgobo,434662
158
+ modal_proto/api_pb2.py,sha256=CqY-OvOubZmM74rgT0dAeBCGkLvjUn9RKV1U_9ucuK0,321579
159
+ modal_proto/api_pb2.pyi,sha256=eUasABRN3TFeeesNKAdH1eWwk4jOce_Zc633LUinavY,437780
160
160
  modal_proto/api_pb2_grpc.py,sha256=olXvs6OQvy7pqvHP9bkSWC_DdIv0iO38xRlmkLo-ai8,239213
161
161
  modal_proto/api_pb2_grpc.pyi,sha256=ybhcN2nwFBIPd4Z4kkMOv-M8Ejidz93Bl4zScLpYcK0,55706
162
162
  modal_proto/modal_api_grpc.py,sha256=43ujbC_a8YAjuhtEvS-O-5lNpkG5d0K0ZIlryJ4weT4,14766
@@ -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=b_9tYBKQ8OVORw51ouAMn3uT9_gfkq2Vrg3B7PU_BQw,150
174
- modal-0.73.150.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
175
- modal-0.73.150.dist-info/METADATA,sha256=ePf8YfB9Bp8xAIz5Mjv9GwuZpwsQnBC_wnNqL3u-AY8,2453
176
- modal-0.73.150.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
177
- modal-0.73.150.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
178
- modal-0.73.150.dist-info/top_level.txt,sha256=4BWzoKYREKUZ5iyPzZpjqx4G8uB5TWxXPDwibLcVa7k,43
179
- modal-0.73.150.dist-info/RECORD,,
173
+ modal_version/_version_generated.py,sha256=ciOdTKcT9aMFmuPOVpqzfwEYkTVr5C0lQk4__he_oB8,150
174
+ modal-0.73.152.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
175
+ modal-0.73.152.dist-info/METADATA,sha256=uB-4bcV49TVPAV-c6QD7iVfnwrUu91e0Qdg4f6xKddI,2453
176
+ modal-0.73.152.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
177
+ modal-0.73.152.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
178
+ modal-0.73.152.dist-info/top_level.txt,sha256=4BWzoKYREKUZ5iyPzZpjqx4G8uB5TWxXPDwibLcVa7k,43
179
+ modal-0.73.152.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 {
@@ -2880,17 +2893,12 @@ message VolumeMount {
2880
2893
  }
2881
2894
 
2882
2895
  message VolumePutFiles2Request {
2883
- // List of files, sorted lexicographically by `path`.
2896
+ // List of files to put/upload.
2884
2897
  repeated File files = 1;
2885
2898
 
2886
- // The last time the client called `VolumePutFiles2` for this file, it was
2887
- // told that some blocks were missing. This field contains information
2888
- // about the client having uploaded those missing blocks.
2889
- repeated NewBlock new_blocks = 2;
2890
-
2891
2899
  // If set to true, prevent overwriting existing files. (Note that we don't
2892
2900
  // allow overwriting existing directories with uploaded files regardless.)
2893
- bool disallow_overwrite_existing_files = 3;
2901
+ bool disallow_overwrite_existing_files = 2;
2894
2902
 
2895
2903
  message File {
2896
2904
  // Destination path of the file to be uploaded, including any parent dirs
@@ -2900,22 +2908,22 @@ message VolumePutFiles2Request {
2900
2908
  // The total size of the file, in bytes.
2901
2909
  uint64 size = 2;
2902
2910
 
2903
- // SHA-256 checksum of each 8MiB block of the file's contents, in binary
2904
- // (ie 32 raw bytes) format for compactness.
2905
- repeated bytes blocks_sha256 = 3;
2911
+ // The blocks, in units of 8MiB, that this file consists of.
2912
+ repeated Block blocks = 3;
2906
2913
  }
2907
2914
 
2908
- message NewBlock {
2909
- // Index of the file in the `files` field.
2910
- uint64 file_index = 1;
2911
-
2912
- // The index of the block in `files[file_index].blocks_sha256`.
2913
- uint64 block_index = 2;
2914
-
2915
- // The raw bytes of the body that was returned from the HTTP PUT request
2916
- // when the client made a request for the `put_url` returned in the
2917
- // previous `VolumePutFiles2Response`.
2918
- bytes put_response = 3;
2915
+ message Block {
2916
+ // The SHA256 digest of the contents of this block, in raw (ie. 32 bytes)
2917
+ // form for compactness.
2918
+ bytes contents_sha256 = 1;
2919
+
2920
+ // From a previous call to `VolumePutFiles2`, we might have gotten a
2921
+ // response indicating that this block was missing.
2922
+ //
2923
+ // For such a block, this field contains the raw bytes of the body that
2924
+ // was returned from the HTTP PUT request when the client made a request
2925
+ // for the `put_url` returned in the previous `VolumePutFiles2Response`.
2926
+ optional bytes put_response = 2;
2919
2927
  }
2920
2928
  }
2921
2929
 
@@ -2934,8 +2942,8 @@ message VolumePutFiles2Response {
2934
2942
  // Index of the file in the original `files` field of the request.
2935
2943
  uint64 file_index = 1;
2936
2944
 
2937
- // The index of the block in the original
2938
- // `files[file_index].blocks_sha256`.
2945
+ // The index of the block in the original `files[file_index].blocks` of the
2946
+ // request.
2939
2947
  uint64 block_index = 2;
2940
2948
 
2941
2949
  // Make a HTTP PUT request to this endpoint with the blocks' contents as