modal 1.4.2.dev7__tar.gz → 1.4.2.dev9__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.
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/PKG-INFO +1 -1
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/task_command_router_client.py +6 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/client.py +7 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/client.pyi +14 -2
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/sandbox.py +29 -7
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/sandbox.pyi +54 -21
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal.egg-info/PKG-INFO +1 -1
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal_version/__init__.py +1 -1
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/pyproject.toml +3 -3
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/LICENSE +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/README.md +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/__init__.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/__main__.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_billing.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_clustered_functions.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_clustered_functions.pyi +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_container_entrypoint.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_functions.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_grpc_client.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_ipython.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_load_context.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_location.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_logs.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_object.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_output/__init__.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_output/manager.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_output/pty.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_output/rich.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_output/status.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_partial_function.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_resolver.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_resources.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_runtime/__init__.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_runtime/asgi.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_runtime/container_io_manager.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_runtime/container_io_manager.pyi +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_runtime/execution_context.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_runtime/execution_context.pyi +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_runtime/gpu_memory_snapshot.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_runtime/telemetry.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_runtime/user_code_event_loop.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_runtime/user_code_imports.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_serialization.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_server.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_traceback.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_tunnel.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_tunnel.pyi +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_type_manager.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/__init__.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/app_utils.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/async_utils.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/auth_token_manager.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/blob_utils.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/browser_utils.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/bytes_io_segment_payload.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/deprecation.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/docker_utils.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/function_utils.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/git_utils.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/grpc_testing.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/grpc_utils.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/hash_utils.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/http_utils.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/jwt_utils.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/logger.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/mount_utils.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/name_utils.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/package_utils.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/pattern_utils.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/rand_pb_testing.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/sandbox_fs_utils.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/shell_utils.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_utils/time_utils.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_vendor/__init__.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_vendor/a2wsgi_wsgi.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_vendor/cloudpickle.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_vendor/tblib.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_vendor/version.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/_watcher.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/app.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/app.pyi +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/billing.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/builder/2023.12.312.txt +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/builder/2023.12.txt +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/builder/2024.04.txt +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/builder/2024.10.txt +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/builder/2025.06.txt +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/builder/PREVIEW.txt +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/builder/README.md +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/builder/base-images.json +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/call_graph.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/__init__.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/_download.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/_traceback.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/app.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/billing.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/changelog.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/cluster.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/config.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/container.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/dashboard.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/dict.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/entry_point.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/environment.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/import_refs.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/launch.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/network_file_system.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/profile.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/programs/__init__.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/programs/run_jupyter.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/programs/vscode.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/queues.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/run.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/secret.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/selector.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/shell.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/token.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/utils.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cli/volume.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cloud_bucket_mount.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cloud_bucket_mount.pyi +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cls.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/cls.pyi +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/config.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/container_process.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/container_process.pyi +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/dict.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/dict.pyi +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/environments.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/environments.pyi +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/exception.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/experimental/__init__.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/experimental/flash.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/experimental/flash.pyi +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/experimental/ipython.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/file_io.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/file_io.pyi +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/file_pattern_matcher.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/functions.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/functions.pyi +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/image.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/image.pyi +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/io_streams.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/io_streams.pyi +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/mount.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/mount.pyi +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/network_file_system.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/network_file_system.pyi +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/object.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/object.pyi +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/output.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/parallel_map.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/parallel_map.pyi +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/partial_function.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/partial_function.pyi +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/proxy.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/proxy.pyi +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/py.typed +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/queue.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/queue.pyi +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/retries.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/runner.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/runner.pyi +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/running_app.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/sandbox_fs.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/sandbox_fs.pyi +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/schedule.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/scheduler_placement.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/secret.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/secret.pyi +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/server.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/server.pyi +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/serving.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/serving.pyi +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/snapshot.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/snapshot.pyi +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/stream_type.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/token_flow.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/token_flow.pyi +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/volume.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal/volume.pyi +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal.egg-info/SOURCES.txt +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal.egg-info/dependency_links.txt +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal.egg-info/entry_points.txt +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal.egg-info/requires.txt +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal.egg-info/top_level.txt +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal_docs/__init__.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal_docs/gen_cli_docs.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal_docs/gen_cli_docs_main.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal_docs/gen_reference_docs.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal_docs/gen_reference_docs_main.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal_docs/mdmd/__init__.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal_docs/mdmd/mdmd.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal_docs/mdmd/signatures.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal_proto/__init__.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal_proto/api_grpc.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal_proto/api_pb2.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal_proto/api_pb2.pyi +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal_proto/api_pb2_grpc.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal_proto/api_pb2_grpc.pyi +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal_proto/modal_api_grpc.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal_proto/py.typed +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal_proto/task_command_router_grpc.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal_proto/task_command_router_pb2.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal_proto/task_command_router_pb2.pyi +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal_proto/task_command_router_pb2_grpc.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal_proto/task_command_router_pb2_grpc.pyi +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/modal_version/__main__.py +0 -0
- {modal-1.4.2.dev7 → modal-1.4.2.dev9}/setup.cfg +0 -0
|
@@ -617,6 +617,12 @@ class TaskCommandRouterClient:
|
|
|
617
617
|
lambda: self._call_with_auth_retry(self._stub.TaskMountDirectory, request)
|
|
618
618
|
)
|
|
619
619
|
|
|
620
|
+
async def unmount_image(self, request: sr_pb2.TaskUnmountDirectoryRequest):
|
|
621
|
+
with grpc_error_converter():
|
|
622
|
+
return await call_with_retries_on_transient_errors(
|
|
623
|
+
lambda: self._call_with_auth_retry(self._stub.TaskUnmountDirectory, request)
|
|
624
|
+
)
|
|
625
|
+
|
|
620
626
|
async def snapshot_directory(
|
|
621
627
|
self, request: sr_pb2.TaskSnapshotDirectoryRequest
|
|
622
628
|
) -> sr_pb2.TaskSnapshotDirectoryResponse:
|
|
@@ -239,6 +239,10 @@ class _Client:
|
|
|
239
239
|
"""
|
|
240
240
|
Constructor based on token credentials; useful for managing Modal on behalf of third-party users.
|
|
241
241
|
|
|
242
|
+
Also useful when it's necessary to explicitly manage the lifecycle of the client
|
|
243
|
+
(e.g. when running Modal in a forked subprocess) — see
|
|
244
|
+
[troubleshooting](/docs/guide/troubleshooting#connection-issues-in-forked-processes).
|
|
245
|
+
|
|
242
246
|
**Usage:**
|
|
243
247
|
|
|
244
248
|
```python notest
|
|
@@ -309,6 +313,9 @@ class _Client:
|
|
|
309
313
|
return await coro
|
|
310
314
|
|
|
311
315
|
async def _reset_on_pid_change(self):
|
|
316
|
+
# Best-effort recovery after os.fork(). The client singleton may be inherited
|
|
317
|
+
# from the parent with stale gRPC state. For reliable post-fork usage, create
|
|
318
|
+
# a fresh client via Client.from_credentials() instead of relying on this.
|
|
312
319
|
if self._owner_pid and self._owner_pid != os.getpid():
|
|
313
320
|
# not calling .close() since that would also interact with stale resources
|
|
314
321
|
# just reset the internal state
|
|
@@ -35,7 +35,7 @@ class _Client:
|
|
|
35
35
|
server_url: str,
|
|
36
36
|
client_type: int,
|
|
37
37
|
credentials: typing.Optional[tuple[str, str]],
|
|
38
|
-
version: str = "1.4.2.
|
|
38
|
+
version: str = "1.4.2.dev9",
|
|
39
39
|
):
|
|
40
40
|
"""mdmd:hidden
|
|
41
41
|
The Modal client object is not intended to be instantiated directly by users.
|
|
@@ -97,6 +97,10 @@ class _Client:
|
|
|
97
97
|
async def from_credentials(cls, token_id: str, token_secret: str) -> _Client:
|
|
98
98
|
"""Constructor based on token credentials; useful for managing Modal on behalf of third-party users.
|
|
99
99
|
|
|
100
|
+
Also useful when it's necessary to explicitly manage the lifecycle of the client
|
|
101
|
+
(e.g. when running Modal in a forked subprocess) — see
|
|
102
|
+
[troubleshooting](/docs/guide/troubleshooting#connection-issues-in-forked-processes).
|
|
103
|
+
|
|
100
104
|
**Usage:**
|
|
101
105
|
|
|
102
106
|
```python notest
|
|
@@ -171,7 +175,7 @@ class Client:
|
|
|
171
175
|
server_url: str,
|
|
172
176
|
client_type: int,
|
|
173
177
|
credentials: typing.Optional[tuple[str, str]],
|
|
174
|
-
version: str = "1.4.2.
|
|
178
|
+
version: str = "1.4.2.dev9",
|
|
175
179
|
):
|
|
176
180
|
"""mdmd:hidden
|
|
177
181
|
The Modal client object is not intended to be instantiated directly by users.
|
|
@@ -283,6 +287,10 @@ class Client:
|
|
|
283
287
|
def __call__(self, /, token_id: str, token_secret: str) -> Client:
|
|
284
288
|
"""Constructor based on token credentials; useful for managing Modal on behalf of third-party users.
|
|
285
289
|
|
|
290
|
+
Also useful when it's necessary to explicitly manage the lifecycle of the client
|
|
291
|
+
(e.g. when running Modal in a forked subprocess) — see
|
|
292
|
+
[troubleshooting](/docs/guide/troubleshooting#connection-issues-in-forked-processes).
|
|
293
|
+
|
|
286
294
|
**Usage:**
|
|
287
295
|
|
|
288
296
|
```python notest
|
|
@@ -296,6 +304,10 @@ class Client:
|
|
|
296
304
|
async def aio(self, /, token_id: str, token_secret: str) -> Client:
|
|
297
305
|
"""Constructor based on token credentials; useful for managing Modal on behalf of third-party users.
|
|
298
306
|
|
|
307
|
+
Also useful when it's necessary to explicitly manage the lifecycle of the client
|
|
308
|
+
(e.g. when running Modal in a forked subprocess) — see
|
|
309
|
+
[troubleshooting](/docs/guide/troubleshooting#connection-issues-in-forked-processes).
|
|
310
|
+
|
|
299
311
|
**Usage:**
|
|
300
312
|
|
|
301
313
|
```python notest
|
|
@@ -923,14 +923,15 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
923
923
|
async def mount_image(self, path: Union[PurePosixPath, str], image: _Image):
|
|
924
924
|
"""Mount an Image at a specified path in a running Sandbox.
|
|
925
925
|
|
|
926
|
-
`path` should be a directory
|
|
927
|
-
data, the previous directory will be replaced
|
|
926
|
+
`path` should be a directory that is **not** the root path (`/`). If the path doesn't exist
|
|
927
|
+
it will be created. If it exists and contains data, the previous directory will be replaced
|
|
928
|
+
by the mount.
|
|
928
929
|
|
|
929
|
-
The `image` argument
|
|
930
|
-
-
|
|
931
|
-
- referenced by
|
|
932
|
-
-
|
|
933
|
-
|
|
930
|
+
The `image` argument supports any Image that has an object ID, including:
|
|
931
|
+
- Images built using `image.build()`
|
|
932
|
+
- Images referenced by ID, e.g. `Image.from_id(...)`
|
|
933
|
+
- Filesystem/directory snapshots, e.g. created by `.snapshot_directory()` or `.snapshot_filesystem()`
|
|
934
|
+
- Empty images created with `Image.from_scratch()`
|
|
934
935
|
|
|
935
936
|
Usage:
|
|
936
937
|
```py notest
|
|
@@ -982,6 +983,27 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
982
983
|
req = sr_pb2.TaskMountDirectoryRequest(task_id=task_id, path=path_bytes, image_id=image_id)
|
|
983
984
|
await command_router_client.mount_image(req)
|
|
984
985
|
|
|
986
|
+
async def unmount_image(self, path: Union[PurePosixPath, str]):
|
|
987
|
+
"""Unmount a previously mounted Image from a running Sandbox.
|
|
988
|
+
|
|
989
|
+
`path` must be the exact mount point that was passed to `.mount_image()`.
|
|
990
|
+
After unmounting, the underlying Sandbox filesystem at that path becomes
|
|
991
|
+
visible again.
|
|
992
|
+
"""
|
|
993
|
+
self._ensure_v1("unmount_image")
|
|
994
|
+
|
|
995
|
+
task_id = await self._get_task_id()
|
|
996
|
+
if (command_router_client := await self._get_command_router_client(task_id)) is None:
|
|
997
|
+
raise InvalidError("Unmounting directories requires direct Sandbox control - please contact Modal support.")
|
|
998
|
+
|
|
999
|
+
posix_path = PurePosixPath(path)
|
|
1000
|
+
if not posix_path.is_absolute():
|
|
1001
|
+
raise InvalidError(f"Unmount path must be absolute; got: {posix_path}")
|
|
1002
|
+
path_bytes = posix_path.as_posix().encode("utf8")
|
|
1003
|
+
|
|
1004
|
+
req = sr_pb2.TaskUnmountDirectoryRequest(task_id=task_id, path=path_bytes)
|
|
1005
|
+
await command_router_client.unmount_image(req)
|
|
1006
|
+
|
|
985
1007
|
async def snapshot_directory(self, path: Union[PurePosixPath, str]) -> _Image:
|
|
986
1008
|
"""Snapshot a directory in a running Sandbox, creating a new Image with its content.
|
|
987
1009
|
|
|
@@ -384,14 +384,15 @@ class _Sandbox(modal._object._Object):
|
|
|
384
384
|
async def mount_image(self, path: typing.Union[pathlib.PurePosixPath, str], image: modal.image._Image):
|
|
385
385
|
"""Mount an Image at a specified path in a running Sandbox.
|
|
386
386
|
|
|
387
|
-
`path` should be a directory
|
|
388
|
-
data, the previous directory will be replaced
|
|
387
|
+
`path` should be a directory that is **not** the root path (`/`). If the path doesn't exist
|
|
388
|
+
it will be created. If it exists and contains data, the previous directory will be replaced
|
|
389
|
+
by the mount.
|
|
389
390
|
|
|
390
|
-
The `image` argument
|
|
391
|
-
-
|
|
392
|
-
- referenced by
|
|
393
|
-
-
|
|
394
|
-
|
|
391
|
+
The `image` argument supports any Image that has an object ID, including:
|
|
392
|
+
- Images built using `image.build()`
|
|
393
|
+
- Images referenced by ID, e.g. `Image.from_id(...)`
|
|
394
|
+
- Filesystem/directory snapshots, e.g. created by `.snapshot_directory()` or `.snapshot_filesystem()`
|
|
395
|
+
- Empty images created with `Image.from_scratch()`
|
|
395
396
|
|
|
396
397
|
Usage:
|
|
397
398
|
```py notest
|
|
@@ -405,6 +406,15 @@ class _Sandbox(modal._object._Object):
|
|
|
405
406
|
"""
|
|
406
407
|
...
|
|
407
408
|
|
|
409
|
+
async def unmount_image(self, path: typing.Union[pathlib.PurePosixPath, str]):
|
|
410
|
+
"""Unmount a previously mounted Image from a running Sandbox.
|
|
411
|
+
|
|
412
|
+
`path` must be the exact mount point that was passed to `.mount_image()`.
|
|
413
|
+
After unmounting, the underlying Sandbox filesystem at that path becomes
|
|
414
|
+
visible again.
|
|
415
|
+
"""
|
|
416
|
+
...
|
|
417
|
+
|
|
408
418
|
async def snapshot_directory(self, path: typing.Union[pathlib.PurePosixPath, str]) -> modal.image._Image:
|
|
409
419
|
"""Snapshot a directory in a running Sandbox, creating a new Image with its content.
|
|
410
420
|
|
|
@@ -1351,14 +1361,15 @@ class Sandbox(modal.object.Object):
|
|
|
1351
1361
|
def __call__(self, /, path: typing.Union[pathlib.PurePosixPath, str], image: modal.image.Image):
|
|
1352
1362
|
"""Mount an Image at a specified path in a running Sandbox.
|
|
1353
1363
|
|
|
1354
|
-
`path` should be a directory
|
|
1355
|
-
data, the previous directory will be replaced
|
|
1364
|
+
`path` should be a directory that is **not** the root path (`/`). If the path doesn't exist
|
|
1365
|
+
it will be created. If it exists and contains data, the previous directory will be replaced
|
|
1366
|
+
by the mount.
|
|
1356
1367
|
|
|
1357
|
-
The `image` argument
|
|
1358
|
-
-
|
|
1359
|
-
- referenced by
|
|
1360
|
-
-
|
|
1361
|
-
|
|
1368
|
+
The `image` argument supports any Image that has an object ID, including:
|
|
1369
|
+
- Images built using `image.build()`
|
|
1370
|
+
- Images referenced by ID, e.g. `Image.from_id(...)`
|
|
1371
|
+
- Filesystem/directory snapshots, e.g. created by `.snapshot_directory()` or `.snapshot_filesystem()`
|
|
1372
|
+
- Empty images created with `Image.from_scratch()`
|
|
1362
1373
|
|
|
1363
1374
|
Usage:
|
|
1364
1375
|
```py notest
|
|
@@ -1375,14 +1386,15 @@ class Sandbox(modal.object.Object):
|
|
|
1375
1386
|
async def aio(self, /, path: typing.Union[pathlib.PurePosixPath, str], image: modal.image.Image):
|
|
1376
1387
|
"""Mount an Image at a specified path in a running Sandbox.
|
|
1377
1388
|
|
|
1378
|
-
`path` should be a directory
|
|
1379
|
-
data, the previous directory will be replaced
|
|
1389
|
+
`path` should be a directory that is **not** the root path (`/`). If the path doesn't exist
|
|
1390
|
+
it will be created. If it exists and contains data, the previous directory will be replaced
|
|
1391
|
+
by the mount.
|
|
1380
1392
|
|
|
1381
|
-
The `image` argument
|
|
1382
|
-
-
|
|
1383
|
-
- referenced by
|
|
1384
|
-
-
|
|
1385
|
-
|
|
1393
|
+
The `image` argument supports any Image that has an object ID, including:
|
|
1394
|
+
- Images built using `image.build()`
|
|
1395
|
+
- Images referenced by ID, e.g. `Image.from_id(...)`
|
|
1396
|
+
- Filesystem/directory snapshots, e.g. created by `.snapshot_directory()` or `.snapshot_filesystem()`
|
|
1397
|
+
- Empty images created with `Image.from_scratch()`
|
|
1386
1398
|
|
|
1387
1399
|
Usage:
|
|
1388
1400
|
```py notest
|
|
@@ -1398,6 +1410,27 @@ class Sandbox(modal.object.Object):
|
|
|
1398
1410
|
|
|
1399
1411
|
mount_image: __mount_image_spec
|
|
1400
1412
|
|
|
1413
|
+
class __unmount_image_spec(typing_extensions.Protocol):
|
|
1414
|
+
def __call__(self, /, path: typing.Union[pathlib.PurePosixPath, str]):
|
|
1415
|
+
"""Unmount a previously mounted Image from a running Sandbox.
|
|
1416
|
+
|
|
1417
|
+
`path` must be the exact mount point that was passed to `.mount_image()`.
|
|
1418
|
+
After unmounting, the underlying Sandbox filesystem at that path becomes
|
|
1419
|
+
visible again.
|
|
1420
|
+
"""
|
|
1421
|
+
...
|
|
1422
|
+
|
|
1423
|
+
async def aio(self, /, path: typing.Union[pathlib.PurePosixPath, str]):
|
|
1424
|
+
"""Unmount a previously mounted Image from a running Sandbox.
|
|
1425
|
+
|
|
1426
|
+
`path` must be the exact mount point that was passed to `.mount_image()`.
|
|
1427
|
+
After unmounting, the underlying Sandbox filesystem at that path becomes
|
|
1428
|
+
visible again.
|
|
1429
|
+
"""
|
|
1430
|
+
...
|
|
1431
|
+
|
|
1432
|
+
unmount_image: __unmount_image_spec
|
|
1433
|
+
|
|
1401
1434
|
class __snapshot_directory_spec(typing_extensions.Protocol):
|
|
1402
1435
|
def __call__(self, /, path: typing.Union[pathlib.PurePosixPath, str]) -> modal.image.Image:
|
|
1403
1436
|
"""Snapshot a directory in a running Sandbox, creating a new Image with its content.
|
|
@@ -50,7 +50,7 @@ dev = [
|
|
|
50
50
|
"mypy~=1.18.2",
|
|
51
51
|
"packaging>=23.1",
|
|
52
52
|
"pytest~=8.4.0",
|
|
53
|
-
"pytest-asyncio
|
|
53
|
+
"pytest-asyncio~=1.3.0",
|
|
54
54
|
"pytest-env~=1.1.5",
|
|
55
55
|
"pytest-markdown-docs==0.9.1",
|
|
56
56
|
"pytest-timeout~=2.4.0",
|
|
@@ -119,6 +119,8 @@ module = [
|
|
|
119
119
|
ignore_errors = true
|
|
120
120
|
|
|
121
121
|
[tool.pytest.ini_options]
|
|
122
|
+
asyncio_default_fixture_loop_scope = "session"
|
|
123
|
+
asyncio_default_test_loop_scope = "session"
|
|
122
124
|
timeout = 300
|
|
123
125
|
addopts = "--ignore=modal/cli/programs"
|
|
124
126
|
filterwarnings = [
|
|
@@ -126,9 +128,7 @@ filterwarnings = [
|
|
|
126
128
|
"ignore:Type google._upb.*MapContainer uses PyType_Spec.*Python 3.14:DeprecationWarning",
|
|
127
129
|
"error::modal.exception.DeprecationError",
|
|
128
130
|
"error::modal.exception.AsyncUsageWarning",
|
|
129
|
-
"ignore:There is no current event loop:DeprecationWarning", # pytest-asyncio internals
|
|
130
131
|
"ignore:distutils Version classes are deprecated:DeprecationWarning", # pytest-freezegun internals
|
|
131
|
-
"ignore:'asyncio.iscoroutinefunction' is deprecated:DeprecationWarning", # pytest-asyncio internals
|
|
132
132
|
]
|
|
133
133
|
|
|
134
134
|
[tool.ruff]
|
|
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
|
|
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
|