modAL 1.2.3.dev10__tar.gz → 1.2.3.dev11__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.2.3.dev10 → modal-1.2.3.dev11}/PKG-INFO +1 -1
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/client.pyi +2 -2
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/io_streams.py +101 -32
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/io_streams.pyi +30 -5
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/sandbox.py +2 -6
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal.egg-info/PKG-INFO +1 -1
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal_version/__init__.py +1 -1
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/LICENSE +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/README.md +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/__init__.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/__main__.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_billing.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_clustered_functions.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_clustered_functions.pyi +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_container_entrypoint.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_functions.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_grpc_client.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_ipython.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_load_context.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_location.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_object.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_output.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_partial_function.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_pty.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_resolver.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_resources.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_runtime/__init__.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_runtime/asgi.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_runtime/container_io_manager.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_runtime/container_io_manager.pyi +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_runtime/execution_context.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_runtime/execution_context.pyi +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_runtime/gpu_memory_snapshot.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_runtime/telemetry.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_runtime/user_code_imports.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_serialization.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_traceback.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_tunnel.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_tunnel.pyi +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_type_manager.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_utils/__init__.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_utils/app_utils.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_utils/async_utils.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_utils/auth_token_manager.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_utils/blob_utils.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_utils/bytes_io_segment_payload.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_utils/deprecation.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_utils/docker_utils.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_utils/function_utils.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_utils/git_utils.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_utils/grpc_testing.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_utils/grpc_utils.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_utils/hash_utils.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_utils/http_utils.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_utils/jwt_utils.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_utils/logger.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_utils/mount_utils.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_utils/name_utils.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_utils/package_utils.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_utils/pattern_utils.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_utils/rand_pb_testing.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_utils/shell_utils.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_utils/task_command_router_client.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_utils/time_utils.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_vendor/__init__.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_vendor/a2wsgi_wsgi.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_vendor/cloudpickle.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_vendor/tblib.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/_watcher.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/app.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/app.pyi +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/billing.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/builder/2023.12.312.txt +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/builder/2023.12.txt +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/builder/2024.04.txt +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/builder/2024.10.txt +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/builder/2025.06.txt +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/builder/PREVIEW.txt +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/builder/README.md +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/builder/base-images.json +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/call_graph.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/cli/__init__.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/cli/_download.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/cli/_traceback.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/cli/app.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/cli/cluster.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/cli/config.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/cli/container.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/cli/dict.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/cli/entry_point.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/cli/environment.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/cli/import_refs.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/cli/launch.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/cli/network_file_system.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/cli/profile.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/cli/programs/__init__.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/cli/programs/launch_instance_ssh.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/cli/programs/run_jupyter.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/cli/programs/run_marimo.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/cli/programs/vscode.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/cli/queues.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/cli/run.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/cli/secret.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/cli/token.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/cli/utils.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/cli/volume.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/client.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/cloud_bucket_mount.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/cloud_bucket_mount.pyi +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/cls.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/cls.pyi +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/config.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/container_process.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/container_process.pyi +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/dict.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/dict.pyi +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/environments.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/environments.pyi +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/exception.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/experimental/__init__.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/experimental/flash.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/experimental/flash.pyi +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/experimental/ipython.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/file_io.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/file_io.pyi +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/file_pattern_matcher.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/functions.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/functions.pyi +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/gpu.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/image.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/image.pyi +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/mount.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/mount.pyi +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/network_file_system.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/network_file_system.pyi +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/object.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/object.pyi +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/output.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/parallel_map.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/parallel_map.pyi +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/partial_function.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/partial_function.pyi +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/proxy.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/proxy.pyi +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/py.typed +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/queue.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/queue.pyi +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/retries.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/runner.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/runner.pyi +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/running_app.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/sandbox.pyi +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/schedule.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/scheduler_placement.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/secret.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/secret.pyi +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/serving.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/serving.pyi +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/snapshot.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/snapshot.pyi +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/stream_type.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/token_flow.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/token_flow.pyi +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/volume.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal/volume.pyi +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal.egg-info/SOURCES.txt +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal.egg-info/dependency_links.txt +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal.egg-info/entry_points.txt +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal.egg-info/requires.txt +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal.egg-info/top_level.txt +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal_docs/__init__.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal_docs/gen_cli_docs.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal_docs/gen_reference_docs.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal_docs/mdmd/__init__.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal_docs/mdmd/mdmd.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal_docs/mdmd/signatures.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal_proto/__init__.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal_proto/api.proto +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal_proto/api_grpc.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal_proto/api_pb2.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal_proto/api_pb2.pyi +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal_proto/api_pb2_grpc.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal_proto/api_pb2_grpc.pyi +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal_proto/modal_api_grpc.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal_proto/py.typed +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal_proto/sandbox_router.proto +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal_proto/sandbox_router_grpc.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal_proto/sandbox_router_pb2.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal_proto/sandbox_router_pb2.pyi +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal_proto/sandbox_router_pb2_grpc.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal_proto/sandbox_router_pb2_grpc.pyi +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal_proto/task_command_router.proto +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal_proto/task_command_router_grpc.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal_proto/task_command_router_pb2.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal_proto/task_command_router_pb2.pyi +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal_proto/task_command_router_pb2_grpc.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal_proto/task_command_router_pb2_grpc.pyi +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/modal_version/__main__.py +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/pyproject.toml +0 -0
- {modal-1.2.3.dev10 → modal-1.2.3.dev11}/setup.cfg +0 -0
|
@@ -33,7 +33,7 @@ class _Client:
|
|
|
33
33
|
server_url: str,
|
|
34
34
|
client_type: int,
|
|
35
35
|
credentials: typing.Optional[tuple[str, str]],
|
|
36
|
-
version: str = "1.2.3.
|
|
36
|
+
version: str = "1.2.3.dev11",
|
|
37
37
|
):
|
|
38
38
|
"""mdmd:hidden
|
|
39
39
|
The Modal client object is not intended to be instantiated directly by users.
|
|
@@ -164,7 +164,7 @@ class Client:
|
|
|
164
164
|
server_url: str,
|
|
165
165
|
client_type: int,
|
|
166
166
|
credentials: typing.Optional[tuple[str, str]],
|
|
167
|
-
version: str = "1.2.3.
|
|
167
|
+
version: str = "1.2.3.dev11",
|
|
168
168
|
):
|
|
169
169
|
"""mdmd:hidden
|
|
170
170
|
The Modal client object is not intended to be instantiated directly by users.
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# Copyright Modal Labs 2022
|
|
2
2
|
import asyncio
|
|
3
3
|
import codecs
|
|
4
|
+
import contextlib
|
|
5
|
+
import sys
|
|
4
6
|
import time
|
|
5
7
|
from collections.abc import AsyncGenerator, AsyncIterator
|
|
6
8
|
from dataclasses import dataclass
|
|
@@ -377,7 +379,7 @@ async def _stdio_stream_from_command_router(
|
|
|
377
379
|
return
|
|
378
380
|
|
|
379
381
|
|
|
380
|
-
class _BytesStreamReaderThroughCommandRouter
|
|
382
|
+
class _BytesStreamReaderThroughCommandRouter:
|
|
381
383
|
"""
|
|
382
384
|
StreamReader implementation that will read directly from the worker that
|
|
383
385
|
hosts the sandbox.
|
|
@@ -396,27 +398,27 @@ class _BytesStreamReaderThroughCommandRouter(Generic[T]):
|
|
|
396
398
|
def file_descriptor(self) -> int:
|
|
397
399
|
return self._params.file_descriptor
|
|
398
400
|
|
|
399
|
-
async def read(self) ->
|
|
401
|
+
async def read(self) -> bytes:
|
|
400
402
|
data_bytes = b""
|
|
401
403
|
async for part in self:
|
|
402
404
|
data_bytes += cast(bytes, part)
|
|
403
|
-
return
|
|
405
|
+
return data_bytes
|
|
404
406
|
|
|
405
|
-
def __aiter__(self) -> AsyncIterator[
|
|
407
|
+
def __aiter__(self) -> AsyncIterator[bytes]:
|
|
406
408
|
return self
|
|
407
409
|
|
|
408
|
-
async def __anext__(self) ->
|
|
410
|
+
async def __anext__(self) -> bytes:
|
|
409
411
|
if self._stream is None:
|
|
410
412
|
self._stream = _stdio_stream_from_command_router(self._params)
|
|
411
413
|
# This raises StopAsyncIteration if the stream is at EOF.
|
|
412
|
-
return
|
|
414
|
+
return await self._stream.__anext__()
|
|
413
415
|
|
|
414
416
|
async def aclose(self):
|
|
415
417
|
if self._stream:
|
|
416
418
|
await self._stream.aclose()
|
|
417
419
|
|
|
418
420
|
|
|
419
|
-
class _TextStreamReaderThroughCommandRouter
|
|
421
|
+
class _TextStreamReaderThroughCommandRouter:
|
|
420
422
|
"""
|
|
421
423
|
StreamReader implementation that will read directly from the worker
|
|
422
424
|
that hosts the sandbox.
|
|
@@ -437,16 +439,16 @@ class _TextStreamReaderThroughCommandRouter(Generic[T]):
|
|
|
437
439
|
def file_descriptor(self) -> int:
|
|
438
440
|
return self._params.file_descriptor
|
|
439
441
|
|
|
440
|
-
async def read(self) ->
|
|
442
|
+
async def read(self) -> str:
|
|
441
443
|
data_str = ""
|
|
442
444
|
async for part in self:
|
|
443
445
|
data_str += cast(str, part)
|
|
444
|
-
return
|
|
446
|
+
return data_str
|
|
445
447
|
|
|
446
|
-
def __aiter__(self) -> AsyncIterator[
|
|
448
|
+
def __aiter__(self) -> AsyncIterator[str]:
|
|
447
449
|
return self
|
|
448
450
|
|
|
449
|
-
async def __anext__(self) ->
|
|
451
|
+
async def __anext__(self) -> str:
|
|
450
452
|
if self._stream is None:
|
|
451
453
|
bytes_stream = _stdio_stream_from_command_router(self._params)
|
|
452
454
|
if self._by_line:
|
|
@@ -454,13 +456,88 @@ class _TextStreamReaderThroughCommandRouter(Generic[T]):
|
|
|
454
456
|
else:
|
|
455
457
|
self._stream = _decode_bytes_stream_to_str(bytes_stream)
|
|
456
458
|
# This raises StopAsyncIteration if the stream is at EOF.
|
|
457
|
-
return
|
|
459
|
+
return await self._stream.__anext__()
|
|
458
460
|
|
|
459
461
|
async def aclose(self):
|
|
460
462
|
if self._stream:
|
|
461
463
|
await self._stream.aclose()
|
|
462
464
|
|
|
463
465
|
|
|
466
|
+
class _StdoutPrintingStreamReaderThroughCommandRouter(Generic[T]):
|
|
467
|
+
"""
|
|
468
|
+
StreamReader implementation for StreamType.STDOUT when using the task command router.
|
|
469
|
+
|
|
470
|
+
This mirrors the behavior from the server-backed implementation: the stream is printed to
|
|
471
|
+
the local stdout immediately and is not readable via StreamReader methods.
|
|
472
|
+
"""
|
|
473
|
+
|
|
474
|
+
_reader: Union[_TextStreamReaderThroughCommandRouter, _BytesStreamReaderThroughCommandRouter]
|
|
475
|
+
|
|
476
|
+
def __init__(
|
|
477
|
+
self,
|
|
478
|
+
reader: Union[_TextStreamReaderThroughCommandRouter, _BytesStreamReaderThroughCommandRouter],
|
|
479
|
+
) -> None:
|
|
480
|
+
self._reader = reader
|
|
481
|
+
self._task: Optional[asyncio.Task[None]] = None
|
|
482
|
+
self._closed = False
|
|
483
|
+
# Kick off a background task that reads from the underlying text stream and prints to stdout.
|
|
484
|
+
self._start_printing_task()
|
|
485
|
+
|
|
486
|
+
@property
|
|
487
|
+
def file_descriptor(self) -> int:
|
|
488
|
+
return self._reader.file_descriptor
|
|
489
|
+
|
|
490
|
+
def _start_printing_task(self) -> None:
|
|
491
|
+
async def _run():
|
|
492
|
+
try:
|
|
493
|
+
|
|
494
|
+
def print_text_part(part: Union[str, bytes]) -> None:
|
|
495
|
+
assert isinstance(part, str)
|
|
496
|
+
print(cast(str, part), end="")
|
|
497
|
+
|
|
498
|
+
def print_bytes_part(part: Union[str, bytes]) -> None:
|
|
499
|
+
assert isinstance(part, bytes)
|
|
500
|
+
sys.stdout.buffer.write(cast(bytes, part))
|
|
501
|
+
sys.stdout.buffer.flush()
|
|
502
|
+
|
|
503
|
+
if isinstance(self._reader, _BytesStreamReaderThroughCommandRouter):
|
|
504
|
+
print_part = print_bytes_part
|
|
505
|
+
elif isinstance(self._reader, _TextStreamReaderThroughCommandRouter):
|
|
506
|
+
print_part = print_text_part
|
|
507
|
+
else:
|
|
508
|
+
raise ValueError("Unsupported reader type")
|
|
509
|
+
|
|
510
|
+
async for part in self._reader:
|
|
511
|
+
print_part(part)
|
|
512
|
+
except Exception as e:
|
|
513
|
+
logger.exception(f"Error printing stream: {e}")
|
|
514
|
+
finally:
|
|
515
|
+
closed, self._closed = self._closed, True
|
|
516
|
+
if not closed:
|
|
517
|
+
await self._reader.aclose()
|
|
518
|
+
|
|
519
|
+
self._task = asyncio.create_task(_run())
|
|
520
|
+
|
|
521
|
+
async def read(self) -> T:
|
|
522
|
+
raise InvalidError("Output can only be retrieved using the PIPE stream type.")
|
|
523
|
+
|
|
524
|
+
def __aiter__(self) -> AsyncIterator[T]:
|
|
525
|
+
raise InvalidError("Output can only be retrieved using the PIPE stream type.")
|
|
526
|
+
|
|
527
|
+
async def __anext__(self) -> T:
|
|
528
|
+
raise InvalidError("Output can only be retrieved using the PIPE stream type.")
|
|
529
|
+
|
|
530
|
+
async def aclose(self):
|
|
531
|
+
if self._task is not None:
|
|
532
|
+
self._task.cancel()
|
|
533
|
+
with contextlib.suppress(asyncio.CancelledError):
|
|
534
|
+
await self._task
|
|
535
|
+
self._task = None
|
|
536
|
+
closed, self._closed = self._closed, True
|
|
537
|
+
if not closed:
|
|
538
|
+
await self._reader.aclose()
|
|
539
|
+
|
|
540
|
+
|
|
464
541
|
class _DevnullStreamReader(Generic[T]):
|
|
465
542
|
"""StreamReader implementation for a stream configured with
|
|
466
543
|
StreamType.DEVNULL. Throws an error if read or any other method is
|
|
@@ -499,6 +576,7 @@ class _StreamReader(Generic[T]):
|
|
|
499
576
|
_DevnullStreamReader,
|
|
500
577
|
_TextStreamReaderThroughCommandRouter,
|
|
501
578
|
_BytesStreamReaderThroughCommandRouter,
|
|
579
|
+
_StdoutPrintingStreamReaderThroughCommandRouter,
|
|
502
580
|
]
|
|
503
581
|
|
|
504
582
|
def __init__(
|
|
@@ -523,35 +601,26 @@ class _StreamReader(Generic[T]):
|
|
|
523
601
|
file_descriptor, object_id, object_type, client, stream_type, text, by_line, deadline
|
|
524
602
|
)
|
|
525
603
|
else:
|
|
526
|
-
# The only reason task_id is optional is because StreamReader is
|
|
527
|
-
#
|
|
528
|
-
# when the StreamReader is created.
|
|
604
|
+
# The only reason task_id is optional is because StreamReader is also used for sandbox
|
|
605
|
+
# logs, which don't have a task ID available when the StreamReader is created.
|
|
529
606
|
assert task_id is not None
|
|
530
607
|
assert object_type == "container_process"
|
|
531
608
|
if stream_type == StreamType.DEVNULL:
|
|
532
609
|
self._impl = _DevnullStreamReader(file_descriptor)
|
|
533
610
|
else:
|
|
534
611
|
assert stream_type == StreamType.PIPE or stream_type == StreamType.STDOUT
|
|
535
|
-
# TODO(saltzm): The original implementation of STDOUT StreamType in
|
|
536
|
-
# _StreamReaderThroughServer prints to stdout immediately. This doesn't match
|
|
537
|
-
# python subprocess.run, which uses None to print to stdout immediately, and uses
|
|
538
|
-
# STDOUT as an argument to stderr to redirect stderr to the stdout stream. We should
|
|
539
|
-
# implement the old behavior here before moving out of beta, but after that
|
|
540
|
-
# we should consider changing the API to match python subprocess.run. I don't expect
|
|
541
|
-
# many customers are using this in any case, so I think it's fine to leave this
|
|
542
|
-
# unimplemented for now.
|
|
543
|
-
if stream_type == StreamType.STDOUT:
|
|
544
|
-
raise NotImplementedError(
|
|
545
|
-
"Currently the STDOUT stream type is not supported when using exec "
|
|
546
|
-
"through a task command router, which is currently in beta."
|
|
547
|
-
)
|
|
548
612
|
params = _StreamReaderThroughCommandRouterParams(
|
|
549
613
|
file_descriptor, task_id, object_id, command_router_client, deadline
|
|
550
614
|
)
|
|
551
615
|
if text:
|
|
552
|
-
|
|
616
|
+
reader = _TextStreamReaderThroughCommandRouter(params, by_line)
|
|
617
|
+
else:
|
|
618
|
+
reader = _BytesStreamReaderThroughCommandRouter(params)
|
|
619
|
+
|
|
620
|
+
if stream_type == StreamType.STDOUT:
|
|
621
|
+
self._impl = _StdoutPrintingStreamReaderThroughCommandRouter(reader)
|
|
553
622
|
else:
|
|
554
|
-
self._impl =
|
|
623
|
+
self._impl = reader
|
|
555
624
|
|
|
556
625
|
@property
|
|
557
626
|
def file_descriptor(self) -> int:
|
|
@@ -560,7 +629,7 @@ class _StreamReader(Generic[T]):
|
|
|
560
629
|
|
|
561
630
|
async def read(self) -> T:
|
|
562
631
|
"""Fetch the entire contents of the stream until EOF."""
|
|
563
|
-
return await self._impl.read()
|
|
632
|
+
return cast(T, await self._impl.read())
|
|
564
633
|
|
|
565
634
|
# TODO(saltzm): I'd prefer to have the implementation classes only implement __aiter__
|
|
566
635
|
# and have them return generator functions directly, but synchronicity doesn't let us
|
|
@@ -572,7 +641,7 @@ class _StreamReader(Generic[T]):
|
|
|
572
641
|
|
|
573
642
|
async def __anext__(self) -> T:
|
|
574
643
|
"""mdmd:hidden"""
|
|
575
|
-
return await self._impl.__anext__()
|
|
644
|
+
return cast(T, await self._impl.__anext__())
|
|
576
645
|
|
|
577
646
|
async def aclose(self):
|
|
578
647
|
"""mdmd:hidden"""
|
|
@@ -127,7 +127,7 @@ def _stdio_stream_from_command_router(
|
|
|
127
127
|
"""Stream raw bytes from the router client."""
|
|
128
128
|
...
|
|
129
129
|
|
|
130
|
-
class _BytesStreamReaderThroughCommandRouter
|
|
130
|
+
class _BytesStreamReaderThroughCommandRouter:
|
|
131
131
|
"""StreamReader implementation that will read directly from the worker that
|
|
132
132
|
hosts the sandbox.
|
|
133
133
|
|
|
@@ -139,12 +139,12 @@ class _BytesStreamReaderThroughCommandRouter(typing.Generic[T]):
|
|
|
139
139
|
|
|
140
140
|
@property
|
|
141
141
|
def file_descriptor(self) -> int: ...
|
|
142
|
-
async def read(self) ->
|
|
143
|
-
def __aiter__(self) -> collections.abc.AsyncIterator[
|
|
144
|
-
async def __anext__(self) ->
|
|
142
|
+
async def read(self) -> bytes: ...
|
|
143
|
+
def __aiter__(self) -> collections.abc.AsyncIterator[bytes]: ...
|
|
144
|
+
async def __anext__(self) -> bytes: ...
|
|
145
145
|
async def aclose(self): ...
|
|
146
146
|
|
|
147
|
-
class _TextStreamReaderThroughCommandRouter
|
|
147
|
+
class _TextStreamReaderThroughCommandRouter:
|
|
148
148
|
"""StreamReader implementation that will read directly from the worker
|
|
149
149
|
that hosts the sandbox.
|
|
150
150
|
|
|
@@ -156,6 +156,29 @@ class _TextStreamReaderThroughCommandRouter(typing.Generic[T]):
|
|
|
156
156
|
|
|
157
157
|
@property
|
|
158
158
|
def file_descriptor(self) -> int: ...
|
|
159
|
+
async def read(self) -> str: ...
|
|
160
|
+
def __aiter__(self) -> collections.abc.AsyncIterator[str]: ...
|
|
161
|
+
async def __anext__(self) -> str: ...
|
|
162
|
+
async def aclose(self): ...
|
|
163
|
+
|
|
164
|
+
class _StdoutPrintingStreamReaderThroughCommandRouter(typing.Generic[T]):
|
|
165
|
+
"""StreamReader implementation for StreamType.STDOUT when using the task command router.
|
|
166
|
+
|
|
167
|
+
This mirrors the behavior from the server-backed implementation: the stream is printed to
|
|
168
|
+
the local stdout immediately and is not readable via StreamReader methods.
|
|
169
|
+
"""
|
|
170
|
+
|
|
171
|
+
_reader: typing.Union[_TextStreamReaderThroughCommandRouter, _BytesStreamReaderThroughCommandRouter]
|
|
172
|
+
|
|
173
|
+
def __init__(
|
|
174
|
+
self, reader: typing.Union[_TextStreamReaderThroughCommandRouter, _BytesStreamReaderThroughCommandRouter]
|
|
175
|
+
) -> None:
|
|
176
|
+
"""Initialize self. See help(type(self)) for accurate signature."""
|
|
177
|
+
...
|
|
178
|
+
|
|
179
|
+
@property
|
|
180
|
+
def file_descriptor(self) -> int: ...
|
|
181
|
+
def _start_printing_task(self) -> None: ...
|
|
159
182
|
async def read(self) -> T: ...
|
|
160
183
|
def __aiter__(self) -> collections.abc.AsyncIterator[T]: ...
|
|
161
184
|
async def __anext__(self) -> T: ...
|
|
@@ -189,6 +212,7 @@ class _StreamReader(typing.Generic[T]):
|
|
|
189
212
|
_DevnullStreamReader,
|
|
190
213
|
_TextStreamReaderThroughCommandRouter,
|
|
191
214
|
_BytesStreamReaderThroughCommandRouter,
|
|
215
|
+
_StdoutPrintingStreamReaderThroughCommandRouter,
|
|
192
216
|
]
|
|
193
217
|
|
|
194
218
|
def __init__(
|
|
@@ -357,6 +381,7 @@ class StreamReader(typing.Generic[T]):
|
|
|
357
381
|
_DevnullStreamReader,
|
|
358
382
|
_TextStreamReaderThroughCommandRouter,
|
|
359
383
|
_BytesStreamReaderThroughCommandRouter,
|
|
384
|
+
_StdoutPrintingStreamReaderThroughCommandRouter,
|
|
360
385
|
]
|
|
361
386
|
|
|
362
387
|
def __init__(
|
|
@@ -928,12 +928,8 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
928
928
|
elif stdout == StreamType.DEVNULL:
|
|
929
929
|
stdout_config = sr_pb2.TaskExecStdoutConfig.TASK_EXEC_STDOUT_CONFIG_DEVNULL
|
|
930
930
|
elif stdout == StreamType.STDOUT:
|
|
931
|
-
#
|
|
932
|
-
|
|
933
|
-
raise NotImplementedError(
|
|
934
|
-
"Currently the STDOUT stream type is not supported when using exec "
|
|
935
|
-
"through a task command router, which is currently in beta."
|
|
936
|
-
)
|
|
931
|
+
# Stream stdout to the client so that it can be printed locally in the reader.
|
|
932
|
+
stdout_config = sr_pb2.TaskExecStdoutConfig.TASK_EXEC_STDOUT_CONFIG_PIPE
|
|
937
933
|
else:
|
|
938
934
|
raise ValueError("Unsupported StreamType for stdout")
|
|
939
935
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|