modal 0.77.1.dev0__py3-none-any.whl → 1.0.0__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.
Potentially problematic release.
This version of modal might be problematic. Click here for more details.
- modal/__init__.py +10 -4
- modal/_functions.py +15 -90
- modal/_object.py +0 -14
- modal/_partial_function.py +4 -14
- modal/_serialization.py +2 -2
- modal/_utils/function_utils.py +3 -6
- modal/_utils/grpc_utils.py +6 -1
- modal/app.py +1 -104
- modal/app.pyi +0 -127
- modal/cli/app.py +0 -19
- modal/cli/programs/run_jupyter.py +1 -1
- modal/cli/programs/vscode.py +1 -1
- modal/client.pyi +2 -10
- modal/cls.py +9 -14
- modal/cls.pyi +2 -17
- modal/config.py +5 -16
- modal/container_process.py +1 -9
- modal/container_process.pyi +3 -3
- modal/dict.py +3 -5
- modal/environments.py +1 -3
- modal/exception.py +1 -1
- modal/functions.pyi +8 -29
- modal/image.py +12 -36
- modal/image.pyi +2 -5
- modal/mount.py +2 -65
- modal/mount.pyi +0 -1
- modal/network_file_system.py +3 -5
- modal/object.pyi +0 -6
- modal/queue.py +3 -5
- modal/runner.py +2 -19
- modal/runner.pyi +0 -5
- modal/sandbox.py +78 -32
- modal/sandbox.pyi +102 -7
- modal/secret.py +1 -3
- modal/serving.py +0 -6
- modal/serving.pyi +0 -3
- modal/volume.py +8 -17
- {modal-0.77.1.dev0.dist-info → modal-1.0.0.dist-info}/METADATA +1 -1
- {modal-0.77.1.dev0.dist-info → modal-1.0.0.dist-info}/RECORD +51 -51
- modal_proto/api.proto +29 -2
- modal_proto/api_grpc.py +32 -0
- modal_proto/api_pb2.py +788 -756
- modal_proto/api_pb2.pyi +86 -12
- modal_proto/api_pb2_grpc.py +66 -0
- modal_proto/api_pb2_grpc.pyi +20 -0
- modal_proto/modal_api_grpc.py +2 -0
- modal_version/__init__.py +1 -1
- {modal-0.77.1.dev0.dist-info → modal-1.0.0.dist-info}/WHEEL +0 -0
- {modal-0.77.1.dev0.dist-info → modal-1.0.0.dist-info}/entry_points.txt +0 -0
- {modal-0.77.1.dev0.dist-info → modal-1.0.0.dist-info}/licenses/LICENSE +0 -0
- {modal-0.77.1.dev0.dist-info → modal-1.0.0.dist-info}/top_level.txt +0 -0
modal/mount.pyi
CHANGED
@@ -308,7 +308,6 @@ def _create_client_mount(): ...
|
|
308
308
|
def create_client_mount(): ...
|
309
309
|
def _get_client_mount(): ...
|
310
310
|
def _is_modal_path(remote_path: pathlib.PurePosixPath): ...
|
311
|
-
def get_sys_modules_mounts() -> dict[str, _Mount]: ...
|
312
311
|
|
313
312
|
ROOT_DIR: pathlib.PurePosixPath
|
314
313
|
|
modal/network_file_system.py
CHANGED
@@ -22,7 +22,7 @@ from ._object import (
|
|
22
22
|
from ._resolver import Resolver
|
23
23
|
from ._utils.async_utils import TaskContext, aclosing, async_map, sync_or_async_iter, synchronize_api
|
24
24
|
from ._utils.blob_utils import LARGE_FILE_LIMIT, blob_iter, blob_upload_file
|
25
|
-
from ._utils.deprecation import deprecation_warning
|
25
|
+
from ._utils.deprecation import deprecation_warning
|
26
26
|
from ._utils.grpc_utils import retry_transient_errors
|
27
27
|
from ._utils.hash_utils import get_sha256_hex
|
28
28
|
from ._utils.name_utils import check_object_name
|
@@ -89,7 +89,6 @@ class _NetworkFileSystem(_Object, type_prefix="sv"):
|
|
89
89
|
"""
|
90
90
|
|
91
91
|
@staticmethod
|
92
|
-
@renamed_parameter((2024, 12, 18), "label", "name")
|
93
92
|
def from_name(
|
94
93
|
name: str,
|
95
94
|
*,
|
@@ -166,7 +165,6 @@ class _NetworkFileSystem(_Object, type_prefix="sv"):
|
|
166
165
|
yield cls._new_hydrated(response.shared_volume_id, client, None, is_another_app=True)
|
167
166
|
|
168
167
|
@staticmethod
|
169
|
-
@renamed_parameter((2024, 12, 18), "label", "name")
|
170
168
|
async def lookup(
|
171
169
|
name: str,
|
172
170
|
namespace=api_pb2.DEPLOYMENT_NAMESPACE_WORKSPACE,
|
@@ -174,7 +172,8 @@ class _NetworkFileSystem(_Object, type_prefix="sv"):
|
|
174
172
|
environment_name: Optional[str] = None,
|
175
173
|
create_if_missing: bool = False,
|
176
174
|
) -> "_NetworkFileSystem":
|
177
|
-
"""
|
175
|
+
"""mdmd:hidden
|
176
|
+
Lookup a named NetworkFileSystem.
|
178
177
|
|
179
178
|
DEPRECATED: This method is deprecated in favor of `modal.NetworkFileSystem.from_name`.
|
180
179
|
|
@@ -222,7 +221,6 @@ class _NetworkFileSystem(_Object, type_prefix="sv"):
|
|
222
221
|
return resp.shared_volume_id
|
223
222
|
|
224
223
|
@staticmethod
|
225
|
-
@renamed_parameter((2024, 12, 18), "label", "name")
|
226
224
|
async def delete(name: str, client: Optional[_Client] = None, environment_name: Optional[str] = None):
|
227
225
|
obj = await _NetworkFileSystem.from_name(name, environment_name=environment_name).hydrate(client)
|
228
226
|
req = api_pb2.SharedVolumeDeleteRequest(shared_volume_id=obj.object_id)
|
modal/object.pyi
CHANGED
@@ -124,12 +124,6 @@ class Object:
|
|
124
124
|
@property
|
125
125
|
def deps(self) -> collections.abc.Callable[..., collections.abc.Sequence[Object]]: ...
|
126
126
|
|
127
|
-
class __resolve_spec(typing_extensions.Protocol[SUPERSELF]):
|
128
|
-
def __call__(self, /, client: typing.Optional[modal.client.Client] = None): ...
|
129
|
-
async def aio(self, /, client: typing.Optional[modal.client.Client] = None): ...
|
130
|
-
|
131
|
-
resolve: __resolve_spec[typing_extensions.Self]
|
132
|
-
|
133
127
|
class __hydrate_spec(typing_extensions.Protocol[SUPERSELF]):
|
134
128
|
def __call__(self, /, client: typing.Optional[modal.client.Client] = None) -> SUPERSELF: ...
|
135
129
|
async def aio(self, /, client: typing.Optional[modal.client.Client] = None) -> SUPERSELF: ...
|
modal/queue.py
CHANGED
@@ -14,7 +14,7 @@ from ._object import EPHEMERAL_OBJECT_HEARTBEAT_SLEEP, _get_environment_name, _O
|
|
14
14
|
from ._resolver import Resolver
|
15
15
|
from ._serialization import deserialize, serialize
|
16
16
|
from ._utils.async_utils import TaskContext, synchronize_api, warn_if_generator_is_not_consumed
|
17
|
-
from ._utils.deprecation import deprecation_warning
|
17
|
+
from ._utils.deprecation import deprecation_warning
|
18
18
|
from ._utils.grpc_utils import retry_transient_errors
|
19
19
|
from ._utils.name_utils import check_object_name
|
20
20
|
from .client import _Client
|
@@ -145,7 +145,6 @@ class _Queue(_Object, type_prefix="qu"):
|
|
145
145
|
yield cls._new_hydrated(response.queue_id, client, None, is_another_app=True)
|
146
146
|
|
147
147
|
@staticmethod
|
148
|
-
@renamed_parameter((2024, 12, 18), "label", "name")
|
149
148
|
def from_name(
|
150
149
|
name: str,
|
151
150
|
*,
|
@@ -179,7 +178,6 @@ class _Queue(_Object, type_prefix="qu"):
|
|
179
178
|
return _Queue._from_loader(_load, "Queue()", is_another_app=True, hydrate_lazily=True)
|
180
179
|
|
181
180
|
@staticmethod
|
182
|
-
@renamed_parameter((2024, 12, 18), "label", "name")
|
183
181
|
async def lookup(
|
184
182
|
name: str,
|
185
183
|
namespace=api_pb2.DEPLOYMENT_NAMESPACE_WORKSPACE,
|
@@ -187,7 +185,8 @@ class _Queue(_Object, type_prefix="qu"):
|
|
187
185
|
environment_name: Optional[str] = None,
|
188
186
|
create_if_missing: bool = False,
|
189
187
|
) -> "_Queue":
|
190
|
-
"""
|
188
|
+
"""mdmd:hidden
|
189
|
+
Lookup a named Queue.
|
191
190
|
|
192
191
|
DEPRECATED: This method is deprecated in favor of `modal.Queue.from_name`.
|
193
192
|
|
@@ -215,7 +214,6 @@ class _Queue(_Object, type_prefix="qu"):
|
|
215
214
|
return obj
|
216
215
|
|
217
216
|
@staticmethod
|
218
|
-
@renamed_parameter((2024, 12, 18), "label", "name")
|
219
217
|
async def delete(name: str, *, client: Optional[_Client] = None, environment_name: Optional[str] = None):
|
220
218
|
obj = await _Queue.from_name(name, environment_name=environment_name).hydrate(client)
|
221
219
|
req = api_pb2.QueueDeleteRequest(queue_id=obj.object_id)
|
modal/runner.py
CHANGED
@@ -27,7 +27,6 @@ from ._pty import get_pty_info
|
|
27
27
|
from ._resolver import Resolver
|
28
28
|
from ._traceback import print_server_warnings, traceback_contains_remote_call
|
29
29
|
from ._utils.async_utils import TaskContext, gather_cancel_on_exc, synchronize_api
|
30
|
-
from ._utils.deprecation import deprecation_error
|
31
30
|
from ._utils.git_utils import get_git_commit_info
|
32
31
|
from ._utils.grpc_utils import retry_transient_errors
|
33
32
|
from ._utils.name_utils import check_object_name, is_valid_tag
|
@@ -602,8 +601,9 @@ async def _interactive_shell(
|
|
602
601
|
"MODAL_ENVIRONMENT": _get_environment_name(),
|
603
602
|
}
|
604
603
|
secrets = kwargs.pop("secrets", []) + [_Secret.from_dict(sandbox_env)]
|
604
|
+
|
605
605
|
with enable_output(): # show any image build logs
|
606
|
-
sandbox = await _Sandbox.
|
606
|
+
sandbox = await _Sandbox._create(
|
607
607
|
"sleep",
|
608
608
|
"100000",
|
609
609
|
app=_app,
|
@@ -632,24 +632,7 @@ async def _interactive_shell(
|
|
632
632
|
raise
|
633
633
|
|
634
634
|
|
635
|
-
def _run_stub(*args: Any, **kwargs: Any):
|
636
|
-
"""mdmd:hidden
|
637
|
-
`run_stub` has been renamed to `run_app` and is deprecated. Please update your code.
|
638
|
-
"""
|
639
|
-
deprecation_error(
|
640
|
-
(2024, 5, 1), "`run_stub` has been renamed to `run_app` and is deprecated. Please update your code."
|
641
|
-
)
|
642
|
-
|
643
|
-
|
644
|
-
def _deploy_stub(*args: Any, **kwargs: Any):
|
645
|
-
"""mdmd:hidden"""
|
646
|
-
message = "`deploy_stub` has been renamed to `deploy_app`. Please update your code."
|
647
|
-
deprecation_error((2024, 5, 1), message)
|
648
|
-
|
649
|
-
|
650
635
|
run_app = synchronize_api(_run_app)
|
651
636
|
serve_update = synchronize_api(_serve_update)
|
652
637
|
deploy_app = synchronize_api(_deploy_app)
|
653
638
|
interactive_shell = synchronize_api(_interactive_shell)
|
654
|
-
run_stub = synchronize_api(_run_stub)
|
655
|
-
deploy_stub = synchronize_api(_deploy_stub)
|
modal/runner.pyi
CHANGED
@@ -83,8 +83,6 @@ async def _deploy_app(
|
|
83
83
|
async def _interactive_shell(
|
84
84
|
_app: _App, cmds: list[str], environment_name: str = "", pty: bool = True, **kwargs: typing.Any
|
85
85
|
) -> None: ...
|
86
|
-
def _run_stub(*args: typing.Any, **kwargs: typing.Any): ...
|
87
|
-
def _deploy_stub(*args: typing.Any, **kwargs: typing.Any): ...
|
88
86
|
|
89
87
|
class __run_app_spec(typing_extensions.Protocol):
|
90
88
|
def __call__(
|
@@ -153,6 +151,3 @@ class __interactive_shell_spec(typing_extensions.Protocol):
|
|
153
151
|
) -> None: ...
|
154
152
|
|
155
153
|
interactive_shell: __interactive_shell_spec
|
156
|
-
|
157
|
-
def run_stub(*args: typing.Any, **kwargs: typing.Any): ...
|
158
|
-
def deploy_stub(*args: typing.Any, **kwargs: typing.Any): ...
|
modal/sandbox.py
CHANGED
@@ -12,6 +12,7 @@ from grpclib import GRPCError, Status
|
|
12
12
|
|
13
13
|
from modal._tunnel import Tunnel
|
14
14
|
from modal.cloud_bucket_mount import _CloudBucketMount, cloud_bucket_mounts_to_proto
|
15
|
+
from modal.mount import _Mount
|
15
16
|
from modal.volume import _Volume
|
16
17
|
from modal_proto import api_pb2
|
17
18
|
|
@@ -19,7 +20,6 @@ from ._object import _get_environment_name, _Object
|
|
19
20
|
from ._resolver import Resolver
|
20
21
|
from ._resources import convert_fn_config_to_resources_config
|
21
22
|
from ._utils.async_utils import TaskContext, synchronize_api
|
22
|
-
from ._utils.deprecation import deprecation_error
|
23
23
|
from ._utils.grpc_utils import retry_transient_errors
|
24
24
|
from ._utils.mount_utils import validate_network_file_systems, validate_volumes
|
25
25
|
from .client import _Client
|
@@ -30,7 +30,6 @@ from .file_io import FileWatchEvent, FileWatchEventType, _FileIO
|
|
30
30
|
from .gpu import GPU_T
|
31
31
|
from .image import _Image
|
32
32
|
from .io_streams import StreamReader, StreamWriter, _StreamReader, _StreamWriter
|
33
|
-
from .mount import _Mount
|
34
33
|
from .network_file_system import _NetworkFileSystem, network_file_system_mount_protos
|
35
34
|
from .proxy import _Proxy
|
36
35
|
from .scheduler_placement import SchedulerPlacement
|
@@ -86,7 +85,6 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
86
85
|
def _new(
|
87
86
|
entrypoint_args: Sequence[str],
|
88
87
|
image: _Image,
|
89
|
-
mounts: Sequence[_Mount],
|
90
88
|
secrets: Sequence[_Secret],
|
91
89
|
timeout: Optional[int] = None,
|
92
90
|
workdir: Optional[str] = None,
|
@@ -95,6 +93,7 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
95
93
|
region: Optional[Union[str, Sequence[str]]] = None,
|
96
94
|
cpu: Optional[float] = None,
|
97
95
|
memory: Optional[Union[int, tuple[int, int]]] = None,
|
96
|
+
mounts: Sequence[_Mount] = (),
|
98
97
|
network_file_systems: dict[Union[str, os.PathLike], _NetworkFileSystem] = {},
|
99
98
|
block_network: bool = False,
|
100
99
|
cidr_allowlist: Optional[Sequence[str]] = None,
|
@@ -218,7 +217,6 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
218
217
|
app: Optional["modal.app._App"] = None, # Optionally associate the sandbox with an app
|
219
218
|
environment_name: Optional[str] = None, # Optionally override the default environment
|
220
219
|
image: Optional[_Image] = None, # The image to run as the container for the sandbox.
|
221
|
-
mounts: Sequence[_Mount] = (), # Mounts to attach to the sandbox.
|
222
220
|
secrets: Sequence[_Secret] = (), # Environment variables to inject into the sandbox.
|
223
221
|
network_file_systems: dict[Union[str, os.PathLike], _NetworkFileSystem] = {},
|
224
222
|
timeout: Optional[int] = None, # Maximum execution time of the sandbox in seconds.
|
@@ -265,6 +263,76 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
265
263
|
sandbox.wait()
|
266
264
|
```
|
267
265
|
"""
|
266
|
+
return await _Sandbox._create(
|
267
|
+
*entrypoint_args,
|
268
|
+
app=app,
|
269
|
+
environment_name=environment_name,
|
270
|
+
image=image,
|
271
|
+
secrets=secrets,
|
272
|
+
network_file_systems=network_file_systems,
|
273
|
+
timeout=timeout,
|
274
|
+
workdir=workdir,
|
275
|
+
gpu=gpu,
|
276
|
+
cloud=cloud,
|
277
|
+
region=region,
|
278
|
+
cpu=cpu,
|
279
|
+
memory=memory,
|
280
|
+
block_network=block_network,
|
281
|
+
cidr_allowlist=cidr_allowlist,
|
282
|
+
volumes=volumes,
|
283
|
+
pty_info=pty_info,
|
284
|
+
encrypted_ports=encrypted_ports,
|
285
|
+
unencrypted_ports=unencrypted_ports,
|
286
|
+
proxy=proxy,
|
287
|
+
_experimental_enable_snapshot=_experimental_enable_snapshot,
|
288
|
+
_experimental_scheduler_placement=_experimental_scheduler_placement,
|
289
|
+
client=client,
|
290
|
+
)
|
291
|
+
|
292
|
+
@staticmethod
|
293
|
+
async def _create(
|
294
|
+
*entrypoint_args: str,
|
295
|
+
app: Optional["modal.app._App"] = None, # Optionally associate the sandbox with an app
|
296
|
+
environment_name: Optional[str] = None, # Optionally override the default environment
|
297
|
+
image: Optional[_Image] = None, # The image to run as the container for the sandbox.
|
298
|
+
secrets: Sequence[_Secret] = (), # Environment variables to inject into the sandbox.
|
299
|
+
mounts: Sequence[_Mount] = (),
|
300
|
+
network_file_systems: dict[Union[str, os.PathLike], _NetworkFileSystem] = {},
|
301
|
+
timeout: Optional[int] = None, # Maximum execution time of the sandbox in seconds.
|
302
|
+
workdir: Optional[str] = None, # Working directory of the sandbox.
|
303
|
+
gpu: GPU_T = None,
|
304
|
+
cloud: Optional[str] = None,
|
305
|
+
region: Optional[Union[str, Sequence[str]]] = None, # Region or regions to run the sandbox on.
|
306
|
+
# Specify, in fractional CPU cores, how many CPU cores to request.
|
307
|
+
# Or, pass (request, limit) to additionally specify a hard limit in fractional CPU cores.
|
308
|
+
# CPU throttling will prevent a container from exceeding its specified limit.
|
309
|
+
cpu: Optional[Union[float, tuple[float, float]]] = None,
|
310
|
+
# Specify, in MiB, a memory request which is the minimum memory required.
|
311
|
+
# Or, pass (request, limit) to additionally specify a hard limit in MiB.
|
312
|
+
memory: Optional[Union[int, tuple[int, int]]] = None,
|
313
|
+
block_network: bool = False, # Whether to block network access
|
314
|
+
# List of CIDRs the sandbox is allowed to access. If None, all CIDRs are allowed.
|
315
|
+
cidr_allowlist: Optional[Sequence[str]] = None,
|
316
|
+
volumes: dict[
|
317
|
+
Union[str, os.PathLike], Union[_Volume, _CloudBucketMount]
|
318
|
+
] = {}, # Mount points for Modal Volumes and CloudBucketMounts
|
319
|
+
pty_info: Optional[api_pb2.PTYInfo] = None,
|
320
|
+
# List of ports to tunnel into the sandbox. Encrypted ports are tunneled with TLS.
|
321
|
+
encrypted_ports: Sequence[int] = [],
|
322
|
+
# List of ports to tunnel into the sandbox without encryption.
|
323
|
+
unencrypted_ports: Sequence[int] = [],
|
324
|
+
# Reference to a Modal Proxy to use in front of this Sandbox.
|
325
|
+
proxy: Optional[_Proxy] = None,
|
326
|
+
# Enable memory snapshots.
|
327
|
+
_experimental_enable_snapshot: bool = False,
|
328
|
+
_experimental_scheduler_placement: Optional[
|
329
|
+
SchedulerPlacement
|
330
|
+
] = None, # Experimental controls over fine-grained scheduling (alpha).
|
331
|
+
client: Optional[_Client] = None,
|
332
|
+
):
|
333
|
+
# This method exposes some internal arguments (currently `mounts`) which are not in the public API
|
334
|
+
# `mounts` is currently only used by modal shell (cli) to provide a function's mounts to the
|
335
|
+
# sandbox that runs the shell session
|
268
336
|
from .app import _App
|
269
337
|
|
270
338
|
environment_name = _get_environment_name(environment_name)
|
@@ -275,7 +343,6 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
275
343
|
obj = _Sandbox._new(
|
276
344
|
entrypoint_args,
|
277
345
|
image=image or _default_image,
|
278
|
-
mounts=mounts,
|
279
346
|
secrets=secrets,
|
280
347
|
timeout=timeout,
|
281
348
|
workdir=workdir,
|
@@ -284,6 +351,7 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
284
351
|
region=region,
|
285
352
|
cpu=cpu,
|
286
353
|
memory=memory,
|
354
|
+
mounts=mounts,
|
287
355
|
network_file_systems=network_file_systems,
|
288
356
|
block_network=block_network,
|
289
357
|
cidr_allowlist=cidr_allowlist,
|
@@ -315,14 +383,12 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
315
383
|
app_id = container_app.app_id
|
316
384
|
app_client = container_app._client
|
317
385
|
else:
|
318
|
-
|
319
|
-
|
320
|
-
(
|
321
|
-
"Creating a `Sandbox` without an `App` is deprecated.\n\n"
|
322
|
-
"You may pass in an `App` object, or reference one by name with `App.lookup`:\n\n"
|
386
|
+
raise InvalidError(
|
387
|
+
"Sandboxes require an App when created outside of a Modal container.\n\n"
|
388
|
+
"Run an ephemeral App (`with app.run(): ...`), or reference a deployed App using `App.lookup`:\n\n"
|
323
389
|
"```\n"
|
324
|
-
|
325
|
-
|
390
|
+
'app = modal.App.lookup("sandbox-app", create_if_missing=True)\n'
|
391
|
+
"sb = modal.Sandbox.create(..., app=app)\n"
|
326
392
|
"```",
|
327
393
|
)
|
328
394
|
|
@@ -762,23 +828,3 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
762
828
|
|
763
829
|
|
764
830
|
Sandbox = synchronize_api(_Sandbox)
|
765
|
-
|
766
|
-
|
767
|
-
def __getattr__(name):
|
768
|
-
if name == "LogsReader":
|
769
|
-
deprecation_error(
|
770
|
-
(2024, 8, 12),
|
771
|
-
"`modal.sandbox.LogsReader` is deprecated. Please import `modal.io_streams.StreamReader` instead.",
|
772
|
-
)
|
773
|
-
from .io_streams import StreamReader
|
774
|
-
|
775
|
-
return StreamReader
|
776
|
-
elif name == "StreamWriter":
|
777
|
-
deprecation_error(
|
778
|
-
(2024, 8, 12),
|
779
|
-
"`modal.sandbox.StreamWriter` is deprecated. Please import `modal.io_streams.StreamWriter` instead.",
|
780
|
-
)
|
781
|
-
from .io_streams import StreamWriter
|
782
|
-
|
783
|
-
return StreamWriter
|
784
|
-
raise AttributeError(f"module {__name__} has no attribute {name}")
|
modal/sandbox.pyi
CHANGED
@@ -40,7 +40,6 @@ class _Sandbox(modal._object._Object):
|
|
40
40
|
def _new(
|
41
41
|
entrypoint_args: collections.abc.Sequence[str],
|
42
42
|
image: modal.image._Image,
|
43
|
-
mounts: collections.abc.Sequence[modal.mount._Mount],
|
44
43
|
secrets: collections.abc.Sequence[modal.secret._Secret],
|
45
44
|
timeout: typing.Optional[int] = None,
|
46
45
|
workdir: typing.Optional[str] = None,
|
@@ -49,6 +48,7 @@ class _Sandbox(modal._object._Object):
|
|
49
48
|
region: typing.Union[str, collections.abc.Sequence[str], None] = None,
|
50
49
|
cpu: typing.Optional[float] = None,
|
51
50
|
memory: typing.Union[int, tuple[int, int], None] = None,
|
51
|
+
mounts: collections.abc.Sequence[modal.mount._Mount] = (),
|
52
52
|
network_file_systems: dict[typing.Union[str, os.PathLike], modal.network_file_system._NetworkFileSystem] = {},
|
53
53
|
block_network: bool = False,
|
54
54
|
cidr_allowlist: typing.Optional[collections.abc.Sequence[str]] = None,
|
@@ -69,7 +69,6 @@ class _Sandbox(modal._object._Object):
|
|
69
69
|
app: typing.Optional[modal.app._App] = None,
|
70
70
|
environment_name: typing.Optional[str] = None,
|
71
71
|
image: typing.Optional[modal.image._Image] = None,
|
72
|
-
mounts: collections.abc.Sequence[modal.mount._Mount] = (),
|
73
72
|
secrets: collections.abc.Sequence[modal.secret._Secret] = (),
|
74
73
|
network_file_systems: dict[typing.Union[str, os.PathLike], modal.network_file_system._NetworkFileSystem] = {},
|
75
74
|
timeout: typing.Optional[int] = None,
|
@@ -93,6 +92,36 @@ class _Sandbox(modal._object._Object):
|
|
93
92
|
_experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
|
94
93
|
client: typing.Optional[modal.client._Client] = None,
|
95
94
|
) -> _Sandbox: ...
|
95
|
+
@staticmethod
|
96
|
+
async def _create(
|
97
|
+
*entrypoint_args: str,
|
98
|
+
app: typing.Optional[modal.app._App] = None,
|
99
|
+
environment_name: typing.Optional[str] = None,
|
100
|
+
image: typing.Optional[modal.image._Image] = None,
|
101
|
+
secrets: collections.abc.Sequence[modal.secret._Secret] = (),
|
102
|
+
mounts: collections.abc.Sequence[modal.mount._Mount] = (),
|
103
|
+
network_file_systems: dict[typing.Union[str, os.PathLike], modal.network_file_system._NetworkFileSystem] = {},
|
104
|
+
timeout: typing.Optional[int] = None,
|
105
|
+
workdir: typing.Optional[str] = None,
|
106
|
+
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
107
|
+
cloud: typing.Optional[str] = None,
|
108
|
+
region: typing.Union[str, collections.abc.Sequence[str], None] = None,
|
109
|
+
cpu: typing.Union[float, tuple[float, float], None] = None,
|
110
|
+
memory: typing.Union[int, tuple[int, int], None] = None,
|
111
|
+
block_network: bool = False,
|
112
|
+
cidr_allowlist: typing.Optional[collections.abc.Sequence[str]] = None,
|
113
|
+
volumes: dict[
|
114
|
+
typing.Union[str, os.PathLike],
|
115
|
+
typing.Union[modal.volume._Volume, modal.cloud_bucket_mount._CloudBucketMount],
|
116
|
+
] = {},
|
117
|
+
pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
|
118
|
+
encrypted_ports: collections.abc.Sequence[int] = [],
|
119
|
+
unencrypted_ports: collections.abc.Sequence[int] = [],
|
120
|
+
proxy: typing.Optional[modal.proxy._Proxy] = None,
|
121
|
+
_experimental_enable_snapshot: bool = False,
|
122
|
+
_experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
|
123
|
+
client: typing.Optional[modal.client._Client] = None,
|
124
|
+
): ...
|
96
125
|
def _hydrate_metadata(self, handle_metadata: typing.Optional[google.protobuf.message.Message]): ...
|
97
126
|
@staticmethod
|
98
127
|
async def from_id(sandbox_id: str, client: typing.Optional[modal.client._Client] = None) -> _Sandbox: ...
|
@@ -182,7 +211,6 @@ class Sandbox(modal.object.Object):
|
|
182
211
|
def _new(
|
183
212
|
entrypoint_args: collections.abc.Sequence[str],
|
184
213
|
image: modal.image.Image,
|
185
|
-
mounts: collections.abc.Sequence[modal.mount.Mount],
|
186
214
|
secrets: collections.abc.Sequence[modal.secret.Secret],
|
187
215
|
timeout: typing.Optional[int] = None,
|
188
216
|
workdir: typing.Optional[str] = None,
|
@@ -191,6 +219,7 @@ class Sandbox(modal.object.Object):
|
|
191
219
|
region: typing.Union[str, collections.abc.Sequence[str], None] = None,
|
192
220
|
cpu: typing.Optional[float] = None,
|
193
221
|
memory: typing.Union[int, tuple[int, int], None] = None,
|
222
|
+
mounts: collections.abc.Sequence[modal.mount.Mount] = (),
|
194
223
|
network_file_systems: dict[typing.Union[str, os.PathLike], modal.network_file_system.NetworkFileSystem] = {},
|
195
224
|
block_network: bool = False,
|
196
225
|
cidr_allowlist: typing.Optional[collections.abc.Sequence[str]] = None,
|
@@ -213,7 +242,6 @@ class Sandbox(modal.object.Object):
|
|
213
242
|
app: typing.Optional[modal.app.App] = None,
|
214
243
|
environment_name: typing.Optional[str] = None,
|
215
244
|
image: typing.Optional[modal.image.Image] = None,
|
216
|
-
mounts: collections.abc.Sequence[modal.mount.Mount] = (),
|
217
245
|
secrets: collections.abc.Sequence[modal.secret.Secret] = (),
|
218
246
|
network_file_systems: dict[
|
219
247
|
typing.Union[str, os.PathLike], modal.network_file_system.NetworkFileSystem
|
@@ -246,7 +274,6 @@ class Sandbox(modal.object.Object):
|
|
246
274
|
app: typing.Optional[modal.app.App] = None,
|
247
275
|
environment_name: typing.Optional[str] = None,
|
248
276
|
image: typing.Optional[modal.image.Image] = None,
|
249
|
-
mounts: collections.abc.Sequence[modal.mount.Mount] = (),
|
250
277
|
secrets: collections.abc.Sequence[modal.secret.Secret] = (),
|
251
278
|
network_file_systems: dict[
|
252
279
|
typing.Union[str, os.PathLike], modal.network_file_system.NetworkFileSystem
|
@@ -275,6 +302,76 @@ class Sandbox(modal.object.Object):
|
|
275
302
|
|
276
303
|
create: __create_spec
|
277
304
|
|
305
|
+
class ___create_spec(typing_extensions.Protocol):
|
306
|
+
def __call__(
|
307
|
+
self,
|
308
|
+
/,
|
309
|
+
*entrypoint_args: str,
|
310
|
+
app: typing.Optional[modal.app.App] = None,
|
311
|
+
environment_name: typing.Optional[str] = None,
|
312
|
+
image: typing.Optional[modal.image.Image] = None,
|
313
|
+
secrets: collections.abc.Sequence[modal.secret.Secret] = (),
|
314
|
+
mounts: collections.abc.Sequence[modal.mount.Mount] = (),
|
315
|
+
network_file_systems: dict[
|
316
|
+
typing.Union[str, os.PathLike], modal.network_file_system.NetworkFileSystem
|
317
|
+
] = {},
|
318
|
+
timeout: typing.Optional[int] = None,
|
319
|
+
workdir: typing.Optional[str] = None,
|
320
|
+
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
321
|
+
cloud: typing.Optional[str] = None,
|
322
|
+
region: typing.Union[str, collections.abc.Sequence[str], None] = None,
|
323
|
+
cpu: typing.Union[float, tuple[float, float], None] = None,
|
324
|
+
memory: typing.Union[int, tuple[int, int], None] = None,
|
325
|
+
block_network: bool = False,
|
326
|
+
cidr_allowlist: typing.Optional[collections.abc.Sequence[str]] = None,
|
327
|
+
volumes: dict[
|
328
|
+
typing.Union[str, os.PathLike],
|
329
|
+
typing.Union[modal.volume.Volume, modal.cloud_bucket_mount.CloudBucketMount],
|
330
|
+
] = {},
|
331
|
+
pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
|
332
|
+
encrypted_ports: collections.abc.Sequence[int] = [],
|
333
|
+
unencrypted_ports: collections.abc.Sequence[int] = [],
|
334
|
+
proxy: typing.Optional[modal.proxy.Proxy] = None,
|
335
|
+
_experimental_enable_snapshot: bool = False,
|
336
|
+
_experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
|
337
|
+
client: typing.Optional[modal.client.Client] = None,
|
338
|
+
): ...
|
339
|
+
async def aio(
|
340
|
+
self,
|
341
|
+
/,
|
342
|
+
*entrypoint_args: str,
|
343
|
+
app: typing.Optional[modal.app.App] = None,
|
344
|
+
environment_name: typing.Optional[str] = None,
|
345
|
+
image: typing.Optional[modal.image.Image] = None,
|
346
|
+
secrets: collections.abc.Sequence[modal.secret.Secret] = (),
|
347
|
+
mounts: collections.abc.Sequence[modal.mount.Mount] = (),
|
348
|
+
network_file_systems: dict[
|
349
|
+
typing.Union[str, os.PathLike], modal.network_file_system.NetworkFileSystem
|
350
|
+
] = {},
|
351
|
+
timeout: typing.Optional[int] = None,
|
352
|
+
workdir: typing.Optional[str] = None,
|
353
|
+
gpu: typing.Union[None, str, modal.gpu._GPUConfig] = None,
|
354
|
+
cloud: typing.Optional[str] = None,
|
355
|
+
region: typing.Union[str, collections.abc.Sequence[str], None] = None,
|
356
|
+
cpu: typing.Union[float, tuple[float, float], None] = None,
|
357
|
+
memory: typing.Union[int, tuple[int, int], None] = None,
|
358
|
+
block_network: bool = False,
|
359
|
+
cidr_allowlist: typing.Optional[collections.abc.Sequence[str]] = None,
|
360
|
+
volumes: dict[
|
361
|
+
typing.Union[str, os.PathLike],
|
362
|
+
typing.Union[modal.volume.Volume, modal.cloud_bucket_mount.CloudBucketMount],
|
363
|
+
] = {},
|
364
|
+
pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
|
365
|
+
encrypted_ports: collections.abc.Sequence[int] = [],
|
366
|
+
unencrypted_ports: collections.abc.Sequence[int] = [],
|
367
|
+
proxy: typing.Optional[modal.proxy.Proxy] = None,
|
368
|
+
_experimental_enable_snapshot: bool = False,
|
369
|
+
_experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
|
370
|
+
client: typing.Optional[modal.client.Client] = None,
|
371
|
+
): ...
|
372
|
+
|
373
|
+
_create: ___create_spec
|
374
|
+
|
278
375
|
def _hydrate_metadata(self, handle_metadata: typing.Optional[google.protobuf.message.Message]): ...
|
279
376
|
|
280
377
|
class __from_id_spec(typing_extensions.Protocol):
|
@@ -484,6 +581,4 @@ class Sandbox(modal.object.Object):
|
|
484
581
|
|
485
582
|
list: __list_spec
|
486
583
|
|
487
|
-
def __getattr__(name): ...
|
488
|
-
|
489
584
|
_default_image: modal.image._Image
|
modal/secret.py
CHANGED
@@ -10,7 +10,7 @@ from ._object import _get_environment_name, _Object
|
|
10
10
|
from ._resolver import Resolver
|
11
11
|
from ._runtime.execution_context import is_local
|
12
12
|
from ._utils.async_utils import synchronize_api
|
13
|
-
from ._utils.deprecation import deprecation_warning
|
13
|
+
from ._utils.deprecation import deprecation_warning
|
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
|
@@ -162,7 +162,6 @@ class _Secret(_Object, type_prefix="st"):
|
|
162
162
|
return _Secret._from_loader(_load, "Secret.from_dotenv()", hydrate_lazily=True)
|
163
163
|
|
164
164
|
@staticmethod
|
165
|
-
@renamed_parameter((2024, 12, 18), "label", "name")
|
166
165
|
def from_name(
|
167
166
|
name: str,
|
168
167
|
*,
|
@@ -206,7 +205,6 @@ class _Secret(_Object, type_prefix="st"):
|
|
206
205
|
return _Secret._from_loader(_load, "Secret()", hydrate_lazily=True)
|
207
206
|
|
208
207
|
@staticmethod
|
209
|
-
@renamed_parameter((2024, 12, 18), "label", "name")
|
210
208
|
async def lookup(
|
211
209
|
name: str,
|
212
210
|
namespace=api_pb2.DEPLOYMENT_NAMESPACE_WORKSPACE,
|
modal/serving.py
CHANGED
@@ -11,7 +11,6 @@ from synchronicity.async_wrap import asynccontextmanager
|
|
11
11
|
from modal._output import OutputManager
|
12
12
|
|
13
13
|
from ._utils.async_utils import TaskContext, asyncify, synchronize_api, synchronizer
|
14
|
-
from ._utils.deprecation import deprecation_error
|
15
14
|
from ._utils.logger import logger
|
16
15
|
from ._watcher import watch
|
17
16
|
from .cli.import_refs import ImportRef, import_app_from_ref
|
@@ -122,9 +121,4 @@ async def _serve_app(
|
|
122
121
|
yield app
|
123
122
|
|
124
123
|
|
125
|
-
def _serve_stub(*args, **kwargs):
|
126
|
-
deprecation_error((2024, 5, 1), "`serve_stub` is deprecated. Please use `serve_app` instead.")
|
127
|
-
|
128
|
-
|
129
124
|
serve_app = synchronize_api(_serve_app)
|
130
|
-
serve_stub = synchronize_api(_serve_stub)
|
modal/serving.pyi
CHANGED
@@ -33,7 +33,6 @@ def _serve_app(
|
|
33
33
|
_watcher: typing.Optional[collections.abc.AsyncGenerator[set[str], None]] = None,
|
34
34
|
environment_name: typing.Optional[str] = None,
|
35
35
|
) -> typing.AsyncContextManager[_App]: ...
|
36
|
-
def _serve_stub(*args, **kwargs): ...
|
37
36
|
|
38
37
|
class __serve_app_spec(typing_extensions.Protocol):
|
39
38
|
def __call__(
|
@@ -56,5 +55,3 @@ class __serve_app_spec(typing_extensions.Protocol):
|
|
56
55
|
) -> typing.AsyncContextManager[_App]: ...
|
57
56
|
|
58
57
|
serve_app: __serve_app_spec
|
59
|
-
|
60
|
-
def serve_stub(*args, **kwargs): ...
|
modal/volume.py
CHANGED
@@ -27,7 +27,7 @@ from grpclib import GRPCError, Status
|
|
27
27
|
from synchronicity.async_wrap import asynccontextmanager
|
28
28
|
|
29
29
|
import modal_proto.api_pb2
|
30
|
-
from modal.exception import VolumeUploadTimeoutError
|
30
|
+
from modal.exception import InvalidError, VolumeUploadTimeoutError
|
31
31
|
from modal_proto import api_pb2
|
32
32
|
|
33
33
|
from ._object import EPHEMERAL_OBJECT_HEARTBEAT_SLEEP, _get_environment_name, _Object, live_method, live_method_gen
|
@@ -49,7 +49,7 @@ from ._utils.blob_utils import (
|
|
49
49
|
get_file_upload_spec_from_fileobj,
|
50
50
|
get_file_upload_spec_from_path,
|
51
51
|
)
|
52
|
-
from ._utils.deprecation import
|
52
|
+
from ._utils.deprecation import deprecation_warning
|
53
53
|
from ._utils.grpc_utils import retry_transient_errors
|
54
54
|
from ._utils.http_utils import ClientSessionRegistry
|
55
55
|
from ._utils.name_utils import check_object_name
|
@@ -149,7 +149,6 @@ class _Volume(_Object, type_prefix="vo"):
|
|
149
149
|
return self._lock
|
150
150
|
|
151
151
|
@staticmethod
|
152
|
-
@renamed_parameter((2024, 12, 18), "label", "name")
|
153
152
|
def from_name(
|
154
153
|
name: str,
|
155
154
|
*,
|
@@ -244,7 +243,6 @@ class _Volume(_Object, type_prefix="vo"):
|
|
244
243
|
yield cls._new_hydrated(response.volume_id, client, response.metadata, is_another_app=True)
|
245
244
|
|
246
245
|
@staticmethod
|
247
|
-
@renamed_parameter((2024, 12, 18), "label", "name")
|
248
246
|
async def lookup(
|
249
247
|
name: str,
|
250
248
|
namespace=api_pb2.DEPLOYMENT_NAMESPACE_WORKSPACE,
|
@@ -253,7 +251,8 @@ class _Volume(_Object, type_prefix="vo"):
|
|
253
251
|
create_if_missing: bool = False,
|
254
252
|
version: "typing.Optional[modal_proto.api_pb2.VolumeFsVersion.ValueType]" = None,
|
255
253
|
) -> "_Volume":
|
256
|
-
"""
|
254
|
+
"""mdmd:hidden
|
255
|
+
Lookup a named Volume.
|
257
256
|
|
258
257
|
DEPRECATED: This method is deprecated in favor of `modal.Volume.from_name`.
|
259
258
|
|
@@ -366,21 +365,14 @@ class _Volume(_Object, type_prefix="vo"):
|
|
366
365
|
recursively.
|
367
366
|
"""
|
368
367
|
if path.endswith("**"):
|
369
|
-
|
368
|
+
raise InvalidError(
|
370
369
|
"Glob patterns in `volume get` and `Volume.listdir()` are deprecated. "
|
371
370
|
"Please pass recursive=True instead. For the CLI, just remove the glob suffix."
|
372
371
|
)
|
373
|
-
deprecation_error(
|
374
|
-
(2024, 4, 23),
|
375
|
-
msg,
|
376
|
-
)
|
377
372
|
elif path.endswith("*"):
|
378
|
-
|
379
|
-
(
|
380
|
-
|
381
|
-
"Glob patterns in `volume get` and `Volume.listdir()` are deprecated. "
|
382
|
-
"Please remove the glob `*` suffix."
|
383
|
-
),
|
373
|
+
raise InvalidError(
|
374
|
+
"Glob patterns in `volume get` and `Volume.listdir()` are deprecated. "
|
375
|
+
"Please remove the glob `*` suffix."
|
384
376
|
)
|
385
377
|
|
386
378
|
req = api_pb2.VolumeListFilesRequest(volume_id=self.object_id, path=path, recursive=recursive)
|
@@ -595,7 +587,6 @@ class _Volume(_Object, type_prefix="vo"):
|
|
595
587
|
)
|
596
588
|
|
597
589
|
@staticmethod
|
598
|
-
@renamed_parameter((2024, 12, 18), "label", "name")
|
599
590
|
async def delete(name: str, client: Optional[_Client] = None, environment_name: Optional[str] = None):
|
600
591
|
obj = await _Volume.from_name(name, environment_name=environment_name).hydrate(client)
|
601
592
|
req = api_pb2.VolumeDeleteRequest(volume_id=obj.object_id)
|