modal 1.2.1.dev5__tar.gz → 1.2.1.dev7__tar.gz
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-1.2.1.dev5 → modal-1.2.1.dev7}/PKG-INFO +1 -1
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/cli/_download.py +19 -3
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/cli/volume.py +7 -1
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/client.pyi +2 -2
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/functions.pyi +6 -6
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/runner.py +11 -9
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/volume.py +21 -3
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/volume.pyi +30 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal.egg-info/PKG-INFO +1 -1
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal_version/__init__.py +1 -1
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/LICENSE +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/README.md +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/__init__.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/__main__.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_billing.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_clustered_functions.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_clustered_functions.pyi +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_container_entrypoint.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_functions.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_ipython.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_location.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_object.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_output.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_partial_function.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_pty.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_resolver.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_resources.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_runtime/__init__.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_runtime/asgi.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_runtime/container_io_manager.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_runtime/container_io_manager.pyi +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_runtime/execution_context.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_runtime/execution_context.pyi +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_runtime/gpu_memory_snapshot.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_runtime/telemetry.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_runtime/user_code_imports.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_serialization.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_traceback.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_tunnel.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_tunnel.pyi +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_type_manager.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_utils/__init__.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_utils/app_utils.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_utils/async_utils.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_utils/auth_token_manager.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_utils/blob_utils.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_utils/bytes_io_segment_payload.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_utils/deprecation.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_utils/docker_utils.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_utils/function_utils.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_utils/git_utils.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_utils/grpc_testing.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_utils/grpc_utils.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_utils/hash_utils.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_utils/http_utils.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_utils/jwt_utils.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_utils/logger.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_utils/mount_utils.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_utils/name_utils.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_utils/package_utils.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_utils/pattern_utils.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_utils/rand_pb_testing.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_utils/shell_utils.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_utils/time_utils.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_vendor/__init__.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_vendor/a2wsgi_wsgi.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_vendor/cloudpickle.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_vendor/tblib.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/_watcher.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/app.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/app.pyi +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/billing.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/builder/2023.12.312.txt +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/builder/2023.12.txt +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/builder/2024.04.txt +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/builder/2024.10.txt +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/builder/2025.06.txt +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/builder/PREVIEW.txt +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/builder/README.md +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/builder/base-images.json +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/call_graph.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/cli/__init__.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/cli/_traceback.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/cli/app.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/cli/cluster.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/cli/config.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/cli/container.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/cli/dict.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/cli/entry_point.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/cli/environment.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/cli/import_refs.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/cli/launch.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/cli/network_file_system.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/cli/profile.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/cli/programs/__init__.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/cli/programs/launch_instance_ssh.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/cli/programs/run_jupyter.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/cli/programs/run_marimo.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/cli/programs/vscode.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/cli/queues.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/cli/run.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/cli/secret.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/cli/token.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/cli/utils.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/client.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/cloud_bucket_mount.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/cloud_bucket_mount.pyi +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/cls.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/cls.pyi +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/config.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/container_process.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/container_process.pyi +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/dict.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/dict.pyi +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/environments.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/environments.pyi +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/exception.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/experimental/__init__.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/experimental/flash.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/experimental/flash.pyi +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/experimental/ipython.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/file_io.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/file_io.pyi +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/file_pattern_matcher.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/functions.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/gpu.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/image.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/image.pyi +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/io_streams.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/io_streams.pyi +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/mount.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/mount.pyi +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/network_file_system.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/network_file_system.pyi +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/object.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/object.pyi +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/output.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/parallel_map.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/parallel_map.pyi +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/partial_function.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/partial_function.pyi +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/proxy.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/proxy.pyi +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/py.typed +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/queue.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/queue.pyi +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/retries.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/runner.pyi +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/running_app.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/sandbox.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/sandbox.pyi +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/schedule.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/scheduler_placement.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/secret.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/secret.pyi +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/serving.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/serving.pyi +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/snapshot.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/snapshot.pyi +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/stream_type.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/token_flow.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal/token_flow.pyi +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal.egg-info/SOURCES.txt +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal.egg-info/dependency_links.txt +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal.egg-info/entry_points.txt +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal.egg-info/requires.txt +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal.egg-info/top_level.txt +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal_docs/__init__.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal_docs/gen_cli_docs.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal_docs/gen_reference_docs.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal_docs/mdmd/__init__.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal_docs/mdmd/mdmd.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal_docs/mdmd/signatures.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal_proto/__init__.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal_proto/api.proto +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal_proto/api_grpc.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal_proto/api_pb2.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal_proto/api_pb2.pyi +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal_proto/api_pb2_grpc.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal_proto/api_pb2_grpc.pyi +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal_proto/modal_api_grpc.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal_proto/py.typed +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal_proto/sandbox_router.proto +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal_proto/sandbox_router_grpc.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal_proto/sandbox_router_pb2.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal_proto/sandbox_router_pb2.pyi +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal_proto/sandbox_router_pb2_grpc.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal_proto/sandbox_router_pb2_grpc.pyi +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal_proto/task_command_router.proto +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal_proto/task_command_router_grpc.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal_proto/task_command_router_pb2.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal_proto/task_command_router_pb2.pyi +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal_proto/task_command_router_pb2_grpc.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal_proto/task_command_router_pb2_grpc.pyi +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/modal_version/__main__.py +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/pyproject.toml +0 -0
- {modal-1.2.1.dev5 → modal-1.2.1.dev7}/setup.cfg +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Copyright Modal Labs 2023
|
|
2
2
|
import asyncio
|
|
3
3
|
import functools
|
|
4
|
+
import multiprocessing
|
|
4
5
|
import os
|
|
5
6
|
import shutil
|
|
6
7
|
import sys
|
|
@@ -23,12 +24,22 @@ async def _volume_download(
|
|
|
23
24
|
remote_path: str,
|
|
24
25
|
local_destination: Path,
|
|
25
26
|
overwrite: bool,
|
|
26
|
-
|
|
27
|
+
concurrency: Optional[int] = None,
|
|
28
|
+
progress_cb: Optional[Callable] = None,
|
|
27
29
|
):
|
|
30
|
+
if progress_cb is None:
|
|
31
|
+
|
|
32
|
+
def progress_cb(*_, **__):
|
|
33
|
+
pass
|
|
34
|
+
|
|
35
|
+
if concurrency is None:
|
|
36
|
+
concurrency = max(128, 2 * multiprocessing.cpu_count())
|
|
37
|
+
|
|
28
38
|
is_pipe = local_destination == PIPE_PATH
|
|
29
39
|
|
|
30
40
|
q: asyncio.Queue[tuple[Optional[Path], Optional[FileEntry]]] = asyncio.Queue()
|
|
31
|
-
num_consumers = 1 if is_pipe else
|
|
41
|
+
num_consumers = 1 if is_pipe else concurrency # concurrency limit for downloading files
|
|
42
|
+
download_semaphore = asyncio.Semaphore(concurrency)
|
|
32
43
|
|
|
33
44
|
async def producer():
|
|
34
45
|
iterator: AsyncIterator[FileEntry]
|
|
@@ -86,7 +97,12 @@ async def _volume_download(
|
|
|
86
97
|
|
|
87
98
|
with output_path.open("wb") as fp:
|
|
88
99
|
if isinstance(volume, _Volume):
|
|
89
|
-
b = await volume.
|
|
100
|
+
b = await volume._read_file_into_fileobj(
|
|
101
|
+
path=entry.path,
|
|
102
|
+
fileobj=fp,
|
|
103
|
+
download_semaphore=download_semaphore,
|
|
104
|
+
progress_cb=file_progress_cb,
|
|
105
|
+
)
|
|
90
106
|
else:
|
|
91
107
|
b = 0
|
|
92
108
|
async for chunk in volume.read_file(entry.path):
|
|
@@ -96,7 +96,13 @@ async def get(
|
|
|
96
96
|
console = make_console()
|
|
97
97
|
progress_handler = ProgressHandler(type="download", console=console)
|
|
98
98
|
with progress_handler.live:
|
|
99
|
-
await _volume_download(
|
|
99
|
+
await _volume_download(
|
|
100
|
+
volume=volume,
|
|
101
|
+
remote_path=remote_path,
|
|
102
|
+
local_destination=destination,
|
|
103
|
+
overwrite=force,
|
|
104
|
+
progress_cb=progress_handler.progress,
|
|
105
|
+
)
|
|
100
106
|
console.print(OutputManager.step_completed("Finished downloading files to local!"))
|
|
101
107
|
|
|
102
108
|
|
|
@@ -33,7 +33,7 @@ class _Client:
|
|
|
33
33
|
server_url: str,
|
|
34
34
|
client_type: int,
|
|
35
35
|
credentials: typing.Optional[tuple[str, str]],
|
|
36
|
-
version: str = "1.2.1.
|
|
36
|
+
version: str = "1.2.1.dev7",
|
|
37
37
|
):
|
|
38
38
|
"""mdmd:hidden
|
|
39
39
|
The Modal client object is not intended to be instantiated directly by users.
|
|
@@ -164,7 +164,7 @@ class Client:
|
|
|
164
164
|
server_url: str,
|
|
165
165
|
client_type: int,
|
|
166
166
|
credentials: typing.Optional[tuple[str, str]],
|
|
167
|
-
version: str = "1.2.1.
|
|
167
|
+
version: str = "1.2.1.dev7",
|
|
168
168
|
):
|
|
169
169
|
"""mdmd:hidden
|
|
170
170
|
The Modal client object is not intended to be instantiated directly by users.
|
|
@@ -401,7 +401,7 @@ class Function(
|
|
|
401
401
|
|
|
402
402
|
_call_generator: ___call_generator_spec[typing_extensions.Self]
|
|
403
403
|
|
|
404
|
-
class __remote_spec(typing_extensions.Protocol[
|
|
404
|
+
class __remote_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
|
|
405
405
|
def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER:
|
|
406
406
|
"""Calls the function remotely, executing it with the given arguments and returning the execution's result."""
|
|
407
407
|
...
|
|
@@ -410,7 +410,7 @@ class Function(
|
|
|
410
410
|
"""Calls the function remotely, executing it with the given arguments and returning the execution's result."""
|
|
411
411
|
...
|
|
412
412
|
|
|
413
|
-
remote: __remote_spec[modal._functions.
|
|
413
|
+
remote: __remote_spec[modal._functions.P, modal._functions.ReturnType, typing_extensions.Self]
|
|
414
414
|
|
|
415
415
|
class __remote_gen_spec(typing_extensions.Protocol[SUPERSELF]):
|
|
416
416
|
def __call__(self, /, *args, **kwargs) -> typing.Generator[typing.Any, None, None]:
|
|
@@ -437,7 +437,7 @@ class Function(
|
|
|
437
437
|
"""
|
|
438
438
|
...
|
|
439
439
|
|
|
440
|
-
class ___experimental_spawn_spec(typing_extensions.Protocol[
|
|
440
|
+
class ___experimental_spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
|
|
441
441
|
def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]:
|
|
442
442
|
"""[Experimental] Calls the function with the given arguments, without waiting for the results.
|
|
443
443
|
|
|
@@ -461,7 +461,7 @@ class Function(
|
|
|
461
461
|
...
|
|
462
462
|
|
|
463
463
|
_experimental_spawn: ___experimental_spawn_spec[
|
|
464
|
-
modal._functions.
|
|
464
|
+
modal._functions.P, modal._functions.ReturnType, typing_extensions.Self
|
|
465
465
|
]
|
|
466
466
|
|
|
467
467
|
class ___spawn_map_inner_spec(typing_extensions.Protocol[P_INNER, SUPERSELF]):
|
|
@@ -470,7 +470,7 @@ class Function(
|
|
|
470
470
|
|
|
471
471
|
_spawn_map_inner: ___spawn_map_inner_spec[modal._functions.P, typing_extensions.Self]
|
|
472
472
|
|
|
473
|
-
class __spawn_spec(typing_extensions.Protocol[
|
|
473
|
+
class __spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER, SUPERSELF]):
|
|
474
474
|
def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]:
|
|
475
475
|
"""Calls the function with the given arguments, without waiting for the results.
|
|
476
476
|
|
|
@@ -491,7 +491,7 @@ class Function(
|
|
|
491
491
|
"""
|
|
492
492
|
...
|
|
493
493
|
|
|
494
|
-
spawn: __spawn_spec[modal._functions.
|
|
494
|
+
spawn: __spawn_spec[modal._functions.P, modal._functions.ReturnType, typing_extensions.Self]
|
|
495
495
|
|
|
496
496
|
def get_raw_f(self) -> collections.abc.Callable[..., typing.Any]:
|
|
497
497
|
"""Return the inner Python object wrapped by this Modal Function."""
|
|
@@ -355,6 +355,14 @@ async def _run_app(
|
|
|
355
355
|
await _status_based_disconnect(client, running_app.app_id, e)
|
|
356
356
|
raise
|
|
357
357
|
|
|
358
|
+
detached_disconnect_msg = (
|
|
359
|
+
"The detached App will keep running. You can track its progress on the Dashboard: "
|
|
360
|
+
f"[magenta underline]{running_app.app_page_url}[/magenta underline]"
|
|
361
|
+
"\n"
|
|
362
|
+
f"\nStream logs: [green]modal app logs {running_app.app_id}[/green]"
|
|
363
|
+
f"\nStop the App: [green]modal app stop {running_app.app_id}[/green]"
|
|
364
|
+
)
|
|
365
|
+
|
|
358
366
|
try:
|
|
359
367
|
# Show logs from dynamically created images.
|
|
360
368
|
# TODO: better way to do this
|
|
@@ -377,11 +385,7 @@ async def _run_app(
|
|
|
377
385
|
if detach:
|
|
378
386
|
if output_mgr := _get_output_manager():
|
|
379
387
|
output_mgr.print(output_mgr.step_completed("Shutting down Modal client."))
|
|
380
|
-
output_mgr.print(
|
|
381
|
-
"The detached app keeps running. You can track its progress at: "
|
|
382
|
-
f"[magenta]{running_app.app_page_url}[/magenta]"
|
|
383
|
-
""
|
|
384
|
-
)
|
|
388
|
+
output_mgr.print(detached_disconnect_msg)
|
|
385
389
|
if logs_loop:
|
|
386
390
|
logs_loop.cancel()
|
|
387
391
|
await _status_based_disconnect(client, running_app.app_id, e)
|
|
@@ -409,10 +413,8 @@ async def _run_app(
|
|
|
409
413
|
# If we lose connection to the server after a detached App has started running, it will continue
|
|
410
414
|
# I think we can only exit "nicely" if we are able to print output though, otherwise we should raise
|
|
411
415
|
if detach and (output_mgr := _get_output_manager()):
|
|
412
|
-
output_mgr.print(
|
|
413
|
-
|
|
414
|
-
f"[magenta]{running_app.app_page_url}[/magenta]"
|
|
415
|
-
)
|
|
416
|
+
output_mgr.print(":white_exclamation_mark: Connection lost!")
|
|
417
|
+
output_mgr.print(detached_disconnect_msg)
|
|
416
418
|
return
|
|
417
419
|
raise
|
|
418
420
|
except BaseException as e:
|
|
@@ -670,16 +670,33 @@ class _Volume(_Object, type_prefix="vo"):
|
|
|
670
670
|
|
|
671
671
|
@live_method
|
|
672
672
|
async def read_file_into_fileobj(
|
|
673
|
-
self,
|
|
673
|
+
self,
|
|
674
|
+
path: str,
|
|
675
|
+
fileobj: typing.IO[bytes],
|
|
676
|
+
progress_cb: Optional[Callable[..., Any]] = None,
|
|
674
677
|
) -> int:
|
|
675
678
|
"""mdmd:hidden
|
|
676
679
|
Read volume file into file-like IO object.
|
|
677
680
|
"""
|
|
681
|
+
return await self._read_file_into_fileobj(path, fileobj, progress_cb=progress_cb)
|
|
682
|
+
|
|
683
|
+
@live_method
|
|
684
|
+
async def _read_file_into_fileobj(
|
|
685
|
+
self,
|
|
686
|
+
path: str,
|
|
687
|
+
fileobj: typing.IO[bytes],
|
|
688
|
+
concurrency: Optional[int] = None,
|
|
689
|
+
download_semaphore: Optional[asyncio.Semaphore] = None,
|
|
690
|
+
progress_cb: Optional[Callable[..., Any]] = None,
|
|
691
|
+
) -> int:
|
|
678
692
|
if progress_cb is None:
|
|
679
693
|
|
|
680
694
|
def progress_cb(*_, **__):
|
|
681
695
|
pass
|
|
682
696
|
|
|
697
|
+
if concurrency is None:
|
|
698
|
+
concurrency = multiprocessing.cpu_count()
|
|
699
|
+
|
|
683
700
|
req = api_pb2.VolumeGetFile2Request(volume_id=self.object_id, path=path)
|
|
684
701
|
|
|
685
702
|
try:
|
|
@@ -687,8 +704,9 @@ class _Volume(_Object, type_prefix="vo"):
|
|
|
687
704
|
except modal.exception.NotFoundError as exc:
|
|
688
705
|
raise FileNotFoundError(exc.args[0])
|
|
689
706
|
|
|
690
|
-
|
|
691
|
-
|
|
707
|
+
if download_semaphore is None:
|
|
708
|
+
download_semaphore = asyncio.Semaphore(concurrency)
|
|
709
|
+
|
|
692
710
|
write_lock = asyncio.Lock()
|
|
693
711
|
start_pos = fileobj.tell()
|
|
694
712
|
|
|
@@ -626,6 +626,14 @@ class _Volume(modal._object._Object):
|
|
|
626
626
|
"""
|
|
627
627
|
...
|
|
628
628
|
|
|
629
|
+
async def _read_file_into_fileobj(
|
|
630
|
+
self,
|
|
631
|
+
path: str,
|
|
632
|
+
fileobj: typing.IO[bytes],
|
|
633
|
+
concurrency: typing.Optional[int] = None,
|
|
634
|
+
download_semaphore: typing.Optional[asyncio.locks.Semaphore] = None,
|
|
635
|
+
progress_cb: typing.Optional[collections.abc.Callable[..., typing.Any]] = None,
|
|
636
|
+
) -> int: ...
|
|
629
637
|
async def remove_file(self, path: str, recursive: bool = False) -> None:
|
|
630
638
|
"""Remove a file or directory from a volume."""
|
|
631
639
|
...
|
|
@@ -1065,6 +1073,28 @@ class Volume(modal.object.Object):
|
|
|
1065
1073
|
|
|
1066
1074
|
read_file_into_fileobj: __read_file_into_fileobj_spec[typing_extensions.Self]
|
|
1067
1075
|
|
|
1076
|
+
class ___read_file_into_fileobj_spec(typing_extensions.Protocol[SUPERSELF]):
|
|
1077
|
+
def __call__(
|
|
1078
|
+
self,
|
|
1079
|
+
/,
|
|
1080
|
+
path: str,
|
|
1081
|
+
fileobj: typing.IO[bytes],
|
|
1082
|
+
concurrency: typing.Optional[int] = None,
|
|
1083
|
+
download_semaphore: typing.Optional[asyncio.locks.Semaphore] = None,
|
|
1084
|
+
progress_cb: typing.Optional[collections.abc.Callable[..., typing.Any]] = None,
|
|
1085
|
+
) -> int: ...
|
|
1086
|
+
async def aio(
|
|
1087
|
+
self,
|
|
1088
|
+
/,
|
|
1089
|
+
path: str,
|
|
1090
|
+
fileobj: typing.IO[bytes],
|
|
1091
|
+
concurrency: typing.Optional[int] = None,
|
|
1092
|
+
download_semaphore: typing.Optional[asyncio.locks.Semaphore] = None,
|
|
1093
|
+
progress_cb: typing.Optional[collections.abc.Callable[..., typing.Any]] = None,
|
|
1094
|
+
) -> int: ...
|
|
1095
|
+
|
|
1096
|
+
_read_file_into_fileobj: ___read_file_into_fileobj_spec[typing_extensions.Self]
|
|
1097
|
+
|
|
1068
1098
|
class __remove_file_spec(typing_extensions.Protocol[SUPERSELF]):
|
|
1069
1099
|
def __call__(self, /, path: str, recursive: bool = False) -> None:
|
|
1070
1100
|
"""Remove a file or directory from a volume."""
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|