modal 0.73.169__py3-none-any.whl → 0.73.170__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/cli/run.py CHANGED
@@ -7,9 +7,10 @@ import re
7
7
  import shlex
8
8
  import sys
9
9
  import time
10
+ import typing
10
11
  from dataclasses import dataclass
11
12
  from functools import partial
12
- from typing import Any, Callable, Optional, get_type_hints
13
+ from typing import Any, Callable, Optional
13
14
 
14
15
  import click
15
16
  import typer
@@ -18,6 +19,7 @@ from typing_extensions import TypedDict
18
19
 
19
20
  from .._functions import _FunctionSpec
20
21
  from ..app import App, LocalEntrypoint
22
+ from ..cls import _get_class_constructor_signature
21
23
  from ..config import config
22
24
  from ..environments import ensure_env
23
25
  from ..exception import ExecutionError, InvalidError, _CliUserExecutionError
@@ -42,7 +44,7 @@ class ParameterMetadata(TypedDict):
42
44
  name: str
43
45
  default: Any
44
46
  annotation: Any
45
- type_hint: Any
47
+ type_hint: Any # same as annotation but evaluated by typing.get_type_hints
46
48
  kind: Any
47
49
 
48
50
 
@@ -68,27 +70,24 @@ class NoParserAvailable(InvalidError):
68
70
 
69
71
 
70
72
  @dataclass
71
- class FnSignature:
73
+ class CliRunnableSignature:
72
74
  parameters: dict[str, ParameterMetadata]
73
75
  has_variadic_args: bool
74
76
 
75
77
 
76
- def _get_signature(f: Callable[..., Any], is_method: bool = False) -> FnSignature:
78
+ def safe_get_type_hints(func_or_cls: typing.Union[Callable[..., Any], type]) -> dict[str, type]:
77
79
  try:
78
- type_hints = get_type_hints(f)
80
+ return typing.get_type_hints(func_or_cls)
79
81
  except Exception as exc:
80
82
  # E.g., if entrypoint type hints cannot be evaluated by local Python runtime
81
- msg = "Unable to generate command line interface for app entrypoint. See traceback above for details."
83
+ msg = "Unable to generate command line interface for app entrypoint due to unparseable type hints:\n" + str(exc)
82
84
  raise ExecutionError(msg) from exc
83
85
 
84
- has_variadic_args = False
85
-
86
- if is_method:
87
- self = None # Dummy, doesn't matter
88
- f = functools.partial(f, self)
89
86
 
87
+ def _get_cli_runnable_signature(sig: inspect.Signature, type_hints: dict[str, type]) -> CliRunnableSignature:
88
+ has_variadic_args = False
90
89
  signature: dict[str, ParameterMetadata] = {}
91
- for param in inspect.signature(f).parameters.values():
90
+ for param in sig.parameters.values():
92
91
  if param.kind == inspect.Parameter.VAR_POSITIONAL:
93
92
  has_variadic_args = True
94
93
  else:
@@ -103,7 +102,7 @@ def _get_signature(f: Callable[..., Any], is_method: bool = False) -> FnSignatur
103
102
  if has_variadic_args and len(signature) > 0:
104
103
  raise InvalidError("Functions with variable-length positional arguments (*args) cannot have other parameters.")
105
104
 
106
- return FnSignature(signature, has_variadic_args)
105
+ return CliRunnableSignature(signature, has_variadic_args)
107
106
 
108
107
 
109
108
  def _get_param_type_as_str(annot: Any) -> str:
@@ -172,7 +171,7 @@ def _write_local_result(result_path: str, res: Any):
172
171
  fid.write(res)
173
172
 
174
173
 
175
- def _make_click_function(app, signature: FnSignature, inner: Callable[[tuple[str, ...], dict[str, Any]], Any]):
174
+ def _make_click_function(app, signature: CliRunnableSignature, inner: Callable[[tuple[str, ...], dict[str, Any]], Any]):
176
175
  @click.pass_context
177
176
  def f(ctx, **kwargs):
178
177
  if signature.has_variadic_args:
@@ -201,7 +200,9 @@ def _get_click_command_for_function(app: App, function: Function):
201
200
  if function.is_generator:
202
201
  raise InvalidError("`modal run` is not supported for generator functions")
203
202
 
204
- signature = _get_signature(function.info.raw_f)
203
+ sig: inspect.Signature = inspect.signature(function.info.raw_f)
204
+ type_hints = safe_get_type_hints(function.info.raw_f)
205
+ signature: CliRunnableSignature = _get_cli_runnable_signature(sig, type_hints)
205
206
 
206
207
  def _inner(args, click_kwargs):
207
208
  return function.remote(*args, **click_kwargs)
@@ -223,7 +224,10 @@ def _get_click_command_for_cls(app: App, method_ref: MethodReference):
223
224
  cls = method_ref.cls
224
225
  method_name = method_ref.method_name
225
226
 
226
- cls_signature = _get_signature(cls._get_user_cls())
227
+ user_cls = cls._get_user_cls()
228
+ type_hints = safe_get_type_hints(user_cls)
229
+ sig: inspect.Signature = _get_class_constructor_signature(user_cls)
230
+ cls_signature: CliRunnableSignature = _get_cli_runnable_signature(sig, type_hints)
227
231
 
228
232
  if cls_signature.has_variadic_args:
229
233
  raise InvalidError("Modal classes cannot have variable-length positional arguments (*args).")
@@ -241,7 +245,9 @@ def _get_click_command_for_cls(app: App, method_ref: MethodReference):
241
245
  )
242
246
 
243
247
  partial_function = partial_functions[method_name]
244
- fun_signature = _get_signature(partial_function._get_raw_f(), is_method=True)
248
+ raw_f = partial_function._get_raw_f()
249
+ sig_without_self = inspect.signature(functools.partial(raw_f, None))
250
+ fun_signature = _get_cli_runnable_signature(sig_without_self, safe_get_type_hints(raw_f))
245
251
 
246
252
  # TODO(erikbern): assert there's no overlap?
247
253
  parameters = dict(**cls_signature.parameters, **fun_signature.parameters) # Pool all arguments
@@ -271,7 +277,7 @@ def _get_click_command_for_local_entrypoint(app: App, entrypoint: LocalEntrypoin
271
277
  func = entrypoint.info.raw_f
272
278
  isasync = inspect.iscoroutinefunction(func)
273
279
 
274
- signature = _get_signature(func)
280
+ signature = _get_cli_runnable_signature(inspect.signature(func), safe_get_type_hints(func))
275
281
 
276
282
  @click.pass_context
277
283
  def f(ctx, *args, **kwargs):
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.169",
34
+ version: str = "0.73.170",
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.169",
96
+ version: str = "0.73.170",
97
97
  ): ...
98
98
  def is_closed(self) -> bool: ...
99
99
  @property
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modal
3
- Version: 0.73.169
3
+ Version: 0.73.170
4
4
  Summary: Python client library for Modal
5
5
  Author-email: Modal Labs <support@modal.com>
6
6
  License: Apache-2.0
@@ -22,7 +22,7 @@ modal/app.py,sha256=bJp7W3liuVG2VwWkG31tMFogDh84EKppzP8YJFWl3eQ,48140
22
22
  modal/app.pyi,sha256=SkqXNrdnGIZ4MmNNvpGtzNLoUdyuvi9IjQQR_DRiRHk,26968
23
23
  modal/call_graph.py,sha256=1g2DGcMIJvRy-xKicuf63IVE98gJSnQsr8R_NVMptNc,2581
24
24
  modal/client.py,sha256=U-YKSw0n7J1ZLREt9cbEJCtmHe5YoPKFxl0xlkan2yc,15565
25
- modal/client.pyi,sha256=OPhN2duy3E59Cd0XH_KxhMf2Asehk37vBruSo_mJEZ8,7661
25
+ modal/client.pyi,sha256=KBxA9Giwan5u4NmHsSuD_dQ8XlWfKL5syIR70BuLbOA,7661
26
26
  modal/cloud_bucket_mount.py,sha256=YOe9nnvSr4ZbeCn587d7_VhE9IioZYRvF9VYQTQux08,5914
27
27
  modal/cloud_bucket_mount.pyi,sha256=30T3K1a89l6wzmEJ_J9iWv9SknoGqaZDx59Xs-ZQcmk,1607
28
28
  modal/cls.py,sha256=x3CUDPC-QK7pa9E2eiFsiCS2ULvVi8UzNZQw1i9drsU,32945
@@ -128,7 +128,7 @@ modal/cli/launch.py,sha256=0_sBu6bv2xJEPWi-rbGS6Ri9ggnkWQvrGlgpYSUBMyY,3097
128
128
  modal/cli/network_file_system.py,sha256=eq3JnwjbfFNsJodIyANHL06ByYc3BSavzdmu8C96cHA,7948
129
129
  modal/cli/profile.py,sha256=0TYhgRSGUvQZ5LH9nkl6iZllEvAjDniES264dE57wOM,3201
130
130
  modal/cli/queues.py,sha256=6gTu76dzBtPN5eQVsLrvQpuru5jI9ZCWK5Eh8J8XhaM,4498
131
- modal/cli/run.py,sha256=v1_yj6fJ-W8hPi3z5tHsogsXjtuvwjnjV-EjTIJqXr8,22947
131
+ modal/cli/run.py,sha256=NX2wWwj8HD6XUhnZRF808Qy9eeouv8KnvyOP57HqIXI,23637
132
132
  modal/cli/secret.py,sha256=WB_c-LE9-eDqleLpJxsJ9rZw62Eeza8ZFQFR10vNMEk,4197
133
133
  modal/cli/token.py,sha256=mxSgOWakXG6N71hQb1ko61XAR9ZGkTMZD-Txn7gmTac,1924
134
134
  modal/cli/utils.py,sha256=hZmjyzcPjDnQSkLvycZD2LhGdcsfdZshs_rOU78EpvI,3717
@@ -145,7 +145,7 @@ modal/requirements/2024.10.txt,sha256=qD-5cVIVM9wXesJ6JC89Ew-3m2KjEElUz3jaw_MddR
145
145
  modal/requirements/PREVIEW.txt,sha256=qD-5cVIVM9wXesJ6JC89Ew-3m2KjEElUz3jaw_MddRo,296
146
146
  modal/requirements/README.md,sha256=9tK76KP0Uph7O0M5oUgsSwEZDj5y-dcUPsnpR0Sc-Ik,854
147
147
  modal/requirements/base-images.json,sha256=57vMSqzMbLBxw5tFWSaMiIkkVEps4JfX5PAtXGnkS4U,740
148
- modal-0.73.169.dist-info/licenses/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
148
+ modal-0.73.170.dist-info/licenses/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
149
149
  modal_docs/__init__.py,sha256=svYKtV8HDwDCN86zbdWqyq5T8sMdGDj0PVlzc2tIxDM,28
150
150
  modal_docs/gen_cli_docs.py,sha256=c1yfBS_x--gL5bs0N4ihMwqwX8l3IBWSkBAKNNIi6bQ,3801
151
151
  modal_docs/gen_reference_docs.py,sha256=cvTgltucqYLLIX84QxAwf51Z5Vc2n6cLxS8VcrxNCAo,6401
@@ -170,9 +170,9 @@ 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=K1I-OHoqF3Qf9hN8YD8e7nCzAieLwZ3R8l4ov209qJs,150
174
- modal-0.73.169.dist-info/METADATA,sha256=1QhcQPji6dqJkEd3YfibNbEuaI5JLzZAsF9LmPZ8FFQ,2475
175
- modal-0.73.169.dist-info/WHEEL,sha256=1tXe9gY0PYatrMPMDd6jXqjfpz_B-Wqm32CPfRC58XU,91
176
- modal-0.73.169.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
177
- modal-0.73.169.dist-info/top_level.txt,sha256=4BWzoKYREKUZ5iyPzZpjqx4G8uB5TWxXPDwibLcVa7k,43
178
- modal-0.73.169.dist-info/RECORD,,
173
+ modal_version/_version_generated.py,sha256=uAuYxu7DBPrzw4Kuc3Hd44Hu_fSVZZC0e5kkTME2oz0,150
174
+ modal-0.73.170.dist-info/METADATA,sha256=2ImlbrU1H3oX54VF9Ocmrbe90XCzqZezDpcHbPWPdEo,2475
175
+ modal-0.73.170.dist-info/WHEEL,sha256=1tXe9gY0PYatrMPMDd6jXqjfpz_B-Wqm32CPfRC58XU,91
176
+ modal-0.73.170.dist-info/entry_points.txt,sha256=An-wYgeEUnm6xzrAP9_NTSTSciYvvEWsMZILtYrvpAI,46
177
+ modal-0.73.170.dist-info/top_level.txt,sha256=4BWzoKYREKUZ5iyPzZpjqx4G8uB5TWxXPDwibLcVa7k,43
178
+ modal-0.73.170.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  # Copyright Modal Labs 2025
2
2
 
3
3
  # Note: Reset this value to -1 whenever you make a minor `0.X` release of the client.
4
- build_number = 169 # git: 4137d51
4
+ build_number = 170 # git: b0e5f86