modal 1.4.3.dev25__tar.gz → 1.4.3.dev26__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.dev25 → modal-1.4.3.dev26}/PKG-INFO +1 -1
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/cli/cluster.py +13 -1
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/cli/container.py +13 -1
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/cli/shell.py +4 -1
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/client.pyi +2 -2
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/experimental/flash.py +5 -5
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/sandbox.py +22 -12
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/sandbox.pyi +11 -8
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal.egg-info/PKG-INFO +1 -1
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal_proto/api_pb2.py +380 -380
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal_proto/api_pb2.pyi +14 -2
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal_version/__init__.py +1 -1
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/LICENSE +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/README.md +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/__init__.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/__main__.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_billing.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_clustered_functions.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_clustered_functions.pyi +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_container_entrypoint.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_environments.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_functions.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_grpc_client.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_ipython.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_load_context.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_location.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_logs.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_object.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_output/__init__.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_output/manager.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_output/pty.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_output/rich.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_output/status.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_partial_function.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_resolver.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_resources.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_runtime/__init__.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_runtime/asgi.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_runtime/container_io_manager.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_runtime/container_io_manager.pyi +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_runtime/execution_context.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_runtime/execution_context.pyi +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_runtime/gpu_memory_snapshot.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_runtime/telemetry.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_runtime/user_code_event_loop.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_runtime/user_code_imports.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_serialization.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_server.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_traceback.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_tunnel.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_tunnel.pyi +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_type_manager.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_utils/__init__.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_utils/app_utils.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_utils/async_utils.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_utils/auth_token_manager.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_utils/blob_utils.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_utils/browser_utils.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_utils/bytes_io_segment_payload.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_utils/deprecation.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_utils/docker_utils.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_utils/function_utils.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_utils/git_utils.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_utils/grpc_testing.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_utils/grpc_utils.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_utils/hash_utils.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_utils/http_utils.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_utils/jwt_utils.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_utils/logger.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_utils/mount_utils.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_utils/name_utils.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_utils/package_utils.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_utils/pattern_utils.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_utils/rand_pb_testing.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_utils/sandbox_fs_utils.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_utils/shell_utils.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_utils/task_command_router_client.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_utils/time_utils.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_vendor/__init__.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_vendor/a2wsgi_wsgi.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_vendor/cloudpickle.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_vendor/tblib.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_vendor/version.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/_watcher.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/app.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/app.pyi +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/billing.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/builder/2023.12.312.txt +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/builder/2023.12.txt +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/builder/2024.04.txt +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/builder/2024.10.txt +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/builder/2025.06.txt +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/builder/PREVIEW.txt +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/builder/README.md +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/builder/base-images.json +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/call_graph.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/cli/__init__.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/cli/_download.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/cli/_help.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/cli/_traceback.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/cli/app.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/cli/billing.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/cli/bootstrap.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/cli/changelog.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/cli/config.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/cli/dashboard.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/cli/dict.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/cli/entry_point.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/cli/environment.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/cli/import_refs.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/cli/launch.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/cli/logo.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/cli/network_file_system.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/cli/profile.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/cli/programs/__init__.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/cli/programs/run_jupyter.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/cli/programs/vscode.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/cli/queues.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/cli/run.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/cli/secret.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/cli/selector.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/cli/token.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/cli/utils.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/cli/volume.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/client.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/cloud_bucket_mount.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/cloud_bucket_mount.pyi +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/cls.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/cls.pyi +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/config.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/container_process.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/container_process.pyi +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/dict.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/dict.pyi +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/environments.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/environments.pyi +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/exception.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/experimental/__init__.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/experimental/flash.pyi +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/experimental/ipython.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/file_io.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/file_io.pyi +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/file_pattern_matcher.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/functions.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/functions.pyi +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/image.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/image.pyi +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/io_streams.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/io_streams.pyi +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/mount.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/mount.pyi +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/network_file_system.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/network_file_system.pyi +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/object.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/object.pyi +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/output.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/parallel_map.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/parallel_map.pyi +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/partial_function.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/partial_function.pyi +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/proxy.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/proxy.pyi +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/py.typed +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/queue.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/queue.pyi +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/retries.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/runner.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/runner.pyi +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/running_app.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/sandbox_fs.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/sandbox_fs.pyi +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/schedule.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/scheduler_placement.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/secret.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/secret.pyi +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/server.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/server.pyi +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/serving.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/serving.pyi +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/snapshot.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/snapshot.pyi +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/stream_type.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/token_flow.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/token_flow.pyi +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/volume.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal/volume.pyi +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal.egg-info/SOURCES.txt +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal.egg-info/dependency_links.txt +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal.egg-info/entry_points.txt +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal.egg-info/requires.txt +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal.egg-info/top_level.txt +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal_docs/__init__.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal_docs/gen_cli_docs.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal_docs/gen_cli_docs_main.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal_docs/gen_reference_docs.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal_docs/gen_reference_docs_main.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal_docs/mdmd/__init__.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal_docs/mdmd/mdmd.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal_docs/mdmd/signatures.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal_proto/__init__.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal_proto/api_grpc.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal_proto/api_pb2_grpc.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal_proto/api_pb2_grpc.pyi +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal_proto/modal_api_grpc.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal_proto/py.typed +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal_proto/task_command_router_grpc.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal_proto/task_command_router_pb2.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal_proto/task_command_router_pb2.pyi +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal_proto/task_command_router_pb2_grpc.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal_proto/task_command_router_pb2_grpc.pyi +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/modal_version/__main__.py +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/pyproject.toml +0 -0
- {modal-1.4.3.dev25 → modal-1.4.3.dev26}/setup.cfg +0 -0
|
@@ -94,7 +94,19 @@ async def shell(cluster_id: str, rank: int = 0):
|
|
|
94
94
|
await command_router_client.exec_start(start_req)
|
|
95
95
|
|
|
96
96
|
if pty:
|
|
97
|
-
|
|
97
|
+
# PTY output is raw terminal bytes (control sequences, mouse events,
|
|
98
|
+
# glyphs in non-UTF-8 locales, etc.) — not text. Strict UTF-8 decode on
|
|
99
|
+
# this stream crashes the shell as soon as anything emits a byte that
|
|
100
|
+
# isn't valid UTF-8, e.g. vim drawing a Latin-1 file under LC_CTYPE=C.
|
|
101
|
+
# Pass bytes through unmodified; `attach()` writes them straight to the
|
|
102
|
+
# local fd.
|
|
103
|
+
await _ContainerProcess(
|
|
104
|
+
process_id,
|
|
105
|
+
task_id,
|
|
106
|
+
client,
|
|
107
|
+
command_router_client=command_router_client,
|
|
108
|
+
text=False,
|
|
109
|
+
).attach()
|
|
98
110
|
else:
|
|
99
111
|
await _ContainerProcess(
|
|
100
112
|
process_id,
|
|
@@ -294,7 +294,19 @@ async def _exec_impl(
|
|
|
294
294
|
await command_router_client.exec_start(start_req)
|
|
295
295
|
|
|
296
296
|
if pty:
|
|
297
|
-
|
|
297
|
+
# PTY output is raw terminal bytes (control sequences, mouse events,
|
|
298
|
+
# glyphs in non-UTF-8 locales, etc.) — not text. Strict UTF-8 decode on
|
|
299
|
+
# this stream crashes the shell as soon as anything emits a byte that
|
|
300
|
+
# isn't valid UTF-8, e.g. vim drawing a Latin-1 file under LC_CTYPE=C.
|
|
301
|
+
# Pass bytes through unmodified; `attach()` writes them straight to the
|
|
302
|
+
# local fd.
|
|
303
|
+
await _ContainerProcess(
|
|
304
|
+
process_id,
|
|
305
|
+
container_id,
|
|
306
|
+
client,
|
|
307
|
+
command_router_client=command_router_client,
|
|
308
|
+
text=False,
|
|
309
|
+
).attach()
|
|
298
310
|
else:
|
|
299
311
|
await _ContainerProcess(
|
|
300
312
|
process_id,
|
|
@@ -100,7 +100,10 @@ def _start_shell_in_sandbox_container(sandbox_id: str, container_name: str, cmd:
|
|
|
100
100
|
try:
|
|
101
101
|
sandbox_container = sandbox._experimental_containers.get(name=container_name)
|
|
102
102
|
if pty:
|
|
103
|
-
|
|
103
|
+
# PTY output is raw terminal bytes, not text; strict UTF-8 decode
|
|
104
|
+
# crashes on the first non-UTF-8 byte (e.g. vim drawing a Latin-1
|
|
105
|
+
# file under LC_CTYPE=C). See the matching call in `_exec_impl`.
|
|
106
|
+
process = sandbox_container.exec(*shlex.split(cmd), pty=pty, text=False)
|
|
104
107
|
process.attach()
|
|
105
108
|
else:
|
|
106
109
|
process = sandbox_container.exec(
|
|
@@ -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.dev26",
|
|
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.dev26",
|
|
179
179
|
):
|
|
180
180
|
"""mdmd:hidden
|
|
181
181
|
The Modal client object is not intended to be instantiated directly by users.
|
|
@@ -76,7 +76,7 @@ class _FlashManager:
|
|
|
76
76
|
except (OSError, asyncio.TimeoutError):
|
|
77
77
|
await asyncio.sleep(0.1)
|
|
78
78
|
|
|
79
|
-
return False, Exception(f"Waited too long for port {self.port} to
|
|
79
|
+
return False, Exception(f"Waited too long for port {self.port} to accept connections")
|
|
80
80
|
|
|
81
81
|
async def _start(self):
|
|
82
82
|
self.tunnel = await self.tunnel_manager.__aenter__()
|
|
@@ -152,16 +152,16 @@ class _FlashManager:
|
|
|
152
152
|
logger.warning(f"Listening at {resp.url} over {self.tunnel.url} for task_id {self.task_id}")
|
|
153
153
|
return True
|
|
154
154
|
except asyncio.CancelledError:
|
|
155
|
-
logger.warning("
|
|
155
|
+
logger.warning("Healthcheck cancelled while waiting for port to accept connections. Shutting down...")
|
|
156
156
|
raise
|
|
157
157
|
except Exception as e:
|
|
158
|
-
logger.error(f"Error waiting for port to
|
|
158
|
+
logger.error(f"Error waiting for port to accept connections: {e}")
|
|
159
159
|
try:
|
|
160
160
|
await asyncio.sleep(1)
|
|
161
161
|
except asyncio.CancelledError:
|
|
162
|
-
logger.warning("
|
|
162
|
+
logger.warning("Healthcheck cancelled while waiting for port to accept connections. Shutting down...")
|
|
163
163
|
raise
|
|
164
|
-
raise TimeoutError("
|
|
164
|
+
raise TimeoutError("Timed out while waiting for port to accept connections. Shutting down...")
|
|
165
165
|
|
|
166
166
|
async def _run_heartbeat(self, host: str, port: int):
|
|
167
167
|
while True:
|
|
@@ -232,7 +232,7 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
232
232
|
mounts: Sequence[_Mount] = (),
|
|
233
233
|
network_file_systems: dict[Union[str, os.PathLike], _NetworkFileSystem] = {},
|
|
234
234
|
block_network: bool = False,
|
|
235
|
-
|
|
235
|
+
outbound_cidr_allowlist: Optional[Sequence[str]] = None,
|
|
236
236
|
inbound_cidr_allowlist: Optional[Sequence[str]] = None,
|
|
237
237
|
volumes: dict[Union[str, os.PathLike], Union[_Volume, _CloudBucketMount]] = {},
|
|
238
238
|
pty: bool = False,
|
|
@@ -321,15 +321,14 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
321
321
|
)
|
|
322
322
|
|
|
323
323
|
if block_network:
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
raise InvalidError("`cidr_allowlist` cannot be used when `block_network` is enabled")
|
|
324
|
+
if outbound_cidr_allowlist is not None:
|
|
325
|
+
raise InvalidError("`outbound_cidr_allowlist` cannot be used when `block_network` is enabled")
|
|
327
326
|
if inbound_cidr_allowlist is not None:
|
|
328
327
|
raise InvalidError("`inbound_cidr_allowlist` cannot be used when `block_network` is enabled")
|
|
329
328
|
network_access = api_pb2.NetworkAccess(
|
|
330
329
|
network_access_type=api_pb2.NetworkAccess.NetworkAccessType.BLOCKED,
|
|
331
330
|
)
|
|
332
|
-
elif
|
|
331
|
+
elif outbound_cidr_allowlist is None:
|
|
333
332
|
# If the allowlist is empty, we allow all network access.
|
|
334
333
|
network_access = api_pb2.NetworkAccess(
|
|
335
334
|
network_access_type=api_pb2.NetworkAccess.NetworkAccessType.OPEN,
|
|
@@ -337,7 +336,7 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
337
336
|
else:
|
|
338
337
|
network_access = api_pb2.NetworkAccess(
|
|
339
338
|
network_access_type=api_pb2.NetworkAccess.NetworkAccessType.ALLOWLIST,
|
|
340
|
-
allowed_cidrs=
|
|
339
|
+
allowed_cidrs=outbound_cidr_allowlist,
|
|
341
340
|
)
|
|
342
341
|
|
|
343
342
|
ephemeral_disk = None # Ephemeral disk requests not supported on Sandboxes.
|
|
@@ -412,7 +411,7 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
412
411
|
memory: Optional[Union[int, tuple[int, int]]] = None,
|
|
413
412
|
block_network: bool = False, # Whether to block network access
|
|
414
413
|
# List of CIDRs the sandbox is allowed to access. If None, all CIDRs are allowed.
|
|
415
|
-
|
|
414
|
+
outbound_cidr_allowlist: Optional[Sequence[str]] = None,
|
|
416
415
|
# List of CIDRs allowed to connect inbound to the sandbox (tunnels and connection tokens).
|
|
417
416
|
inbound_cidr_allowlist: Optional[Sequence[str]] = None,
|
|
418
417
|
volumes: dict[
|
|
@@ -443,6 +442,7 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
443
442
|
client: Optional[_Client] = None,
|
|
444
443
|
environment_name: Optional[str] = None, # *DEPRECATED* Optionally override the default environment
|
|
445
444
|
pty_info: Optional[api_pb2.PTYInfo] = None, # *DEPRECATED* Use `pty` instead. `pty` will override `pty_info`.
|
|
445
|
+
cidr_allowlist: Optional[Sequence[str]] = None, # *DEPRECATED* Use outbound_cidr_allowlist instead.
|
|
446
446
|
) -> "_Sandbox":
|
|
447
447
|
"""
|
|
448
448
|
Create a new Sandbox to run untrusted, arbitrary code.
|
|
@@ -472,6 +472,16 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
472
472
|
"Set the `pty` parameter to `True` instead.",
|
|
473
473
|
)
|
|
474
474
|
|
|
475
|
+
if cidr_allowlist is not None:
|
|
476
|
+
if outbound_cidr_allowlist is not None:
|
|
477
|
+
raise InvalidError("Cannot specify both `cidr_allowlist` and `outbound_cidr_allowlist`.")
|
|
478
|
+
deprecation_warning(
|
|
479
|
+
(2026, 5, 11),
|
|
480
|
+
"The `cidr_allowlist` parameter has been renamed to `outbound_cidr_allowlist`. "
|
|
481
|
+
"`cidr_allowlist` will be removed in a future release.",
|
|
482
|
+
)
|
|
483
|
+
outbound_cidr_allowlist = cidr_allowlist
|
|
484
|
+
|
|
475
485
|
secrets = secrets or []
|
|
476
486
|
if env:
|
|
477
487
|
secrets = [*secrets, _Secret.from_dict(env)]
|
|
@@ -492,7 +502,7 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
492
502
|
cpu=cpu,
|
|
493
503
|
memory=memory,
|
|
494
504
|
block_network=block_network,
|
|
495
|
-
|
|
505
|
+
outbound_cidr_allowlist=outbound_cidr_allowlist,
|
|
496
506
|
inbound_cidr_allowlist=inbound_cidr_allowlist,
|
|
497
507
|
volumes=volumes,
|
|
498
508
|
pty=pty,
|
|
@@ -531,7 +541,7 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
531
541
|
cpu: Optional[Union[float, tuple[float, float]]] = None,
|
|
532
542
|
memory: Optional[Union[int, tuple[int, int]]] = None,
|
|
533
543
|
block_network: bool = False,
|
|
534
|
-
|
|
544
|
+
outbound_cidr_allowlist: Optional[Sequence[str]] = None,
|
|
535
545
|
inbound_cidr_allowlist: Optional[Sequence[str]] = None,
|
|
536
546
|
volumes: dict[Union[str, os.PathLike], Union[_Volume, _CloudBucketMount]] = {},
|
|
537
547
|
pty: bool = False,
|
|
@@ -584,7 +594,7 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
584
594
|
mounts=mounts,
|
|
585
595
|
network_file_systems=network_file_systems,
|
|
586
596
|
block_network=block_network,
|
|
587
|
-
|
|
597
|
+
outbound_cidr_allowlist=outbound_cidr_allowlist,
|
|
588
598
|
inbound_cidr_allowlist=inbound_cidr_allowlist,
|
|
589
599
|
volumes=volumes,
|
|
590
600
|
pty=pty,
|
|
@@ -1270,8 +1280,8 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
1270
1280
|
)
|
|
1271
1281
|
else:
|
|
1272
1282
|
self._command_router_client = await TaskCommandRouterClient.init(self._client, task_id)
|
|
1273
|
-
except
|
|
1274
|
-
raise NotFoundError(
|
|
1283
|
+
except ConflictError as e:
|
|
1284
|
+
raise NotFoundError(str(e)) from e
|
|
1275
1285
|
return self._command_router_client
|
|
1276
1286
|
|
|
1277
1287
|
@property
|
|
@@ -172,7 +172,7 @@ class _Sandbox(modal._object._Object):
|
|
|
172
172
|
mounts: collections.abc.Sequence[modal.mount._Mount] = (),
|
|
173
173
|
network_file_systems: dict[typing.Union[str, os.PathLike], modal.network_file_system._NetworkFileSystem] = {},
|
|
174
174
|
block_network: bool = False,
|
|
175
|
-
|
|
175
|
+
outbound_cidr_allowlist: typing.Optional[collections.abc.Sequence[str]] = None,
|
|
176
176
|
inbound_cidr_allowlist: typing.Optional[collections.abc.Sequence[str]] = None,
|
|
177
177
|
volumes: dict[
|
|
178
178
|
typing.Union[str, os.PathLike],
|
|
@@ -214,7 +214,7 @@ class _Sandbox(modal._object._Object):
|
|
|
214
214
|
cpu: typing.Union[float, tuple[float, float], None] = None,
|
|
215
215
|
memory: typing.Union[int, tuple[int, int], None] = None,
|
|
216
216
|
block_network: bool = False,
|
|
217
|
-
|
|
217
|
+
outbound_cidr_allowlist: typing.Optional[collections.abc.Sequence[str]] = None,
|
|
218
218
|
inbound_cidr_allowlist: typing.Optional[collections.abc.Sequence[str]] = None,
|
|
219
219
|
volumes: dict[
|
|
220
220
|
typing.Union[str, os.PathLike],
|
|
@@ -234,6 +234,7 @@ class _Sandbox(modal._object._Object):
|
|
|
234
234
|
client: typing.Optional[modal.client._Client] = None,
|
|
235
235
|
environment_name: typing.Optional[str] = None,
|
|
236
236
|
pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
|
|
237
|
+
cidr_allowlist: typing.Optional[collections.abc.Sequence[str]] = None,
|
|
237
238
|
) -> _Sandbox:
|
|
238
239
|
"""Create a new Sandbox to run untrusted, arbitrary code.
|
|
239
240
|
|
|
@@ -270,7 +271,7 @@ class _Sandbox(modal._object._Object):
|
|
|
270
271
|
cpu: typing.Union[float, tuple[float, float], None] = None,
|
|
271
272
|
memory: typing.Union[int, tuple[int, int], None] = None,
|
|
272
273
|
block_network: bool = False,
|
|
273
|
-
|
|
274
|
+
outbound_cidr_allowlist: typing.Optional[collections.abc.Sequence[str]] = None,
|
|
274
275
|
inbound_cidr_allowlist: typing.Optional[collections.abc.Sequence[str]] = None,
|
|
275
276
|
volumes: dict[
|
|
276
277
|
typing.Union[str, os.PathLike],
|
|
@@ -926,7 +927,7 @@ class Sandbox(modal.object.Object):
|
|
|
926
927
|
mounts: collections.abc.Sequence[modal.mount.Mount] = (),
|
|
927
928
|
network_file_systems: dict[typing.Union[str, os.PathLike], modal.network_file_system.NetworkFileSystem] = {},
|
|
928
929
|
block_network: bool = False,
|
|
929
|
-
|
|
930
|
+
outbound_cidr_allowlist: typing.Optional[collections.abc.Sequence[str]] = None,
|
|
930
931
|
inbound_cidr_allowlist: typing.Optional[collections.abc.Sequence[str]] = None,
|
|
931
932
|
volumes: dict[
|
|
932
933
|
typing.Union[str, os.PathLike], typing.Union[modal.volume.Volume, modal.cloud_bucket_mount.CloudBucketMount]
|
|
@@ -971,7 +972,7 @@ class Sandbox(modal.object.Object):
|
|
|
971
972
|
cpu: typing.Union[float, tuple[float, float], None] = None,
|
|
972
973
|
memory: typing.Union[int, tuple[int, int], None] = None,
|
|
973
974
|
block_network: bool = False,
|
|
974
|
-
|
|
975
|
+
outbound_cidr_allowlist: typing.Optional[collections.abc.Sequence[str]] = None,
|
|
975
976
|
inbound_cidr_allowlist: typing.Optional[collections.abc.Sequence[str]] = None,
|
|
976
977
|
volumes: dict[
|
|
977
978
|
typing.Union[str, os.PathLike],
|
|
@@ -991,6 +992,7 @@ class Sandbox(modal.object.Object):
|
|
|
991
992
|
client: typing.Optional[modal.client.Client] = None,
|
|
992
993
|
environment_name: typing.Optional[str] = None,
|
|
993
994
|
pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
|
|
995
|
+
cidr_allowlist: typing.Optional[collections.abc.Sequence[str]] = None,
|
|
994
996
|
) -> Sandbox:
|
|
995
997
|
"""Create a new Sandbox to run untrusted, arbitrary code.
|
|
996
998
|
|
|
@@ -1029,7 +1031,7 @@ class Sandbox(modal.object.Object):
|
|
|
1029
1031
|
cpu: typing.Union[float, tuple[float, float], None] = None,
|
|
1030
1032
|
memory: typing.Union[int, tuple[int, int], None] = None,
|
|
1031
1033
|
block_network: bool = False,
|
|
1032
|
-
|
|
1034
|
+
outbound_cidr_allowlist: typing.Optional[collections.abc.Sequence[str]] = None,
|
|
1033
1035
|
inbound_cidr_allowlist: typing.Optional[collections.abc.Sequence[str]] = None,
|
|
1034
1036
|
volumes: dict[
|
|
1035
1037
|
typing.Union[str, os.PathLike],
|
|
@@ -1049,6 +1051,7 @@ class Sandbox(modal.object.Object):
|
|
|
1049
1051
|
client: typing.Optional[modal.client.Client] = None,
|
|
1050
1052
|
environment_name: typing.Optional[str] = None,
|
|
1051
1053
|
pty_info: typing.Optional[modal_proto.api_pb2.PTYInfo] = None,
|
|
1054
|
+
cidr_allowlist: typing.Optional[collections.abc.Sequence[str]] = None,
|
|
1052
1055
|
) -> Sandbox:
|
|
1053
1056
|
"""Create a new Sandbox to run untrusted, arbitrary code.
|
|
1054
1057
|
|
|
@@ -1091,7 +1094,7 @@ class Sandbox(modal.object.Object):
|
|
|
1091
1094
|
cpu: typing.Union[float, tuple[float, float], None] = None,
|
|
1092
1095
|
memory: typing.Union[int, tuple[int, int], None] = None,
|
|
1093
1096
|
block_network: bool = False,
|
|
1094
|
-
|
|
1097
|
+
outbound_cidr_allowlist: typing.Optional[collections.abc.Sequence[str]] = None,
|
|
1095
1098
|
inbound_cidr_allowlist: typing.Optional[collections.abc.Sequence[str]] = None,
|
|
1096
1099
|
volumes: dict[
|
|
1097
1100
|
typing.Union[str, os.PathLike],
|
|
@@ -1142,7 +1145,7 @@ class Sandbox(modal.object.Object):
|
|
|
1142
1145
|
cpu: typing.Union[float, tuple[float, float], None] = None,
|
|
1143
1146
|
memory: typing.Union[int, tuple[int, int], None] = None,
|
|
1144
1147
|
block_network: bool = False,
|
|
1145
|
-
|
|
1148
|
+
outbound_cidr_allowlist: typing.Optional[collections.abc.Sequence[str]] = None,
|
|
1146
1149
|
inbound_cidr_allowlist: typing.Optional[collections.abc.Sequence[str]] = None,
|
|
1147
1150
|
volumes: dict[
|
|
1148
1151
|
typing.Union[str, os.PathLike],
|