modal 0.68.24__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 +6 -2
- modal/_utils/deprecation.py +89 -0
- modal/app.py +15 -34
- modal/app.pyi +6 -7
- modal/cli/app.py +1 -1
- modal/cli/dict.py +6 -2
- modal/cli/network_file_system.py +1 -1
- modal/cli/run.py +1 -0
- modal/cli/volume.py +1 -1
- modal/client.pyi +2 -2
- modal/cls.py +15 -9
- modal/cls.pyi +5 -5
- modal/config.py +2 -1
- modal/container_process.py +2 -1
- modal/dict.py +12 -17
- modal/dict.pyi +8 -12
- modal/environments.py +10 -7
- modal/environments.pyi +6 -6
- modal/exception.py +0 -54
- modal/file_io.py +54 -7
- modal/file_io.pyi +18 -8
- modal/file_pattern_matcher.py +48 -15
- modal/functions.py +11 -13
- modal/functions.pyi +18 -12
- modal/image.py +21 -20
- modal/image.pyi +16 -28
- modal/mount.py +7 -4
- modal/mount.pyi +4 -4
- modal/network_file_system.py +13 -19
- modal/network_file_system.pyi +8 -12
- modal/partial_function.py +2 -30
- modal/queue.py +12 -17
- modal/queue.pyi +8 -12
- modal/runner.py +2 -7
- modal/sandbox.py +25 -13
- modal/sandbox.pyi +21 -0
- modal/secret.py +7 -4
- modal/secret.pyi +5 -5
- modal/serving.py +1 -1
- modal/volume.py +12 -17
- modal/volume.pyi +8 -12
- {modal-0.68.24.dist-info → modal-0.68.42.dist-info}/METADATA +2 -2
- {modal-0.68.24.dist-info → modal-0.68.42.dist-info}/RECORD +51 -50
- modal_proto/api.proto +1 -1
- modal_proto/api_pb2.py +750 -750
- modal_proto/api_pb2.pyi +4 -4
- modal_version/_version_generated.py +1 -1
- {modal-0.68.24.dist-info → modal-0.68.42.dist-info}/LICENSE +0 -0
- {modal-0.68.24.dist-info → modal-0.68.42.dist-info}/WHEEL +0 -0
- {modal-0.68.24.dist-info → modal-0.68.42.dist-info}/entry_points.txt +0 -0
- {modal-0.68.24.dist-info → modal-0.68.42.dist-info}/top_level.txt +0 -0
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
|
-
|
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
|
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
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# Copyright Modal Labs 2024
|
2
|
+
import functools
|
3
|
+
import sys
|
4
|
+
import warnings
|
5
|
+
from datetime import date
|
6
|
+
from typing import Any, Callable, TypeVar
|
7
|
+
|
8
|
+
from typing_extensions import ParamSpec # Needed for Python 3.9
|
9
|
+
|
10
|
+
from ..exception import DeprecationError, PendingDeprecationError
|
11
|
+
|
12
|
+
_INTERNAL_MODULES = ["modal", "synchronicity"]
|
13
|
+
|
14
|
+
|
15
|
+
def _is_internal_frame(frame):
|
16
|
+
module = frame.f_globals["__name__"].split(".")[0]
|
17
|
+
return module in _INTERNAL_MODULES
|
18
|
+
|
19
|
+
|
20
|
+
def deprecation_error(deprecated_on: tuple[int, int, int], msg: str):
|
21
|
+
raise DeprecationError(f"Deprecated on {date(*deprecated_on)}: {msg}")
|
22
|
+
|
23
|
+
|
24
|
+
def deprecation_warning(
|
25
|
+
deprecated_on: tuple[int, int, int], msg: str, *, pending: bool = False, show_source: bool = True
|
26
|
+
) -> None:
|
27
|
+
"""Issue a Modal deprecation warning with source optionally attributed to user code.
|
28
|
+
|
29
|
+
See the implementation of the built-in [warnings.warn](https://docs.python.org/3/library/warnings.html#available-functions).
|
30
|
+
"""
|
31
|
+
filename, lineno = "<unknown>", 0
|
32
|
+
if show_source:
|
33
|
+
# Find the last non-Modal line that triggered the warning
|
34
|
+
try:
|
35
|
+
frame = sys._getframe()
|
36
|
+
while frame is not None and _is_internal_frame(frame):
|
37
|
+
frame = frame.f_back
|
38
|
+
if frame is not None:
|
39
|
+
filename = frame.f_code.co_filename
|
40
|
+
lineno = frame.f_lineno
|
41
|
+
except ValueError:
|
42
|
+
# Use the defaults from above
|
43
|
+
pass
|
44
|
+
|
45
|
+
warning_cls = PendingDeprecationError if pending else DeprecationError
|
46
|
+
|
47
|
+
# This is a lower-level function that warnings.warn uses
|
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,6 +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, renamed_parameter
|
25
26
|
from ._utils.function_utils import FunctionInfo, is_global_object, is_method_fn
|
26
27
|
from ._utils.grpc_utils import retry_transient_errors
|
27
28
|
from ._utils.mount_utils import validate_volumes
|
@@ -29,7 +30,7 @@ from .client import _Client
|
|
29
30
|
from .cloud_bucket_mount import _CloudBucketMount
|
30
31
|
from .cls import _Cls, parameter
|
31
32
|
from .config import logger
|
32
|
-
from .exception import ExecutionError, InvalidError
|
33
|
+
from .exception import ExecutionError, InvalidError
|
33
34
|
from .functions import Function, _Function
|
34
35
|
from .gpu import GPU_T
|
35
36
|
from .image import _Image
|
@@ -45,7 +46,6 @@ from .partial_function import (
|
|
45
46
|
from .proxy import _Proxy
|
46
47
|
from .retries import Retries
|
47
48
|
from .running_app import RunningApp
|
48
|
-
from .sandbox import _Sandbox
|
49
49
|
from .schedule import Schedule
|
50
50
|
from .scheduler_placement import SchedulerPlacement
|
51
51
|
from .secret import _Secret
|
@@ -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
|
-
|
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=
|
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(
|
294
|
+
app = _App(name)
|
294
295
|
app._app_id = response.app_id
|
295
296
|
app._client = client
|
296
297
|
app._running_app = RunningApp(
|
@@ -964,36 +965,16 @@ class _App:
|
|
964
965
|
_experimental_scheduler_placement: Optional[
|
965
966
|
SchedulerPlacement
|
966
967
|
] = None, # Experimental controls over fine-grained scheduling (alpha).
|
967
|
-
) ->
|
968
|
-
"""
|
969
|
-
|
970
|
-
|
971
|
-
|
972
|
-
|
973
|
-
|
974
|
-
|
975
|
-
|
976
|
-
return await _Sandbox.create(
|
977
|
-
*entrypoint_args,
|
978
|
-
app=self,
|
979
|
-
environment_name=self._running_app.environment_name,
|
980
|
-
image=image or _default_image,
|
981
|
-
mounts=mounts,
|
982
|
-
secrets=secrets,
|
983
|
-
timeout=timeout,
|
984
|
-
workdir=workdir,
|
985
|
-
gpu=gpu,
|
986
|
-
cloud=cloud,
|
987
|
-
region=region,
|
988
|
-
cpu=cpu,
|
989
|
-
memory=memory,
|
990
|
-
network_file_systems=network_file_systems,
|
991
|
-
block_network=block_network,
|
992
|
-
volumes=volumes,
|
993
|
-
pty_info=pty_info,
|
994
|
-
_experimental_scheduler_placement=_experimental_scheduler_placement,
|
995
|
-
client=self._client,
|
968
|
+
) -> None:
|
969
|
+
"""mdmd:hidden"""
|
970
|
+
arglist = ", ".join(repr(s) for s in entrypoint_args)
|
971
|
+
message = (
|
972
|
+
"`App.spawn_sandbox` is deprecated.\n\n"
|
973
|
+
"Sandboxes can be created using the `Sandbox` object:\n\n"
|
974
|
+
f"```\nsb = Sandbox.create({arglist}, app=app)\n```\n\n"
|
975
|
+
"See https://modal.com/docs/guide/sandbox for more info on working with sandboxes."
|
996
976
|
)
|
977
|
+
deprecation_error((2024, 7, 5), message)
|
997
978
|
|
998
979
|
def include(self, /, other_app: "_App"):
|
999
980
|
"""Include another App's objects in this one.
|
modal/app.pyi
CHANGED
@@ -13,7 +13,6 @@ import modal.partial_function
|
|
13
13
|
import modal.proxy
|
14
14
|
import modal.retries
|
15
15
|
import modal.running_app
|
16
|
-
import modal.sandbox
|
17
16
|
import modal.schedule
|
18
17
|
import modal.scheduler_placement
|
19
18
|
import modal.secret
|
@@ -108,7 +107,7 @@ class _App:
|
|
108
107
|
def description(self) -> typing.Optional[str]: ...
|
109
108
|
@staticmethod
|
110
109
|
async def lookup(
|
111
|
-
|
110
|
+
name: str,
|
112
111
|
client: typing.Optional[modal.client._Client] = None,
|
113
112
|
environment_name: typing.Optional[str] = None,
|
114
113
|
create_if_missing: bool = False,
|
@@ -261,7 +260,7 @@ class _App:
|
|
261
260
|
] = {},
|
262
261
|
pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
|
263
262
|
_experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
|
264
|
-
) ->
|
263
|
+
) -> None: ...
|
265
264
|
def include(self, /, other_app: _App): ...
|
266
265
|
def _logs(
|
267
266
|
self, client: typing.Optional[modal.client._Client] = None
|
@@ -307,14 +306,14 @@ class App:
|
|
307
306
|
class __lookup_spec(typing_extensions.Protocol):
|
308
307
|
def __call__(
|
309
308
|
self,
|
310
|
-
|
309
|
+
name: str,
|
311
310
|
client: typing.Optional[modal.client.Client] = None,
|
312
311
|
environment_name: typing.Optional[str] = None,
|
313
312
|
create_if_missing: bool = False,
|
314
313
|
) -> App: ...
|
315
314
|
async def aio(
|
316
315
|
self,
|
317
|
-
|
316
|
+
name: str,
|
318
317
|
client: typing.Optional[modal.client.Client] = None,
|
319
318
|
environment_name: typing.Optional[str] = None,
|
320
319
|
create_if_missing: bool = False,
|
@@ -491,7 +490,7 @@ class App:
|
|
491
490
|
] = {},
|
492
491
|
pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
|
493
492
|
_experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
|
494
|
-
) ->
|
493
|
+
) -> None: ...
|
495
494
|
async def aio(
|
496
495
|
self,
|
497
496
|
*entrypoint_args: str,
|
@@ -515,7 +514,7 @@ class App:
|
|
515
514
|
] = {},
|
516
515
|
pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
|
517
516
|
_experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
|
518
|
-
) ->
|
517
|
+
) -> None: ...
|
519
518
|
|
520
519
|
spawn_sandbox: __spawn_sandbox_spec
|
521
520
|
|
modal/cli/app.py
CHANGED
@@ -10,9 +10,9 @@ from rich.text import Text
|
|
10
10
|
from typer import Argument
|
11
11
|
|
12
12
|
from modal._utils.async_utils import synchronizer
|
13
|
+
from modal._utils.deprecation import deprecation_warning
|
13
14
|
from modal.client import _Client
|
14
15
|
from modal.environments import ensure_env
|
15
|
-
from modal.exception import deprecation_warning
|
16
16
|
from modal.object import _get_environment_name
|
17
17
|
from modal_proto import api_pb2
|
18
18
|
|
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
|
-
|
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)
|
modal/cli/network_file_system.py
CHANGED
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
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.
|
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.
|
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
|
-
|
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
|
-
|
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=
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
653
|
-
|
655
|
+
Model = modal.Cls.lookup("other-app", "Model")
|
656
|
+
model = Model()
|
657
|
+
model.inference(...)
|
654
658
|
```
|
655
659
|
"""
|
656
|
-
obj = _Cls.from_name(
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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/config.py
CHANGED
@@ -86,8 +86,9 @@ from google.protobuf.empty_pb2 import Empty
|
|
86
86
|
|
87
87
|
from modal_proto import api_pb2
|
88
88
|
|
89
|
+
from ._utils.deprecation import deprecation_error
|
89
90
|
from ._utils.logger import configure_logger
|
90
|
-
from .exception import InvalidError
|
91
|
+
from .exception import InvalidError
|
91
92
|
|
92
93
|
# Locate config file and read it
|
93
94
|
|
modal/container_process.py
CHANGED
@@ -6,10 +6,11 @@ from typing import Generic, Optional, TypeVar
|
|
6
6
|
from modal_proto import api_pb2
|
7
7
|
|
8
8
|
from ._utils.async_utils import TaskContext, synchronize_api
|
9
|
+
from ._utils.deprecation import deprecation_error
|
9
10
|
from ._utils.grpc_utils import retry_transient_errors
|
10
11
|
from ._utils.shell_utils import stream_from_stdin, write_to_fd
|
11
12
|
from .client import _Client
|
12
|
-
from .exception import InteractiveTimeoutError, InvalidError
|
13
|
+
from .exception import InteractiveTimeoutError, InvalidError
|
13
14
|
from .io_streams import _StreamReader, _StreamWriter
|
14
15
|
from .stream_type import StreamType
|
15
16
|
|
modal/dict.py
CHANGED
@@ -10,11 +10,12 @@ 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 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
|
16
17
|
from .config import logger
|
17
|
-
from .exception import RequestSizeError
|
18
|
+
from .exception import RequestSizeError
|
18
19
|
from .object import EPHEMERAL_OBJECT_HEARTBEAT_SLEEP, _get_environment_name, _Object, live_method, live_method_gen
|
19
20
|
|
20
21
|
|
@@ -57,15 +58,6 @@ class _Dict(_Object, type_prefix="di"):
|
|
57
58
|
For more examples, see the [guide](/docs/guide/dicts-and-queues#modal-dicts).
|
58
59
|
"""
|
59
60
|
|
60
|
-
@staticmethod
|
61
|
-
def new(data: Optional[dict] = None):
|
62
|
-
"""mdmd:hidden"""
|
63
|
-
message = (
|
64
|
-
"`Dict.new` is deprecated."
|
65
|
-
" Please use `Dict.from_name` (for persisted) or `Dict.ephemeral` (for ephemeral) dicts instead."
|
66
|
-
)
|
67
|
-
deprecation_error((2024, 3, 19), message)
|
68
|
-
|
69
61
|
def __init__(self, data={}):
|
70
62
|
"""mdmd:hidden"""
|
71
63
|
raise RuntimeError(
|
@@ -111,8 +103,9 @@ class _Dict(_Object, type_prefix="di"):
|
|
111
103
|
yield cls._new_hydrated(response.dict_id, client, None, is_another_app=True)
|
112
104
|
|
113
105
|
@staticmethod
|
106
|
+
@renamed_parameter((2024, 12, 18), "label", "name")
|
114
107
|
def from_name(
|
115
|
-
|
108
|
+
name: str,
|
116
109
|
data: Optional[dict] = None,
|
117
110
|
namespace=api_pb2.DEPLOYMENT_NAMESPACE_WORKSPACE,
|
118
111
|
environment_name: Optional[str] = None,
|
@@ -129,12 +122,12 @@ class _Dict(_Object, type_prefix="di"):
|
|
129
122
|
d[123] = 456
|
130
123
|
```
|
131
124
|
"""
|
132
|
-
check_object_name(
|
125
|
+
check_object_name(name, "Dict")
|
133
126
|
|
134
127
|
async def _load(self: _Dict, resolver: Resolver, existing_object_id: Optional[str]):
|
135
128
|
serialized = _serialize_dict(data if data is not None else {})
|
136
129
|
req = api_pb2.DictGetOrCreateRequest(
|
137
|
-
deployment_name=
|
130
|
+
deployment_name=name,
|
138
131
|
namespace=namespace,
|
139
132
|
environment_name=_get_environment_name(environment_name, resolver),
|
140
133
|
object_creation_type=(api_pb2.OBJECT_CREATION_TYPE_CREATE_IF_MISSING if create_if_missing else None),
|
@@ -147,8 +140,9 @@ class _Dict(_Object, type_prefix="di"):
|
|
147
140
|
return _Dict._from_loader(_load, "Dict()", is_another_app=True, hydrate_lazily=True)
|
148
141
|
|
149
142
|
@staticmethod
|
143
|
+
@renamed_parameter((2024, 12, 18), "label", "name")
|
150
144
|
async def lookup(
|
151
|
-
|
145
|
+
name: str,
|
152
146
|
data: Optional[dict] = None,
|
153
147
|
namespace=api_pb2.DEPLOYMENT_NAMESPACE_WORKSPACE,
|
154
148
|
client: Optional[_Client] = None,
|
@@ -166,7 +160,7 @@ class _Dict(_Object, type_prefix="di"):
|
|
166
160
|
```
|
167
161
|
"""
|
168
162
|
obj = _Dict.from_name(
|
169
|
-
|
163
|
+
name,
|
170
164
|
data=data,
|
171
165
|
namespace=namespace,
|
172
166
|
environment_name=environment_name,
|
@@ -179,13 +173,14 @@ class _Dict(_Object, type_prefix="di"):
|
|
179
173
|
return obj
|
180
174
|
|
181
175
|
@staticmethod
|
176
|
+
@renamed_parameter((2024, 12, 18), "label", "name")
|
182
177
|
async def delete(
|
183
|
-
|
178
|
+
name: str,
|
184
179
|
*,
|
185
180
|
client: Optional[_Client] = None,
|
186
181
|
environment_name: Optional[str] = None,
|
187
182
|
):
|
188
|
-
obj = await _Dict.lookup(
|
183
|
+
obj = await _Dict.lookup(name, client=client, environment_name=environment_name)
|
189
184
|
req = api_pb2.DictDeleteRequest(dict_id=obj.object_id)
|
190
185
|
await retry_transient_errors(obj._client.stub.DictDelete, req)
|
191
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
110
|
+
name: str,
|
115
111
|
*,
|
116
112
|
client: typing.Optional[modal.client.Client] = None,
|
117
113
|
environment_name: typing.Optional[str] = None,
|