modal 0.68.37__py3-none-any.whl → 0.68.39__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/_traceback.py CHANGED
@@ -74,11 +74,15 @@ def append_modal_tb(exc: BaseException, tb_dict: TBDictType, line_cache: LineCac
74
74
 
75
75
  def reduce_traceback_to_user_code(tb: Optional[TracebackType], user_source: str) -> TracebackType:
76
76
  """Return a traceback that does not contain modal entrypoint or synchronicity frames."""
77
- # Step forward all the way through the traceback and drop any synchronicity frames
77
+
78
+ # Step forward all the way through the traceback and drop any "Modal support" frames
79
+ def skip_frame(filename: str) -> bool:
80
+ return "/site-packages/synchronicity/" in filename or "modal/_utils/deprecation" in filename
81
+
78
82
  tb_root = tb
79
83
  while tb is not None:
80
84
  while tb.tb_next is not None:
81
- if "/site-packages/synchronicity/" in tb.tb_next.tb_frame.f_code.co_filename:
85
+ if skip_frame(tb.tb_next.tb_frame.f_code.co_filename):
82
86
  tb.tb_next = tb.tb_next.tb_next
83
87
  else:
84
88
  break
@@ -1,7 +1,11 @@
1
1
  # Copyright Modal Labs 2024
2
+ import functools
2
3
  import sys
3
4
  import warnings
4
5
  from datetime import date
6
+ from typing import Any, Callable, TypeVar
7
+
8
+ from typing_extensions import ParamSpec # Needed for Python 3.9
5
9
 
6
10
  from ..exception import DeprecationError, PendingDeprecationError
7
11
 
@@ -42,3 +46,44 @@ def deprecation_warning(
42
46
 
43
47
  # This is a lower-level function that warnings.warn uses
44
48
  warnings.warn_explicit(f"{date(*deprecated_on)}: {msg}", warning_cls, filename, lineno)
49
+
50
+
51
+ P = ParamSpec("P")
52
+ R = TypeVar("R")
53
+
54
+
55
+ def renamed_parameter(
56
+ date: tuple[int, int, int],
57
+ old_name: str,
58
+ new_name: str,
59
+ show_source: bool = True,
60
+ ) -> Callable[[Callable[P, R]], Callable[P, R]]:
61
+ """Decorator for semi-gracefully changing a parameter name.
62
+
63
+ Functions wrapped with this decorator can be defined using only the `new_name` of the parameter.
64
+ If the function is invoked with the `old_name`, the wrapper will pass the value as a keyword
65
+ argument for `new_name` and issue a Modal deprecation warning about the change.
66
+
67
+ Note that this only prevents parameter renamings from breaking code at runtime.
68
+ Type checking will fail when code uses `old_name`. To avoid this, the `old_name` can be
69
+ preserved in the function signature with an `Annotated` type hint indicating the renaming.
70
+ """
71
+
72
+ def decorator(func: Callable[P, R]) -> Callable[P, R]:
73
+ @functools.wraps(func)
74
+ def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
75
+ mut_kwargs: dict[str, Any] = locals()["kwargs"] # Avoid referencing kwargs directly due to bug in sigtools
76
+ if old_name in mut_kwargs:
77
+ mut_kwargs[new_name] = mut_kwargs.pop(old_name)
78
+ func_name = func.__qualname__.removeprefix("_") # Avoid confusion when synchronicity-wrapped
79
+ message = (
80
+ f"The '{old_name}' parameter of `{func_name}` has been renamed to '{new_name}'."
81
+ "\nUsing the old name will become an error in a future release. Please update your code."
82
+ )
83
+ deprecation_warning(date, message, show_source=show_source)
84
+
85
+ return func(*args, **kwargs)
86
+
87
+ return wrapper
88
+
89
+ return decorator
modal/app.py CHANGED
@@ -22,7 +22,7 @@ from modal_proto import api_pb2
22
22
 
23
23
  from ._ipython import is_notebook
24
24
  from ._utils.async_utils import synchronize_api
25
- from ._utils.deprecation import deprecation_error, deprecation_warning
25
+ from ._utils.deprecation import deprecation_error, deprecation_warning, renamed_parameter
26
26
  from ._utils.function_utils import FunctionInfo, is_global_object, is_method_fn
27
27
  from ._utils.grpc_utils import retry_transient_errors
28
28
  from ._utils.mount_utils import validate_volumes
@@ -260,8 +260,9 @@ class _App:
260
260
  return self._description
261
261
 
262
262
  @staticmethod
263
+ @renamed_parameter((2024, 12, 18), "label", "name")
263
264
  async def lookup(
264
- label: str,
265
+ name: str,
265
266
  client: Optional[_Client] = None,
266
267
  environment_name: Optional[str] = None,
267
268
  create_if_missing: bool = False,
@@ -283,14 +284,14 @@ class _App:
283
284
  environment_name = _get_environment_name(environment_name)
284
285
 
285
286
  request = api_pb2.AppGetOrCreateRequest(
286
- app_name=label,
287
+ app_name=name,
287
288
  environment_name=environment_name,
288
289
  object_creation_type=(api_pb2.OBJECT_CREATION_TYPE_CREATE_IF_MISSING if create_if_missing else None),
289
290
  )
290
291
 
291
292
  response = await retry_transient_errors(client.stub.AppGetOrCreate, request)
292
293
 
293
- app = _App(label)
294
+ app = _App(name)
294
295
  app._app_id = response.app_id
295
296
  app._client = client
296
297
  app._running_app = RunningApp(
modal/app.pyi CHANGED
@@ -107,7 +107,7 @@ class _App:
107
107
  def description(self) -> typing.Optional[str]: ...
108
108
  @staticmethod
109
109
  async def lookup(
110
- label: str,
110
+ name: str,
111
111
  client: typing.Optional[modal.client._Client] = None,
112
112
  environment_name: typing.Optional[str] = None,
113
113
  create_if_missing: bool = False,
@@ -306,14 +306,14 @@ class App:
306
306
  class __lookup_spec(typing_extensions.Protocol):
307
307
  def __call__(
308
308
  self,
309
- label: str,
309
+ name: str,
310
310
  client: typing.Optional[modal.client.Client] = None,
311
311
  environment_name: typing.Optional[str] = None,
312
312
  create_if_missing: bool = False,
313
313
  ) -> App: ...
314
314
  async def aio(
315
315
  self,
316
- label: str,
316
+ name: str,
317
317
  client: typing.Optional[modal.client.Client] = None,
318
318
  environment_name: typing.Optional[str] = None,
319
319
  create_if_missing: bool = False,
@@ -237,4 +237,4 @@ async def delete(
237
237
  abort=True,
238
238
  )
239
239
 
240
- await _NetworkFileSystem.delete(label=nfs_name, environment_name=env)
240
+ await _NetworkFileSystem.delete(nfs_name, environment_name=env)
modal/cli/volume.py CHANGED
@@ -286,4 +286,4 @@ async def delete(
286
286
  abort=True,
287
287
  )
288
288
 
289
- await _Volume.delete(label=volume_name, environment_name=env)
289
+ await _Volume.delete(volume_name, environment_name=env)
modal/client.pyi CHANGED
@@ -26,7 +26,7 @@ class _Client:
26
26
  _stub: typing.Optional[modal_proto.api_grpc.ModalClientStub]
27
27
 
28
28
  def __init__(
29
- self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.68.37"
29
+ self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.68.39"
30
30
  ): ...
31
31
  def is_closed(self) -> bool: ...
32
32
  @property
@@ -81,7 +81,7 @@ class Client:
81
81
  _stub: typing.Optional[modal_proto.api_grpc.ModalClientStub]
82
82
 
83
83
  def __init__(
84
- self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.68.37"
84
+ self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.68.39"
85
85
  ): ...
86
86
  def is_closed(self) -> bool: ...
87
87
  @property
modal/cls.py CHANGED
@@ -16,6 +16,7 @@ from ._resources import convert_fn_config_to_resources_config
16
16
  from ._serialization import check_valid_cls_constructor_arg
17
17
  from ._traceback import print_server_warnings
18
18
  from ._utils.async_utils import synchronize_api, synchronizer
19
+ from ._utils.deprecation import renamed_parameter
19
20
  from ._utils.grpc_utils import retry_transient_errors
20
21
  from ._utils.mount_utils import validate_volumes
21
22
  from .client import _Client
@@ -513,10 +514,11 @@ class _Cls(_Object, type_prefix="cs"):
513
514
  return self._class_service_function is not None
514
515
 
515
516
  @classmethod
517
+ @renamed_parameter((2024, 12, 18), "tag", "name")
516
518
  def from_name(
517
519
  cls: type["_Cls"],
518
520
  app_name: str,
519
- tag: str,
521
+ name: str,
520
522
  namespace=api_pb2.DEPLOYMENT_NAMESPACE_WORKSPACE,
521
523
  environment_name: Optional[str] = None,
522
524
  workspace: Optional[str] = None,
@@ -528,7 +530,7 @@ class _Cls(_Object, type_prefix="cs"):
528
530
  Modal servers until the first time it is actually used.
529
531
 
530
532
  ```python
531
- Class = modal.Cls.from_name("other-app", "Class")
533
+ Model = modal.Cls.from_name("other-app", "Model")
532
534
  ```
533
535
  """
534
536
 
@@ -536,7 +538,7 @@ class _Cls(_Object, type_prefix="cs"):
536
538
  _environment_name = _get_environment_name(environment_name, resolver)
537
539
  request = api_pb2.ClassGetRequest(
538
540
  app_name=app_name,
539
- object_tag=tag,
541
+ object_tag=name,
540
542
  namespace=namespace,
541
543
  environment_name=_environment_name,
542
544
  lookup_published=workspace is not None,
@@ -555,11 +557,11 @@ class _Cls(_Object, type_prefix="cs"):
555
557
 
556
558
  print_server_warnings(response.server_warnings)
557
559
 
558
- class_function_tag = f"{tag}.*" # special name of the base service function for the class
560
+ class_service_name = f"{name}.*" # special name of the base service function for the class
559
561
 
560
562
  class_service_function = _Function.from_name(
561
563
  app_name,
562
- class_function_tag,
564
+ class_service_name,
563
565
  environment_name=_environment_name,
564
566
  )
565
567
  try:
@@ -635,9 +637,10 @@ class _Cls(_Object, type_prefix="cs"):
635
637
  return cls
636
638
 
637
639
  @staticmethod
640
+ @renamed_parameter((2024, 12, 18), "tag", "name")
638
641
  async def lookup(
639
642
  app_name: str,
640
- tag: str,
643
+ name: str,
641
644
  namespace=api_pb2.DEPLOYMENT_NAMESPACE_WORKSPACE,
642
645
  client: Optional[_Client] = None,
643
646
  environment_name: Optional[str] = None,
@@ -649,11 +652,14 @@ class _Cls(_Object, type_prefix="cs"):
649
652
  that will hydrate the local object with metadata from Modal servers.
650
653
 
651
654
  ```python notest
652
- Class = modal.Cls.lookup("other-app", "Class")
653
- obj = Class()
655
+ Model = modal.Cls.lookup("other-app", "Model")
656
+ model = Model()
657
+ model.inference(...)
654
658
  ```
655
659
  """
656
- obj = _Cls.from_name(app_name, tag, namespace=namespace, environment_name=environment_name, workspace=workspace)
660
+ obj = _Cls.from_name(
661
+ app_name, name, namespace=namespace, environment_name=environment_name, workspace=workspace
662
+ )
657
663
  if client is None:
658
664
  client = await _Client.from_env()
659
665
  resolver = Resolver(client=client)
modal/cls.pyi CHANGED
@@ -112,7 +112,7 @@ class _Cls(modal.object._Object):
112
112
  def from_name(
113
113
  cls: type[_Cls],
114
114
  app_name: str,
115
- tag: str,
115
+ name: str,
116
116
  namespace=1,
117
117
  environment_name: typing.Optional[str] = None,
118
118
  workspace: typing.Optional[str] = None,
@@ -133,7 +133,7 @@ class _Cls(modal.object._Object):
133
133
  @staticmethod
134
134
  async def lookup(
135
135
  app_name: str,
136
- tag: str,
136
+ name: str,
137
137
  namespace=1,
138
138
  client: typing.Optional[modal.client._Client] = None,
139
139
  environment_name: typing.Optional[str] = None,
@@ -164,7 +164,7 @@ class Cls(modal.object.Object):
164
164
  def from_name(
165
165
  cls: type[Cls],
166
166
  app_name: str,
167
- tag: str,
167
+ name: str,
168
168
  namespace=1,
169
169
  environment_name: typing.Optional[str] = None,
170
170
  workspace: typing.Optional[str] = None,
@@ -187,7 +187,7 @@ class Cls(modal.object.Object):
187
187
  def __call__(
188
188
  self,
189
189
  app_name: str,
190
- tag: str,
190
+ name: str,
191
191
  namespace=1,
192
192
  client: typing.Optional[modal.client.Client] = None,
193
193
  environment_name: typing.Optional[str] = None,
@@ -196,7 +196,7 @@ class Cls(modal.object.Object):
196
196
  async def aio(
197
197
  self,
198
198
  app_name: str,
199
- tag: str,
199
+ name: str,
200
200
  namespace=1,
201
201
  client: typing.Optional[modal.client.Client] = None,
202
202
  environment_name: typing.Optional[str] = None,
modal/dict.py CHANGED
@@ -10,7 +10,7 @@ from modal_proto import api_pb2
10
10
  from ._resolver import Resolver
11
11
  from ._serialization import deserialize, serialize
12
12
  from ._utils.async_utils import TaskContext, synchronize_api
13
- from ._utils.deprecation import deprecation_error
13
+ from ._utils.deprecation import deprecation_error, renamed_parameter
14
14
  from ._utils.grpc_utils import retry_transient_errors
15
15
  from ._utils.name_utils import check_object_name
16
16
  from .client import _Client
@@ -112,8 +112,9 @@ class _Dict(_Object, type_prefix="di"):
112
112
  yield cls._new_hydrated(response.dict_id, client, None, is_another_app=True)
113
113
 
114
114
  @staticmethod
115
+ @renamed_parameter((2024, 12, 18), "label", "name")
115
116
  def from_name(
116
- label: str,
117
+ name: str,
117
118
  data: Optional[dict] = None,
118
119
  namespace=api_pb2.DEPLOYMENT_NAMESPACE_WORKSPACE,
119
120
  environment_name: Optional[str] = None,
@@ -130,12 +131,12 @@ class _Dict(_Object, type_prefix="di"):
130
131
  d[123] = 456
131
132
  ```
132
133
  """
133
- check_object_name(label, "Dict")
134
+ check_object_name(name, "Dict")
134
135
 
135
136
  async def _load(self: _Dict, resolver: Resolver, existing_object_id: Optional[str]):
136
137
  serialized = _serialize_dict(data if data is not None else {})
137
138
  req = api_pb2.DictGetOrCreateRequest(
138
- deployment_name=label,
139
+ deployment_name=name,
139
140
  namespace=namespace,
140
141
  environment_name=_get_environment_name(environment_name, resolver),
141
142
  object_creation_type=(api_pb2.OBJECT_CREATION_TYPE_CREATE_IF_MISSING if create_if_missing else None),
@@ -148,8 +149,9 @@ class _Dict(_Object, type_prefix="di"):
148
149
  return _Dict._from_loader(_load, "Dict()", is_another_app=True, hydrate_lazily=True)
149
150
 
150
151
  @staticmethod
152
+ @renamed_parameter((2024, 12, 18), "label", "name")
151
153
  async def lookup(
152
- label: str,
154
+ name: str,
153
155
  data: Optional[dict] = None,
154
156
  namespace=api_pb2.DEPLOYMENT_NAMESPACE_WORKSPACE,
155
157
  client: Optional[_Client] = None,
@@ -167,7 +169,7 @@ class _Dict(_Object, type_prefix="di"):
167
169
  ```
168
170
  """
169
171
  obj = _Dict.from_name(
170
- label,
172
+ name,
171
173
  data=data,
172
174
  namespace=namespace,
173
175
  environment_name=environment_name,
@@ -180,13 +182,14 @@ class _Dict(_Object, type_prefix="di"):
180
182
  return obj
181
183
 
182
184
  @staticmethod
185
+ @renamed_parameter((2024, 12, 18), "label", "name")
183
186
  async def delete(
184
- label: str,
187
+ name: str,
185
188
  *,
186
189
  client: Optional[_Client] = None,
187
190
  environment_name: Optional[str] = None,
188
191
  ):
189
- obj = await _Dict.lookup(label, client=client, environment_name=environment_name)
192
+ obj = await _Dict.lookup(name, client=client, environment_name=environment_name)
190
193
  req = api_pb2.DictDeleteRequest(dict_id=obj.object_id)
191
194
  await retry_transient_errors(obj._client.stub.DictDelete, req)
192
195
 
modal/dict.pyi CHANGED
@@ -21,7 +21,7 @@ class _Dict(modal.object._Object):
21
21
  ) -> typing.AsyncContextManager[_Dict]: ...
22
22
  @staticmethod
23
23
  def from_name(
24
- label: str,
24
+ name: str,
25
25
  data: typing.Optional[dict] = None,
26
26
  namespace=1,
27
27
  environment_name: typing.Optional[str] = None,
@@ -29,7 +29,7 @@ class _Dict(modal.object._Object):
29
29
  ) -> _Dict: ...
30
30
  @staticmethod
31
31
  async def lookup(
32
- label: str,
32
+ name: str,
33
33
  data: typing.Optional[dict] = None,
34
34
  namespace=1,
35
35
  client: typing.Optional[modal.client._Client] = None,
@@ -38,7 +38,7 @@ class _Dict(modal.object._Object):
38
38
  ) -> _Dict: ...
39
39
  @staticmethod
40
40
  async def delete(
41
- label: str,
41
+ name: str,
42
42
  *,
43
43
  client: typing.Optional[modal.client._Client] = None,
44
44
  environment_name: typing.Optional[str] = None,
@@ -72,7 +72,7 @@ class Dict(modal.object.Object):
72
72
  ) -> synchronicity.combined_types.AsyncAndBlockingContextManager[Dict]: ...
73
73
  @staticmethod
74
74
  def from_name(
75
- label: str,
75
+ name: str,
76
76
  data: typing.Optional[dict] = None,
77
77
  namespace=1,
78
78
  environment_name: typing.Optional[str] = None,
@@ -82,7 +82,7 @@ class Dict(modal.object.Object):
82
82
  class __lookup_spec(typing_extensions.Protocol):
83
83
  def __call__(
84
84
  self,
85
- label: str,
85
+ name: str,
86
86
  data: typing.Optional[dict] = None,
87
87
  namespace=1,
88
88
  client: typing.Optional[modal.client.Client] = None,
@@ -91,7 +91,7 @@ class Dict(modal.object.Object):
91
91
  ) -> Dict: ...
92
92
  async def aio(
93
93
  self,
94
- label: str,
94
+ name: str,
95
95
  data: typing.Optional[dict] = None,
96
96
  namespace=1,
97
97
  client: typing.Optional[modal.client.Client] = None,
@@ -104,14 +104,14 @@ class Dict(modal.object.Object):
104
104
  class __delete_spec(typing_extensions.Protocol):
105
105
  def __call__(
106
106
  self,
107
- label: str,
107
+ name: str,
108
108
  *,
109
109
  client: typing.Optional[modal.client.Client] = None,
110
110
  environment_name: typing.Optional[str] = None,
111
111
  ): ...
112
112
  async def aio(
113
113
  self,
114
- label: str,
114
+ name: str,
115
115
  *,
116
116
  client: typing.Optional[modal.client.Client] = None,
117
117
  environment_name: typing.Optional[str] = None,
modal/environments.py CHANGED
@@ -10,6 +10,7 @@ from modal_proto import api_pb2
10
10
 
11
11
  from ._resolver import Resolver
12
12
  from ._utils.async_utils import synchronize_api, synchronizer
13
+ from ._utils.deprecation import renamed_parameter
13
14
  from ._utils.grpc_utils import retry_transient_errors
14
15
  from ._utils.name_utils import check_object_name
15
16
  from .client import _Client
@@ -52,21 +53,22 @@ class _Environment(_Object, type_prefix="en"):
52
53
  )
53
54
 
54
55
  @staticmethod
56
+ @renamed_parameter((2024, 12, 18), "label", "name")
55
57
  async def from_name(
56
- label: str,
58
+ name: str,
57
59
  create_if_missing: bool = False,
58
60
  ):
59
- if label:
60
- # Allow null labels for the case where we want to look up the "default" environment,
61
+ if name:
62
+ # Allow null names for the case where we want to look up the "default" environment,
61
63
  # which is defined by the server. It feels messy to have "from_name" without a name, though?
62
64
  # We're adding this mostly for internal use right now. We could consider an environment-only
63
65
  # alternate constructor, like `Environment.get_default`, rather than exposing "unnamed"
64
66
  # environments as part of public API when we make this class more useful.
65
- check_object_name(label, "Environment")
67
+ check_object_name(name, "Environment")
66
68
 
67
69
  async def _load(self: _Environment, resolver: Resolver, existing_object_id: Optional[str]):
68
70
  request = api_pb2.EnvironmentGetOrCreateRequest(
69
- deployment_name=label,
71
+ deployment_name=name,
70
72
  object_creation_type=(
71
73
  api_pb2.OBJECT_CREATION_TYPE_CREATE_IF_MISSING
72
74
  if create_if_missing
@@ -81,12 +83,13 @@ class _Environment(_Object, type_prefix="en"):
81
83
  return _Environment._from_loader(_load, "Environment()", is_another_app=True, hydrate_lazily=True)
82
84
 
83
85
  @staticmethod
86
+ @renamed_parameter((2024, 12, 18), "label", "name")
84
87
  async def lookup(
85
- label: str,
88
+ name: str,
86
89
  client: Optional[_Client] = None,
87
90
  create_if_missing: bool = False,
88
91
  ):
89
- obj = await _Environment.from_name(label, create_if_missing=create_if_missing)
92
+ obj = await _Environment.from_name(name, create_if_missing=create_if_missing)
90
93
  if client is None:
91
94
  client = await _Client.from_env()
92
95
  resolver = Resolver(client=client)
modal/environments.pyi CHANGED
@@ -22,10 +22,10 @@ class _Environment(modal.object._Object):
22
22
  def __init__(self): ...
23
23
  def _hydrate_metadata(self, metadata: google.protobuf.message.Message): ...
24
24
  @staticmethod
25
- async def from_name(label: str, create_if_missing: bool = False): ...
25
+ async def from_name(name: str, create_if_missing: bool = False): ...
26
26
  @staticmethod
27
27
  async def lookup(
28
- label: str, client: typing.Optional[modal.client._Client] = None, create_if_missing: bool = False
28
+ name: str, client: typing.Optional[modal.client._Client] = None, create_if_missing: bool = False
29
29
  ): ...
30
30
 
31
31
  class Environment(modal.object.Object):
@@ -35,17 +35,17 @@ class Environment(modal.object.Object):
35
35
  def _hydrate_metadata(self, metadata: google.protobuf.message.Message): ...
36
36
 
37
37
  class __from_name_spec(typing_extensions.Protocol):
38
- def __call__(self, label: str, create_if_missing: bool = False): ...
39
- async def aio(self, label: str, create_if_missing: bool = False): ...
38
+ def __call__(self, name: str, create_if_missing: bool = False): ...
39
+ async def aio(self, name: str, create_if_missing: bool = False): ...
40
40
 
41
41
  from_name: __from_name_spec
42
42
 
43
43
  class __lookup_spec(typing_extensions.Protocol):
44
44
  def __call__(
45
- self, label: str, client: typing.Optional[modal.client.Client] = None, create_if_missing: bool = False
45
+ self, name: str, client: typing.Optional[modal.client.Client] = None, create_if_missing: bool = False
46
46
  ): ...
47
47
  async def aio(
48
- self, label: str, client: typing.Optional[modal.client.Client] = None, create_if_missing: bool = False
48
+ self, name: str, client: typing.Optional[modal.client.Client] = None, create_if_missing: bool = False
49
49
  ): ...
50
50
 
51
51
  lookup: __lookup_spec
modal/functions.py CHANGED
@@ -22,7 +22,6 @@ from grpclib import GRPCError, Status
22
22
  from synchronicity.combined_types import MethodWithAio
23
23
  from synchronicity.exceptions import UserCodeException
24
24
 
25
- from modal._utils.async_utils import aclosing
26
25
  from modal_proto import api_pb2
27
26
  from modal_proto.modal_api_grpc import ModalClientModal
28
27
 
@@ -35,13 +34,14 @@ from ._serialization import serialize, serialize_proto_params
35
34
  from ._traceback import print_server_warnings
36
35
  from ._utils.async_utils import (
37
36
  TaskContext,
37
+ aclosing,
38
38
  async_merge,
39
39
  callable_to_agen,
40
40
  synchronize_api,
41
41
  synchronizer,
42
42
  warn_if_generator_is_not_consumed,
43
43
  )
44
- from ._utils.deprecation import deprecation_warning
44
+ from ._utils.deprecation import deprecation_warning, renamed_parameter
45
45
  from ._utils.function_utils import (
46
46
  ATTEMPT_TIMEOUT_GRACE_PERIOD,
47
47
  OUTPUTS_TIMEOUT,
@@ -1024,10 +1024,11 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
1024
1024
  await retry_transient_errors(self._client.stub.FunctionUpdateSchedulingParams, request)
1025
1025
 
1026
1026
  @classmethod
1027
+ @renamed_parameter((2024, 12, 18), "tag", "name")
1027
1028
  def from_name(
1028
1029
  cls: type["_Function"],
1029
1030
  app_name: str,
1030
- tag: str,
1031
+ name: str,
1031
1032
  namespace=api_pb2.DEPLOYMENT_NAMESPACE_WORKSPACE,
1032
1033
  environment_name: Optional[str] = None,
1033
1034
  ) -> "_Function":
@@ -1046,7 +1047,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
1046
1047
  assert resolver.client and resolver.client.stub
1047
1048
  request = api_pb2.FunctionGetRequest(
1048
1049
  app_name=app_name,
1049
- object_tag=tag,
1050
+ object_tag=name,
1050
1051
  namespace=namespace,
1051
1052
  environment_name=_get_environment_name(environment_name, resolver) or "",
1052
1053
  )
@@ -1066,9 +1067,10 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
1066
1067
  return cls._from_loader(_load_remote, rep, is_another_app=True, hydrate_lazily=True)
1067
1068
 
1068
1069
  @staticmethod
1070
+ @renamed_parameter((2024, 12, 18), "tag", "name")
1069
1071
  async def lookup(
1070
1072
  app_name: str,
1071
- tag: str,
1073
+ name: str,
1072
1074
  namespace=api_pb2.DEPLOYMENT_NAMESPACE_WORKSPACE,
1073
1075
  client: Optional[_Client] = None,
1074
1076
  environment_name: Optional[str] = None,
@@ -1082,7 +1084,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
1082
1084
  f = modal.Function.lookup("other-app", "function")
1083
1085
  ```
1084
1086
  """
1085
- obj = _Function.from_name(app_name, tag, namespace=namespace, environment_name=environment_name)
1087
+ obj = _Function.from_name(app_name, name, namespace=namespace, environment_name=environment_name)
1086
1088
  if client is None:
1087
1089
  client = await _Client.from_env()
1088
1090
  resolver = Resolver(client=client)
modal/functions.pyi CHANGED
@@ -208,12 +208,12 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], modal.object.
208
208
  async def keep_warm(self, warm_pool_size: int) -> None: ...
209
209
  @classmethod
210
210
  def from_name(
211
- cls: type[_Function], app_name: str, tag: str, namespace=1, environment_name: typing.Optional[str] = None
211
+ cls: type[_Function], app_name: str, name: str, namespace=1, environment_name: typing.Optional[str] = None
212
212
  ) -> _Function: ...
213
213
  @staticmethod
214
214
  async def lookup(
215
215
  app_name: str,
216
- tag: str,
216
+ name: str,
217
217
  namespace=1,
218
218
  client: typing.Optional[modal.client._Client] = None,
219
219
  environment_name: typing.Optional[str] = None,
@@ -383,14 +383,14 @@ class Function(typing.Generic[P, ReturnType, OriginalReturnType], modal.object.O
383
383
 
384
384
  @classmethod
385
385
  def from_name(
386
- cls: type[Function], app_name: str, tag: str, namespace=1, environment_name: typing.Optional[str] = None
386
+ cls: type[Function], app_name: str, name: str, namespace=1, environment_name: typing.Optional[str] = None
387
387
  ) -> Function: ...
388
388
 
389
389
  class __lookup_spec(typing_extensions.Protocol):
390
390
  def __call__(
391
391
  self,
392
392
  app_name: str,
393
- tag: str,
393
+ name: str,
394
394
  namespace=1,
395
395
  client: typing.Optional[modal.client.Client] = None,
396
396
  environment_name: typing.Optional[str] = None,
@@ -398,7 +398,7 @@ class Function(typing.Generic[P, ReturnType, OriginalReturnType], modal.object.O
398
398
  async def aio(
399
399
  self,
400
400
  app_name: str,
401
- tag: str,
401
+ name: str,
402
402
  namespace=1,
403
403
  client: typing.Optional[modal.client.Client] = None,
404
404
  environment_name: typing.Optional[str] = None,
@@ -462,11 +462,11 @@ class Function(typing.Generic[P, ReturnType, OriginalReturnType], modal.object.O
462
462
 
463
463
  _call_generator_nowait: ___call_generator_nowait_spec
464
464
 
465
- class __remote_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER]):
465
+ class __remote_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
466
466
  def __call__(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER: ...
467
467
  async def aio(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER: ...
468
468
 
469
- remote: __remote_spec[P, ReturnType]
469
+ remote: __remote_spec[ReturnType, P]
470
470
 
471
471
  class __remote_gen_spec(typing_extensions.Protocol):
472
472
  def __call__(self, *args, **kwargs) -> typing.Generator[typing.Any, None, None]: ...
@@ -479,17 +479,17 @@ class Function(typing.Generic[P, ReturnType, OriginalReturnType], modal.object.O
479
479
  def _get_obj(self) -> typing.Optional[modal.cls.Obj]: ...
480
480
  def local(self, *args: P.args, **kwargs: P.kwargs) -> OriginalReturnType: ...
481
481
 
482
- class ___experimental_spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER]):
482
+ class ___experimental_spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
483
483
  def __call__(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
484
484
  async def aio(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
485
485
 
486
- _experimental_spawn: ___experimental_spawn_spec[P, ReturnType]
486
+ _experimental_spawn: ___experimental_spawn_spec[ReturnType, P]
487
487
 
488
- class __spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER]):
488
+ class __spawn_spec(typing_extensions.Protocol[ReturnType_INNER, P_INNER]):
489
489
  def __call__(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
490
490
  async def aio(self, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]: ...
491
491
 
492
- spawn: __spawn_spec[P, ReturnType]
492
+ spawn: __spawn_spec[ReturnType, P]
493
493
 
494
494
  def get_raw_f(self) -> typing.Callable[..., typing.Any]: ...
495
495