modal 1.4.3.dev6__tar.gz → 1.4.3.dev8__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.3.dev6 → modal-1.4.3.dev8}/PKG-INFO +1 -1
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_utils/async_utils.py +1 -1
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_utils/sandbox_fs_utils.py +60 -30
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/cli/cluster.py +25 -7
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/cli/container.py +22 -7
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/client.pyi +2 -2
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/file_io.py +1 -1
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/sandbox.py +11 -3
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/sandbox.pyi +18 -6
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/sandbox_fs.py +242 -146
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/sandbox_fs.pyi +375 -233
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal.egg-info/PKG-INFO +1 -1
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal_proto/task_command_router_grpc.py +32 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal_proto/task_command_router_pb2.py +109 -63
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal_proto/task_command_router_pb2.pyi +81 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal_proto/task_command_router_pb2_grpc.py +66 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal_proto/task_command_router_pb2_grpc.pyi +20 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal_version/__init__.py +1 -1
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/LICENSE +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/README.md +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/__init__.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/__main__.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_billing.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_clustered_functions.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_clustered_functions.pyi +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_container_entrypoint.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_functions.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_grpc_client.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_ipython.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_load_context.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_location.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_logs.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_object.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_output/__init__.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_output/manager.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_output/pty.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_output/rich.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_output/status.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_partial_function.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_resolver.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_resources.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_runtime/__init__.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_runtime/asgi.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_runtime/container_io_manager.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_runtime/container_io_manager.pyi +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_runtime/execution_context.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_runtime/execution_context.pyi +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_runtime/gpu_memory_snapshot.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_runtime/telemetry.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_runtime/user_code_event_loop.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_runtime/user_code_imports.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_serialization.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_server.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_traceback.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_tunnel.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_tunnel.pyi +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_type_manager.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_utils/__init__.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_utils/app_utils.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_utils/auth_token_manager.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_utils/blob_utils.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_utils/browser_utils.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_utils/bytes_io_segment_payload.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_utils/deprecation.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_utils/docker_utils.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_utils/function_utils.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_utils/git_utils.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_utils/grpc_testing.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_utils/grpc_utils.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_utils/hash_utils.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_utils/http_utils.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_utils/jwt_utils.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_utils/logger.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_utils/mount_utils.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_utils/name_utils.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_utils/package_utils.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_utils/pattern_utils.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_utils/rand_pb_testing.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_utils/shell_utils.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_utils/task_command_router_client.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_utils/time_utils.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_vendor/__init__.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_vendor/a2wsgi_wsgi.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_vendor/cloudpickle.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_vendor/tblib.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_vendor/version.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/_watcher.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/app.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/app.pyi +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/billing.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/builder/2023.12.312.txt +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/builder/2023.12.txt +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/builder/2024.04.txt +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/builder/2024.10.txt +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/builder/2025.06.txt +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/builder/PREVIEW.txt +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/builder/README.md +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/builder/base-images.json +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/call_graph.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/cli/__init__.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/cli/_download.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/cli/_help.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/cli/_traceback.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/cli/app.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/cli/billing.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/cli/bootstrap.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/cli/changelog.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/cli/config.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/cli/dashboard.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/cli/dict.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/cli/entry_point.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/cli/environment.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/cli/import_refs.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/cli/launch.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/cli/logo.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/cli/network_file_system.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/cli/profile.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/cli/programs/__init__.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/cli/programs/run_jupyter.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/cli/programs/vscode.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/cli/queues.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/cli/run.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/cli/secret.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/cli/selector.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/cli/shell.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/cli/token.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/cli/utils.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/cli/volume.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/client.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/cloud_bucket_mount.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/cloud_bucket_mount.pyi +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/cls.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/cls.pyi +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/config.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/container_process.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/container_process.pyi +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/dict.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/dict.pyi +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/environments.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/environments.pyi +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/exception.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/experimental/__init__.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/experimental/flash.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/experimental/flash.pyi +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/experimental/ipython.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/file_io.pyi +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/file_pattern_matcher.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/functions.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/functions.pyi +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/image.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/image.pyi +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/io_streams.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/io_streams.pyi +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/mount.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/mount.pyi +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/network_file_system.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/network_file_system.pyi +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/object.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/object.pyi +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/output.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/parallel_map.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/parallel_map.pyi +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/partial_function.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/partial_function.pyi +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/proxy.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/proxy.pyi +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/py.typed +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/queue.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/queue.pyi +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/retries.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/runner.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/runner.pyi +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/running_app.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/schedule.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/scheduler_placement.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/secret.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/secret.pyi +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/server.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/server.pyi +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/serving.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/serving.pyi +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/snapshot.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/snapshot.pyi +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/stream_type.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/token_flow.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/token_flow.pyi +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/volume.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal/volume.pyi +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal.egg-info/SOURCES.txt +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal.egg-info/dependency_links.txt +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal.egg-info/entry_points.txt +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal.egg-info/requires.txt +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal.egg-info/top_level.txt +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal_docs/__init__.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal_docs/gen_cli_docs.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal_docs/gen_cli_docs_main.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal_docs/gen_reference_docs.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal_docs/gen_reference_docs_main.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal_docs/mdmd/__init__.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal_docs/mdmd/mdmd.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal_docs/mdmd/signatures.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal_proto/__init__.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal_proto/api_grpc.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal_proto/api_pb2.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal_proto/api_pb2.pyi +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal_proto/api_pb2_grpc.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal_proto/api_pb2_grpc.pyi +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal_proto/modal_api_grpc.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal_proto/py.typed +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/modal_version/__main__.py +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/pyproject.toml +0 -0
- {modal-1.4.3.dev6 → modal-1.4.3.dev8}/setup.cfg +0 -0
|
@@ -1115,7 +1115,7 @@ async def async_merge(
|
|
|
1115
1115
|
new_output_task = asyncio.create_task(queue.get())
|
|
1116
1116
|
|
|
1117
1117
|
finally:
|
|
1118
|
-
unfinished_tasks = [t for t in tasks | {new_output_task} if not t.done()]
|
|
1118
|
+
unfinished_tasks: list[asyncio.Task[Any]] = [t for t in tasks | {new_output_task} if not t.done()]
|
|
1119
1119
|
for t in unfinished_tasks:
|
|
1120
1120
|
t.cancel()
|
|
1121
1121
|
try:
|
|
@@ -60,27 +60,6 @@ def try_parse_error_payload(stderr: Union[str, bytes]) -> Optional[ErrorPayload]
|
|
|
60
60
|
return ErrorPayload(error_kind=error_kind, message=message, detail=detail)
|
|
61
61
|
|
|
62
62
|
|
|
63
|
-
def raise_read_file_error(returncode: int, stderr: Union[str, bytes], remote_path: str) -> NoReturn:
|
|
64
|
-
if payload := try_parse_error_payload(stderr):
|
|
65
|
-
logger.debug(
|
|
66
|
-
f"sandbox-fs-tools read error: path={remote_path}, "
|
|
67
|
-
f"error_kind={payload.error_kind}, message={payload.message}, detail={payload.detail}"
|
|
68
|
-
)
|
|
69
|
-
if payload.error_kind == "NotFound":
|
|
70
|
-
raise SandboxFilesystemNotFoundError(f"{payload.message}: {remote_path}")
|
|
71
|
-
if payload.error_kind == "IsDirectory":
|
|
72
|
-
raise SandboxFilesystemIsADirectoryError(f"{payload.message}: {remote_path}")
|
|
73
|
-
if payload.error_kind == "PermissionDenied":
|
|
74
|
-
raise SandboxFilesystemPermissionError(f"{payload.message}: {remote_path}")
|
|
75
|
-
if payload.error_kind == "FileTooLarge":
|
|
76
|
-
raise SandboxFilesystemFileTooLargeError(f"{payload.message}: {remote_path}")
|
|
77
|
-
raise SandboxFilesystemError(payload.message)
|
|
78
|
-
|
|
79
|
-
if stderr_text := _stderr_to_text(stderr):
|
|
80
|
-
logger.debug(f"Unstructured modal-sandbox-fs-tools stderr: {stderr_text}")
|
|
81
|
-
raise SandboxFilesystemError(f"Operation on '{remote_path}' failed with exit code {returncode}")
|
|
82
|
-
|
|
83
|
-
|
|
84
63
|
def _extract_support_error_code(exc: Exception) -> Optional[str]:
|
|
85
64
|
if match := re.search(r"Error code:\s*([A-Z0-9]{8})", str(exc)):
|
|
86
65
|
return match.group(1)
|
|
@@ -144,26 +123,66 @@ def make_write_file_command(remote_path: str) -> str:
|
|
|
144
123
|
return json.dumps({"WriteFile": {"path": remote_path}})
|
|
145
124
|
|
|
146
125
|
|
|
147
|
-
def
|
|
148
|
-
|
|
126
|
+
def raise_list_files_error(returncode: int, stderr: Union[str, bytes], remote_path: str) -> NoReturn:
|
|
127
|
+
if payload := try_parse_error_payload(stderr):
|
|
128
|
+
logger.debug(
|
|
129
|
+
f"sandbox-fs-tools list_files error: path={remote_path}, "
|
|
130
|
+
f"error_kind={payload.error_kind}, message={payload.message}, detail={payload.detail}"
|
|
131
|
+
)
|
|
132
|
+
if payload.error_kind == "NotFound":
|
|
133
|
+
raise SandboxFilesystemNotFoundError(f"{payload.message}: {remote_path}")
|
|
134
|
+
if payload.error_kind in ("IsFile", "NotDirectory"):
|
|
135
|
+
raise SandboxFilesystemNotADirectoryError(f"{payload.message}: {remote_path}")
|
|
136
|
+
if payload.error_kind == "PermissionDenied":
|
|
137
|
+
raise SandboxFilesystemPermissionError(f"{payload.message}: {remote_path}")
|
|
138
|
+
raise SandboxFilesystemError(payload.message)
|
|
139
|
+
|
|
140
|
+
if stderr_text := _stderr_to_text(stderr):
|
|
141
|
+
logger.debug(f"Unstructured modal-sandbox-fs-tools stderr: {stderr_text}")
|
|
142
|
+
raise SandboxFilesystemError(f"Operation on '{remote_path}' failed with exit code {returncode}")
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def make_list_files_command(remote_path: str) -> str:
|
|
146
|
+
"""Build the JSON command string for a ListFiles operation.
|
|
149
147
|
|
|
150
148
|
The returned JSON must match the `Command` enum in the modal-sandbox-fs-tools
|
|
151
149
|
Rust crate (crates/modal-sandbox-fs-tools/src/lib.rs). Treat changes to
|
|
152
150
|
this schema like protobuf changes: fields must not be removed or renamed,
|
|
153
151
|
only added with backwards-compatible defaults.
|
|
154
152
|
"""
|
|
155
|
-
return json.dumps({"
|
|
153
|
+
return json.dumps({"ListFiles": {"path": remote_path}})
|
|
156
154
|
|
|
157
155
|
|
|
158
|
-
def
|
|
159
|
-
|
|
156
|
+
def raise_read_file_error(returncode: int, stderr: Union[str, bytes], remote_path: str) -> NoReturn:
|
|
157
|
+
if payload := try_parse_error_payload(stderr):
|
|
158
|
+
logger.debug(
|
|
159
|
+
f"sandbox-fs-tools read error: path={remote_path}, "
|
|
160
|
+
f"error_kind={payload.error_kind}, message={payload.message}, detail={payload.detail}"
|
|
161
|
+
)
|
|
162
|
+
if payload.error_kind == "NotFound":
|
|
163
|
+
raise SandboxFilesystemNotFoundError(f"{payload.message}: {remote_path}")
|
|
164
|
+
if payload.error_kind == "IsDirectory":
|
|
165
|
+
raise SandboxFilesystemIsADirectoryError(f"{payload.message}: {remote_path}")
|
|
166
|
+
if payload.error_kind == "PermissionDenied":
|
|
167
|
+
raise SandboxFilesystemPermissionError(f"{payload.message}: {remote_path}")
|
|
168
|
+
if payload.error_kind == "FileTooLarge":
|
|
169
|
+
raise SandboxFilesystemFileTooLargeError(f"{payload.message}: {remote_path}")
|
|
170
|
+
raise SandboxFilesystemError(payload.message)
|
|
171
|
+
|
|
172
|
+
if stderr_text := _stderr_to_text(stderr):
|
|
173
|
+
logger.debug(f"Unstructured modal-sandbox-fs-tools stderr: {stderr_text}")
|
|
174
|
+
raise SandboxFilesystemError(f"Operation on '{remote_path}' failed with exit code {returncode}")
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def make_read_file_command(remote_path: str) -> str:
|
|
178
|
+
"""Build the JSON command string for a ReadFile operation.
|
|
160
179
|
|
|
161
180
|
The returned JSON must match the `Command` enum in the modal-sandbox-fs-tools
|
|
162
181
|
Rust crate (crates/modal-sandbox-fs-tools/src/lib.rs). Treat changes to
|
|
163
182
|
this schema like protobuf changes: fields must not be removed or renamed,
|
|
164
183
|
only added with backwards-compatible defaults.
|
|
165
184
|
"""
|
|
166
|
-
return json.dumps({"
|
|
185
|
+
return json.dumps({"ReadFile": {"path": remote_path}})
|
|
167
186
|
|
|
168
187
|
|
|
169
188
|
def raise_remove_error(returncode: int, stderr: Union[str, bytes], remote_path: str) -> NoReturn:
|
|
@@ -189,15 +208,15 @@ def raise_remove_error(returncode: int, stderr: Union[str, bytes], remote_path:
|
|
|
189
208
|
raise SandboxFilesystemError(f"Operation on '{remote_path}' failed with exit code {returncode}")
|
|
190
209
|
|
|
191
210
|
|
|
192
|
-
def
|
|
193
|
-
"""Build the JSON command string for a
|
|
211
|
+
def make_remove_command(remote_path: str, recursive: bool) -> str:
|
|
212
|
+
"""Build the JSON command string for a Remove operation.
|
|
194
213
|
|
|
195
214
|
The returned JSON must match the `Command` enum in the modal-sandbox-fs-tools
|
|
196
215
|
Rust crate (crates/modal-sandbox-fs-tools/src/lib.rs). Treat changes to
|
|
197
216
|
this schema like protobuf changes: fields must not be removed or renamed,
|
|
198
217
|
only added with backwards-compatible defaults.
|
|
199
218
|
"""
|
|
200
|
-
return json.dumps({"
|
|
219
|
+
return json.dumps({"Remove": {"path": remote_path, "recursive": recursive}})
|
|
201
220
|
|
|
202
221
|
|
|
203
222
|
def raise_make_directory_error(returncode: int, stderr: Union[str, bytes], remote_path: str) -> NoReturn:
|
|
@@ -225,6 +244,17 @@ def raise_make_directory_error(returncode: int, stderr: Union[str, bytes], remot
|
|
|
225
244
|
raise SandboxFilesystemError(f"Operation on '{remote_path}' failed with exit code {returncode}")
|
|
226
245
|
|
|
227
246
|
|
|
247
|
+
def make_make_directory_command(remote_path: str, create_parents: bool) -> str:
|
|
248
|
+
"""Build the JSON command string for a MakeDirectory operation.
|
|
249
|
+
|
|
250
|
+
The returned JSON must match the `Command` enum in the modal-sandbox-fs-tools
|
|
251
|
+
Rust crate (crates/modal-sandbox-fs-tools/src/lib.rs). Treat changes to
|
|
252
|
+
this schema like protobuf changes: fields must not be removed or renamed,
|
|
253
|
+
only added with backwards-compatible defaults.
|
|
254
|
+
"""
|
|
255
|
+
return json.dumps({"MakeDirectory": {"path": remote_path, "parents": create_parents}})
|
|
256
|
+
|
|
257
|
+
|
|
228
258
|
def validate_absolute_remote_path(remote_path: str, operation: str) -> None:
|
|
229
259
|
if not PurePosixPath(remote_path).is_absolute():
|
|
230
260
|
raise InvalidError(f"Sandbox.filesystem.{operation}() currently only supports absolute remote_path values")
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# Copyright Modal Labs 2022
|
|
2
|
+
import uuid
|
|
2
3
|
from typing import Optional, Union
|
|
3
4
|
|
|
4
5
|
import click
|
|
@@ -8,15 +9,17 @@ from rich.text import Text
|
|
|
8
9
|
from modal._object import _get_environment_name
|
|
9
10
|
from modal._output.pty import get_pty_info
|
|
10
11
|
from modal._utils.async_utils import synchronizer
|
|
12
|
+
from modal._utils.task_command_router_client import TaskCommandRouterClient
|
|
11
13
|
from modal._utils.time_utils import timestamp_to_localized_str
|
|
12
14
|
from modal.cli.utils import display_table, env_option, is_tty
|
|
13
15
|
from modal.client import _Client
|
|
14
16
|
from modal.config import config
|
|
15
17
|
from modal.container_process import _ContainerProcess
|
|
16
18
|
from modal.environments import ensure_env
|
|
19
|
+
from modal.exception import InvalidError
|
|
17
20
|
from modal.output import OutputManager
|
|
18
21
|
from modal.stream_type import StreamType
|
|
19
|
-
from modal_proto import api_pb2
|
|
22
|
+
from modal_proto import api_pb2, task_command_router_pb2 as sr_pb2
|
|
20
23
|
|
|
21
24
|
from ._help import ModalGroup
|
|
22
25
|
|
|
@@ -75,17 +78,32 @@ async def shell(cluster_id: str, rank: int = 0):
|
|
|
75
78
|
)
|
|
76
79
|
|
|
77
80
|
pty = is_tty()
|
|
78
|
-
|
|
81
|
+
|
|
82
|
+
command_router_client = await TaskCommandRouterClient.try_init(client, task_id)
|
|
83
|
+
if command_router_client is None:
|
|
84
|
+
raise InvalidError(f"Command router access is not available for container {task_id}")
|
|
85
|
+
|
|
86
|
+
process_id = str(uuid.uuid4())
|
|
87
|
+
|
|
88
|
+
start_req = sr_pb2.TaskExecStartRequest(
|
|
79
89
|
task_id=task_id,
|
|
80
|
-
|
|
90
|
+
exec_id=process_id,
|
|
91
|
+
command_args=["/bin/bash"],
|
|
92
|
+
stdout_config=sr_pb2.TaskExecStdoutConfig.TASK_EXEC_STDOUT_CONFIG_PIPE,
|
|
93
|
+
stderr_config=sr_pb2.TaskExecStderrConfig.TASK_EXEC_STDERR_CONFIG_PIPE,
|
|
81
94
|
pty_info=get_pty_info(shell=True) if pty else None,
|
|
82
95
|
runtime_debug=config.get("function_runtime_debug"),
|
|
83
96
|
)
|
|
84
|
-
|
|
97
|
+
await command_router_client.exec_start(start_req)
|
|
98
|
+
|
|
85
99
|
if pty:
|
|
86
|
-
await _ContainerProcess(
|
|
100
|
+
await _ContainerProcess(process_id, task_id, client, command_router_client=command_router_client).attach()
|
|
87
101
|
else:
|
|
88
|
-
# TODO: redirect stderr to its own stream?
|
|
89
102
|
await _ContainerProcess(
|
|
90
|
-
|
|
103
|
+
process_id,
|
|
104
|
+
task_id,
|
|
105
|
+
client,
|
|
106
|
+
command_router_client=command_router_client,
|
|
107
|
+
stdout=StreamType.STDOUT,
|
|
108
|
+
stderr=StreamType.STDOUT,
|
|
91
109
|
).wait()
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# Copyright Modal Labs 2022
|
|
2
|
+
import uuid
|
|
2
3
|
import warnings
|
|
3
4
|
from datetime import datetime, timezone
|
|
4
5
|
from typing import Optional, Union
|
|
@@ -12,6 +13,7 @@ from modal._logs import _FETCH_LIMIT, _MAX_FETCH_RANGE, LogsFilters
|
|
|
12
13
|
from modal._object import _get_environment_name
|
|
13
14
|
from modal._output.pty import get_pty_info
|
|
14
15
|
from modal._utils.async_utils import synchronizer
|
|
16
|
+
from modal._utils.task_command_router_client import TaskCommandRouterClient
|
|
15
17
|
from modal._utils.time_utils import timestamp_to_localized_str
|
|
16
18
|
from modal.cli.app import _DEFAULT_LOGS_TAIL, _SOURCE_OPTIONS, _parse_time_arg
|
|
17
19
|
from modal.cli.utils import (
|
|
@@ -30,7 +32,7 @@ from modal.container_process import _ContainerProcess
|
|
|
30
32
|
from modal.environments import ensure_env
|
|
31
33
|
from modal.exception import InvalidError
|
|
32
34
|
from modal.stream_type import StreamType
|
|
33
|
-
from modal_proto import api_pb2
|
|
35
|
+
from modal_proto import api_pb2, task_command_router_pb2 as sr_pb2
|
|
34
36
|
|
|
35
37
|
from ._help import ModalGroup
|
|
36
38
|
|
|
@@ -276,20 +278,33 @@ async def _exec_impl(
|
|
|
276
278
|
|
|
277
279
|
client = await _Client.from_env()
|
|
278
280
|
|
|
279
|
-
|
|
281
|
+
command_router_client = await TaskCommandRouterClient.try_init(client, container_id)
|
|
282
|
+
if command_router_client is None:
|
|
283
|
+
raise InvalidError(f"Command router access is not available for container {container_id}")
|
|
284
|
+
|
|
285
|
+
process_id = str(uuid.uuid4())
|
|
286
|
+
|
|
287
|
+
start_req = sr_pb2.TaskExecStartRequest(
|
|
280
288
|
task_id=container_id,
|
|
281
|
-
|
|
289
|
+
exec_id=process_id,
|
|
290
|
+
command_args=command,
|
|
291
|
+
stdout_config=sr_pb2.TaskExecStdoutConfig.TASK_EXEC_STDOUT_CONFIG_PIPE,
|
|
292
|
+
stderr_config=sr_pb2.TaskExecStderrConfig.TASK_EXEC_STDERR_CONFIG_PIPE,
|
|
282
293
|
pty_info=get_pty_info(shell=True) if pty else None,
|
|
283
294
|
runtime_debug=config.get("function_runtime_debug"),
|
|
284
295
|
)
|
|
285
|
-
|
|
296
|
+
await command_router_client.exec_start(start_req)
|
|
286
297
|
|
|
287
298
|
if pty:
|
|
288
|
-
await _ContainerProcess(
|
|
299
|
+
await _ContainerProcess(process_id, container_id, client, command_router_client=command_router_client).attach()
|
|
289
300
|
else:
|
|
290
|
-
# TODO: redirect stderr to its own stream?
|
|
291
301
|
await _ContainerProcess(
|
|
292
|
-
|
|
302
|
+
process_id,
|
|
303
|
+
container_id,
|
|
304
|
+
client,
|
|
305
|
+
command_router_client=command_router_client,
|
|
306
|
+
stdout=StreamType.STDOUT,
|
|
307
|
+
stderr=StreamType.STDOUT,
|
|
293
308
|
).wait()
|
|
294
309
|
|
|
295
310
|
|
|
@@ -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.3.
|
|
38
|
+
version: str = "1.4.3.dev8",
|
|
39
39
|
):
|
|
40
40
|
"""mdmd:hidden
|
|
41
41
|
The Modal client object is not intended to be instantiated directly by users.
|
|
@@ -175,7 +175,7 @@ class Client:
|
|
|
175
175
|
server_url: str,
|
|
176
176
|
client_type: int,
|
|
177
177
|
credentials: typing.Optional[tuple[str, str]],
|
|
178
|
-
version: str = "1.4.3.
|
|
178
|
+
version: str = "1.4.3.dev8",
|
|
179
179
|
):
|
|
180
180
|
"""mdmd:hidden
|
|
181
181
|
The Modal client object is not intended to be instantiated directly by users.
|
|
@@ -396,7 +396,7 @@ class _FileIO(Generic[T]):
|
|
|
396
396
|
"""List the contents of the provided directory."""
|
|
397
397
|
deprecation_warning(
|
|
398
398
|
(2026, 3, 9),
|
|
399
|
-
"`FileIO.ls()` is deprecated. Use `Sandbox.
|
|
399
|
+
"`FileIO.ls()` is deprecated. Use `Sandbox.filesystem.list_files()` instead.",
|
|
400
400
|
pending=True,
|
|
401
401
|
)
|
|
402
402
|
return await ls(path, client, task_id)
|
|
@@ -628,6 +628,7 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
628
628
|
idle_timeout: Optional[int] = None,
|
|
629
629
|
workdir: Optional[str] = None,
|
|
630
630
|
cpu: Optional[float] = None,
|
|
631
|
+
memory: Optional[int] = None,
|
|
631
632
|
cloud: Optional[str] = None,
|
|
632
633
|
region: Optional[Union[str, Sequence[str]]] = None,
|
|
633
634
|
block_network: bool = False,
|
|
@@ -642,7 +643,6 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
642
643
|
) -> "_Sandbox":
|
|
643
644
|
"""Create a sandbox using the V2 backend.
|
|
644
645
|
|
|
645
|
-
Only CPU is configurable; memory is derived as a fixed ratio of CPU.
|
|
646
646
|
Features like tags, snapshots, exec, volumes, network file systems,
|
|
647
647
|
GPUs, custom domains, and proxies are not supported.
|
|
648
648
|
"""
|
|
@@ -714,7 +714,7 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
714
714
|
timeout_secs=timeout,
|
|
715
715
|
idle_timeout_secs=idle_timeout,
|
|
716
716
|
workdir=workdir,
|
|
717
|
-
resources=convert_fn_config_to_resources_config(cpu=cpu, memory=
|
|
717
|
+
resources=convert_fn_config_to_resources_config(cpu=cpu, memory=memory, gpu=None, ephemeral_disk=None),
|
|
718
718
|
cloud_provider_str=cloud if cloud else None,
|
|
719
719
|
runtime=config.get("function_runtime"),
|
|
720
720
|
runtime_debug=config.get("function_runtime_debug"),
|
|
@@ -1641,8 +1641,16 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
1641
1641
|
return await _FileIO.create(path, mode, self._client, task_id)
|
|
1642
1642
|
|
|
1643
1643
|
async def ls(self, path: str) -> builtins.list[str]:
|
|
1644
|
-
"""[Alpha] List the contents of a directory in the Sandbox.
|
|
1644
|
+
"""[Alpha] List the contents of a directory in the Sandbox.
|
|
1645
|
+
|
|
1646
|
+
.. deprecated:: 2026-04-15
|
|
1647
|
+
Use `Sandbox.filesystem.list_files()` instead."""
|
|
1645
1648
|
self._ensure_v1("ls")
|
|
1649
|
+
deprecation_warning(
|
|
1650
|
+
(2026, 4, 15),
|
|
1651
|
+
"`Sandbox.ls()` is deprecated. Use `Sandbox.filesystem.list_files()` instead.",
|
|
1652
|
+
pending=True,
|
|
1653
|
+
)
|
|
1646
1654
|
task_id = await self._get_task_id()
|
|
1647
1655
|
return await ls(path, self._client, task_id)
|
|
1648
1656
|
|
|
@@ -304,6 +304,7 @@ class _Sandbox(modal._object._Object):
|
|
|
304
304
|
idle_timeout: typing.Optional[int] = None,
|
|
305
305
|
workdir: typing.Optional[str] = None,
|
|
306
306
|
cpu: typing.Optional[float] = None,
|
|
307
|
+
memory: typing.Optional[int] = None,
|
|
307
308
|
cloud: typing.Optional[str] = None,
|
|
308
309
|
region: typing.Union[str, collections.abc.Sequence[str], None] = None,
|
|
309
310
|
block_network: bool = False,
|
|
@@ -318,7 +319,6 @@ class _Sandbox(modal._object._Object):
|
|
|
318
319
|
) -> _Sandbox:
|
|
319
320
|
"""Create a sandbox using the V2 backend.
|
|
320
321
|
|
|
321
|
-
Only CPU is configurable; memory is derived as a fixed ratio of CPU.
|
|
322
322
|
Features like tags, snapshots, exec, volumes, network file systems,
|
|
323
323
|
GPUs, custom domains, and proxies are not supported.
|
|
324
324
|
"""
|
|
@@ -613,7 +613,11 @@ class _Sandbox(modal._object._Object):
|
|
|
613
613
|
@typing.overload
|
|
614
614
|
async def open(self, path: str, mode: _typeshed.OpenBinaryMode) -> modal.file_io._FileIO[bytes]: ...
|
|
615
615
|
async def ls(self, path: str) -> list[str]:
|
|
616
|
-
"""[Alpha] List the contents of a directory in the Sandbox.
|
|
616
|
+
"""[Alpha] List the contents of a directory in the Sandbox.
|
|
617
|
+
|
|
618
|
+
.. deprecated:: 2026-04-15
|
|
619
|
+
Use `Sandbox.filesystem.list_files()` instead.
|
|
620
|
+
"""
|
|
617
621
|
...
|
|
618
622
|
|
|
619
623
|
async def mkdir(self, path: str, parents: bool = False) -> None:
|
|
@@ -1186,6 +1190,7 @@ class Sandbox(modal.object.Object):
|
|
|
1186
1190
|
idle_timeout: typing.Optional[int] = None,
|
|
1187
1191
|
workdir: typing.Optional[str] = None,
|
|
1188
1192
|
cpu: typing.Optional[float] = None,
|
|
1193
|
+
memory: typing.Optional[int] = None,
|
|
1189
1194
|
cloud: typing.Optional[str] = None,
|
|
1190
1195
|
region: typing.Union[str, collections.abc.Sequence[str], None] = None,
|
|
1191
1196
|
block_network: bool = False,
|
|
@@ -1200,7 +1205,6 @@ class Sandbox(modal.object.Object):
|
|
|
1200
1205
|
) -> Sandbox:
|
|
1201
1206
|
"""Create a sandbox using the V2 backend.
|
|
1202
1207
|
|
|
1203
|
-
Only CPU is configurable; memory is derived as a fixed ratio of CPU.
|
|
1204
1208
|
Features like tags, snapshots, exec, volumes, network file systems,
|
|
1205
1209
|
GPUs, custom domains, and proxies are not supported.
|
|
1206
1210
|
"""
|
|
@@ -1219,6 +1223,7 @@ class Sandbox(modal.object.Object):
|
|
|
1219
1223
|
idle_timeout: typing.Optional[int] = None,
|
|
1220
1224
|
workdir: typing.Optional[str] = None,
|
|
1221
1225
|
cpu: typing.Optional[float] = None,
|
|
1226
|
+
memory: typing.Optional[int] = None,
|
|
1222
1227
|
cloud: typing.Optional[str] = None,
|
|
1223
1228
|
region: typing.Union[str, collections.abc.Sequence[str], None] = None,
|
|
1224
1229
|
block_network: bool = False,
|
|
@@ -1233,7 +1238,6 @@ class Sandbox(modal.object.Object):
|
|
|
1233
1238
|
) -> Sandbox:
|
|
1234
1239
|
"""Create a sandbox using the V2 backend.
|
|
1235
1240
|
|
|
1236
|
-
Only CPU is configurable; memory is derived as a fixed ratio of CPU.
|
|
1237
1241
|
Features like tags, snapshots, exec, volumes, network file systems,
|
|
1238
1242
|
GPUs, custom domains, and proxies are not supported.
|
|
1239
1243
|
"""
|
|
@@ -1908,11 +1912,19 @@ class Sandbox(modal.object.Object):
|
|
|
1908
1912
|
|
|
1909
1913
|
class __ls_spec(typing_extensions.Protocol):
|
|
1910
1914
|
def __call__(self, /, path: str) -> list[str]:
|
|
1911
|
-
"""[Alpha] List the contents of a directory in the Sandbox.
|
|
1915
|
+
"""[Alpha] List the contents of a directory in the Sandbox.
|
|
1916
|
+
|
|
1917
|
+
.. deprecated:: 2026-04-15
|
|
1918
|
+
Use `Sandbox.filesystem.list_files()` instead.
|
|
1919
|
+
"""
|
|
1912
1920
|
...
|
|
1913
1921
|
|
|
1914
1922
|
async def aio(self, /, path: str) -> list[str]:
|
|
1915
|
-
"""[Alpha] List the contents of a directory in the Sandbox.
|
|
1923
|
+
"""[Alpha] List the contents of a directory in the Sandbox.
|
|
1924
|
+
|
|
1925
|
+
.. deprecated:: 2026-04-15
|
|
1926
|
+
Use `Sandbox.filesystem.list_files()` instead.
|
|
1927
|
+
"""
|
|
1916
1928
|
...
|
|
1917
1929
|
|
|
1918
1930
|
ls: __ls_spec
|