modal 0.68.31__py3-none-any.whl → 0.68.42__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,
modal/cli/dict.py CHANGED
@@ -89,6 +89,11 @@ async def get(name: str, key: str, *, env: Optional[str] = ENV_OPTION):
89
89
  console.print(val)
90
90
 
91
91
 
92
+ def _display(input: str, use_repr: bool) -> str:
93
+ val = repr(input) if use_repr else str(input)
94
+ return val[:80] + "..." if len(val) > 80 else val
95
+
96
+
92
97
  @dict_cli.command(name="items", rich_help_panel="Inspection")
93
98
  @synchronizer.create_blocking
94
99
  async def items(
@@ -117,8 +122,7 @@ async def items(
117
122
  if json:
118
123
  display_item = key, val
119
124
  else:
120
- cast = repr if use_repr else str
121
- display_item = cast(key), cast(val) # type: ignore # mypy/issue/12056
125
+ display_item = _display(key, use_repr), _display(val, use_repr) # type: ignore # mypy/issue/12056
122
126
  items.append(display_item)
123
127
 
124
128
  display_table(["Key", "Value"], items, json)
@@ -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/run.py CHANGED
@@ -482,6 +482,7 @@ def shell(
482
482
  volumes=function_spec.volumes,
483
483
  region=function_spec.scheduler_placement.proto.regions if function_spec.scheduler_placement else None,
484
484
  pty=pty,
485
+ proxy=function_spec.proxy,
485
486
  )
486
487
  else:
487
488
  modal_image = Image.from_registry(image, add_python=add_python) if image else None
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.31"
29
+ self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.68.42"
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.31"
84
+ self, server_url: str, client_type: int, credentials: typing.Optional[tuple[str, str]], version: str = "0.68.42"
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 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
@@ -58,15 +58,6 @@ class _Dict(_Object, type_prefix="di"):
58
58
  For more examples, see the [guide](/docs/guide/dicts-and-queues#modal-dicts).
59
59
  """
60
60
 
61
- @staticmethod
62
- def new(data: Optional[dict] = None):
63
- """mdmd:hidden"""
64
- message = (
65
- "`Dict.new` is deprecated."
66
- " Please use `Dict.from_name` (for persisted) or `Dict.ephemeral` (for ephemeral) dicts instead."
67
- )
68
- deprecation_error((2024, 3, 19), message)
69
-
70
61
  def __init__(self, data={}):
71
62
  """mdmd:hidden"""
72
63
  raise RuntimeError(
@@ -112,8 +103,9 @@ class _Dict(_Object, type_prefix="di"):
112
103
  yield cls._new_hydrated(response.dict_id, client, None, is_another_app=True)
113
104
 
114
105
  @staticmethod
106
+ @renamed_parameter((2024, 12, 18), "label", "name")
115
107
  def from_name(
116
- label: str,
108
+ name: str,
117
109
  data: Optional[dict] = None,
118
110
  namespace=api_pb2.DEPLOYMENT_NAMESPACE_WORKSPACE,
119
111
  environment_name: Optional[str] = None,
@@ -130,12 +122,12 @@ class _Dict(_Object, type_prefix="di"):
130
122
  d[123] = 456
131
123
  ```
132
124
  """
133
- check_object_name(label, "Dict")
125
+ check_object_name(name, "Dict")
134
126
 
135
127
  async def _load(self: _Dict, resolver: Resolver, existing_object_id: Optional[str]):
136
128
  serialized = _serialize_dict(data if data is not None else {})
137
129
  req = api_pb2.DictGetOrCreateRequest(
138
- deployment_name=label,
130
+ deployment_name=name,
139
131
  namespace=namespace,
140
132
  environment_name=_get_environment_name(environment_name, resolver),
141
133
  object_creation_type=(api_pb2.OBJECT_CREATION_TYPE_CREATE_IF_MISSING if create_if_missing else None),
@@ -148,8 +140,9 @@ class _Dict(_Object, type_prefix="di"):
148
140
  return _Dict._from_loader(_load, "Dict()", is_another_app=True, hydrate_lazily=True)
149
141
 
150
142
  @staticmethod
143
+ @renamed_parameter((2024, 12, 18), "label", "name")
151
144
  async def lookup(
152
- label: str,
145
+ name: str,
153
146
  data: Optional[dict] = None,
154
147
  namespace=api_pb2.DEPLOYMENT_NAMESPACE_WORKSPACE,
155
148
  client: Optional[_Client] = None,
@@ -167,7 +160,7 @@ class _Dict(_Object, type_prefix="di"):
167
160
  ```
168
161
  """
169
162
  obj = _Dict.from_name(
170
- label,
163
+ name,
171
164
  data=data,
172
165
  namespace=namespace,
173
166
  environment_name=environment_name,
@@ -180,13 +173,14 @@ class _Dict(_Object, type_prefix="di"):
180
173
  return obj
181
174
 
182
175
  @staticmethod
176
+ @renamed_parameter((2024, 12, 18), "label", "name")
183
177
  async def delete(
184
- label: str,
178
+ name: str,
185
179
  *,
186
180
  client: Optional[_Client] = None,
187
181
  environment_name: Optional[str] = None,
188
182
  ):
189
- obj = await _Dict.lookup(label, client=client, environment_name=environment_name)
183
+ obj = await _Dict.lookup(name, client=client, environment_name=environment_name)
190
184
  req = api_pb2.DictDeleteRequest(dict_id=obj.object_id)
191
185
  await retry_transient_errors(obj._client.stub.DictDelete, req)
192
186
 
modal/dict.pyi CHANGED
@@ -8,8 +8,6 @@ import typing_extensions
8
8
  def _serialize_dict(data): ...
9
9
 
10
10
  class _Dict(modal.object._Object):
11
- @staticmethod
12
- def new(data: typing.Optional[dict] = None): ...
13
11
  def __init__(self, data={}): ...
14
12
  @classmethod
15
13
  def ephemeral(
@@ -21,7 +19,7 @@ class _Dict(modal.object._Object):
21
19
  ) -> typing.AsyncContextManager[_Dict]: ...
22
20
  @staticmethod
23
21
  def from_name(
24
- label: str,
22
+ name: str,
25
23
  data: typing.Optional[dict] = None,
26
24
  namespace=1,
27
25
  environment_name: typing.Optional[str] = None,
@@ -29,7 +27,7 @@ class _Dict(modal.object._Object):
29
27
  ) -> _Dict: ...
30
28
  @staticmethod
31
29
  async def lookup(
32
- label: str,
30
+ name: str,
33
31
  data: typing.Optional[dict] = None,
34
32
  namespace=1,
35
33
  client: typing.Optional[modal.client._Client] = None,
@@ -38,7 +36,7 @@ class _Dict(modal.object._Object):
38
36
  ) -> _Dict: ...
39
37
  @staticmethod
40
38
  async def delete(
41
- label: str,
39
+ name: str,
42
40
  *,
43
41
  client: typing.Optional[modal.client._Client] = None,
44
42
  environment_name: typing.Optional[str] = None,
@@ -60,8 +58,6 @@ class _Dict(modal.object._Object):
60
58
 
61
59
  class Dict(modal.object.Object):
62
60
  def __init__(self, data={}): ...
63
- @staticmethod
64
- def new(data: typing.Optional[dict] = None): ...
65
61
  @classmethod
66
62
  def ephemeral(
67
63
  cls: type[Dict],
@@ -72,7 +68,7 @@ class Dict(modal.object.Object):
72
68
  ) -> synchronicity.combined_types.AsyncAndBlockingContextManager[Dict]: ...
73
69
  @staticmethod
74
70
  def from_name(
75
- label: str,
71
+ name: str,
76
72
  data: typing.Optional[dict] = None,
77
73
  namespace=1,
78
74
  environment_name: typing.Optional[str] = None,
@@ -82,7 +78,7 @@ class Dict(modal.object.Object):
82
78
  class __lookup_spec(typing_extensions.Protocol):
83
79
  def __call__(
84
80
  self,
85
- label: str,
81
+ name: str,
86
82
  data: typing.Optional[dict] = None,
87
83
  namespace=1,
88
84
  client: typing.Optional[modal.client.Client] = None,
@@ -91,7 +87,7 @@ class Dict(modal.object.Object):
91
87
  ) -> Dict: ...
92
88
  async def aio(
93
89
  self,
94
- label: str,
90
+ name: str,
95
91
  data: typing.Optional[dict] = None,
96
92
  namespace=1,
97
93
  client: typing.Optional[modal.client.Client] = None,
@@ -104,14 +100,14 @@ class Dict(modal.object.Object):
104
100
  class __delete_spec(typing_extensions.Protocol):
105
101
  def __call__(
106
102
  self,
107
- label: str,
103
+ name: str,
108
104
  *,
109
105
  client: typing.Optional[modal.client.Client] = None,
110
106
  environment_name: typing.Optional[str] = None,
111
107
  ): ...
112
108
  async def aio(
113
109
  self,
114
- label: str,
110
+ name: str,
115
111
  *,
116
112
  client: typing.Optional[modal.client.Client] = None,
117
113
  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,
@@ -346,6 +346,7 @@ class _FunctionSpec:
346
346
  memory: Optional[Union[int, tuple[int, int]]]
347
347
  ephemeral_disk: Optional[int]
348
348
  scheduler_placement: Optional[SchedulerPlacement]
349
+ proxy: Optional[_Proxy]
349
350
 
350
351
 
351
352
  P = typing_extensions.ParamSpec("P")
@@ -530,6 +531,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
530
531
  memory=memory,
531
532
  ephemeral_disk=ephemeral_disk,
532
533
  scheduler_placement=scheduler_placement,
534
+ proxy=proxy,
533
535
  )
534
536
 
535
537
  if info.user_cls and not is_auto_snapshot:
@@ -1022,10 +1024,11 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
1022
1024
  await retry_transient_errors(self._client.stub.FunctionUpdateSchedulingParams, request)
1023
1025
 
1024
1026
  @classmethod
1027
+ @renamed_parameter((2024, 12, 18), "tag", "name")
1025
1028
  def from_name(
1026
1029
  cls: type["_Function"],
1027
1030
  app_name: str,
1028
- tag: str,
1031
+ name: str,
1029
1032
  namespace=api_pb2.DEPLOYMENT_NAMESPACE_WORKSPACE,
1030
1033
  environment_name: Optional[str] = None,
1031
1034
  ) -> "_Function":
@@ -1044,7 +1047,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
1044
1047
  assert resolver.client and resolver.client.stub
1045
1048
  request = api_pb2.FunctionGetRequest(
1046
1049
  app_name=app_name,
1047
- object_tag=tag,
1050
+ object_tag=name,
1048
1051
  namespace=namespace,
1049
1052
  environment_name=_get_environment_name(environment_name, resolver) or "",
1050
1053
  )
@@ -1064,9 +1067,10 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
1064
1067
  return cls._from_loader(_load_remote, rep, is_another_app=True, hydrate_lazily=True)
1065
1068
 
1066
1069
  @staticmethod
1070
+ @renamed_parameter((2024, 12, 18), "tag", "name")
1067
1071
  async def lookup(
1068
1072
  app_name: str,
1069
- tag: str,
1073
+ name: str,
1070
1074
  namespace=api_pb2.DEPLOYMENT_NAMESPACE_WORKSPACE,
1071
1075
  client: Optional[_Client] = None,
1072
1076
  environment_name: Optional[str] = None,
@@ -1080,7 +1084,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
1080
1084
  f = modal.Function.lookup("other-app", "function")
1081
1085
  ```
1082
1086
  """
1083
- 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)
1084
1088
  if client is None:
1085
1089
  client = await _Client.from_env()
1086
1090
  resolver = Resolver(client=client)