modal 1.0.6.dev46__tar.gz → 1.0.6.dev47__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of modal might be problematic. Click here for more details.
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/PKG-INFO +1 -1
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/client.pyi +2 -2
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/container_process.py +2 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/io_streams.py +19 -3
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/io_streams.pyi +7 -1
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/sandbox.py +2 -1
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal.egg-info/PKG-INFO +1 -1
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal_version/__init__.py +1 -1
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/LICENSE +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/README.md +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/__init__.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/__main__.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_clustered_functions.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_clustered_functions.pyi +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_container_entrypoint.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_functions.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_ipython.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_location.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_object.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_output.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_partial_function.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_pty.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_resolver.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_resources.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_runtime/__init__.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_runtime/asgi.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_runtime/container_io_manager.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_runtime/container_io_manager.pyi +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_runtime/execution_context.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_runtime/execution_context.pyi +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_runtime/gpu_memory_snapshot.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_runtime/telemetry.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_runtime/user_code_imports.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_serialization.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_traceback.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_tunnel.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_tunnel.pyi +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_type_manager.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_utils/__init__.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_utils/app_utils.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_utils/async_utils.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_utils/auth_token_manager.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_utils/blob_utils.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_utils/bytes_io_segment_payload.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_utils/deprecation.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_utils/docker_utils.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_utils/function_utils.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_utils/git_utils.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_utils/grpc_testing.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_utils/grpc_utils.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_utils/hash_utils.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_utils/http_utils.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_utils/jwt_utils.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_utils/logger.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_utils/mount_utils.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_utils/name_utils.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_utils/package_utils.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_utils/pattern_utils.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_utils/rand_pb_testing.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_utils/shell_utils.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_utils/time_utils.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_vendor/__init__.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_vendor/a2wsgi_wsgi.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_vendor/cloudpickle.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_vendor/tblib.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/_watcher.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/app.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/app.pyi +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/call_graph.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/cli/__init__.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/cli/_download.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/cli/_traceback.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/cli/app.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/cli/cluster.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/cli/config.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/cli/container.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/cli/dict.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/cli/entry_point.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/cli/environment.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/cli/import_refs.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/cli/launch.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/cli/network_file_system.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/cli/profile.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/cli/programs/__init__.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/cli/programs/run_jupyter.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/cli/programs/vscode.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/cli/queues.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/cli/run.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/cli/secret.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/cli/token.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/cli/utils.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/cli/volume.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/client.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/cloud_bucket_mount.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/cloud_bucket_mount.pyi +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/cls.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/cls.pyi +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/config.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/container_process.pyi +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/dict.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/dict.pyi +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/environments.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/environments.pyi +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/exception.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/experimental/__init__.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/experimental/flash.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/experimental/flash.pyi +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/experimental/ipython.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/file_io.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/file_io.pyi +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/file_pattern_matcher.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/functions.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/functions.pyi +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/gpu.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/image.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/image.pyi +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/mount.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/mount.pyi +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/network_file_system.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/network_file_system.pyi +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/object.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/object.pyi +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/output.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/parallel_map.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/parallel_map.pyi +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/partial_function.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/partial_function.pyi +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/proxy.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/proxy.pyi +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/py.typed +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/queue.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/queue.pyi +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/requirements/2023.12.312.txt +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/requirements/2023.12.txt +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/requirements/2024.04.txt +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/requirements/2024.10.txt +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/requirements/2025.06.txt +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/requirements/PREVIEW.txt +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/requirements/README.md +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/requirements/base-images.json +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/retries.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/runner.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/runner.pyi +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/running_app.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/sandbox.pyi +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/schedule.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/scheduler_placement.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/secret.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/secret.pyi +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/serving.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/serving.pyi +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/snapshot.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/snapshot.pyi +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/stream_type.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/token_flow.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/token_flow.pyi +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/volume.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal/volume.pyi +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal.egg-info/SOURCES.txt +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal.egg-info/dependency_links.txt +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal.egg-info/entry_points.txt +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal.egg-info/requires.txt +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal.egg-info/top_level.txt +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal_docs/__init__.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal_docs/gen_cli_docs.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal_docs/gen_reference_docs.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal_docs/mdmd/__init__.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal_docs/mdmd/mdmd.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal_docs/mdmd/signatures.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal_proto/__init__.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal_proto/api.proto +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal_proto/api_grpc.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal_proto/api_pb2.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal_proto/api_pb2.pyi +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal_proto/api_pb2_grpc.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal_proto/api_pb2_grpc.pyi +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal_proto/modal_api_grpc.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal_proto/modal_options_grpc.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal_proto/options.proto +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal_proto/options_grpc.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal_proto/options_pb2.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal_proto/options_pb2.pyi +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal_proto/options_pb2_grpc.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal_proto/options_pb2_grpc.pyi +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal_proto/py.typed +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/modal_version/__main__.py +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/pyproject.toml +0 -0
- {modal-1.0.6.dev46 → modal-1.0.6.dev47}/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.0.6.
|
|
36
|
+
version: str = "1.0.6.dev47",
|
|
37
37
|
):
|
|
38
38
|
"""mdmd:hidden
|
|
39
39
|
The Modal client object is not intended to be instantiated directly by users.
|
|
@@ -163,7 +163,7 @@ class Client:
|
|
|
163
163
|
server_url: str,
|
|
164
164
|
client_type: int,
|
|
165
165
|
credentials: typing.Optional[tuple[str, str]],
|
|
166
|
-
version: str = "1.0.6.
|
|
166
|
+
version: str = "1.0.6.dev47",
|
|
167
167
|
):
|
|
168
168
|
"""mdmd:hidden
|
|
169
169
|
The Modal client object is not intended to be instantiated directly by users.
|
|
@@ -50,6 +50,7 @@ class _ContainerProcess(Generic[T]):
|
|
|
50
50
|
stream_type=stdout,
|
|
51
51
|
text=text,
|
|
52
52
|
by_line=by_line,
|
|
53
|
+
deadline=exec_deadline,
|
|
53
54
|
)
|
|
54
55
|
self._stderr = _StreamReader[T](
|
|
55
56
|
api_pb2.FILE_DESCRIPTOR_STDERR,
|
|
@@ -59,6 +60,7 @@ class _ContainerProcess(Generic[T]):
|
|
|
59
60
|
stream_type=stderr,
|
|
60
61
|
text=text,
|
|
61
62
|
by_line=by_line,
|
|
63
|
+
deadline=exec_deadline,
|
|
62
64
|
)
|
|
63
65
|
self._stdin = _StreamWriter(process_id, "container_process", self._client)
|
|
64
66
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# Copyright Modal Labs 2022
|
|
2
2
|
import asyncio
|
|
3
|
+
import time
|
|
3
4
|
from collections.abc import AsyncGenerator, AsyncIterator
|
|
4
5
|
from typing import (
|
|
5
6
|
TYPE_CHECKING,
|
|
@@ -50,6 +51,7 @@ async def _container_process_logs_iterator(
|
|
|
50
51
|
file_descriptor: "api_pb2.FileDescriptor.ValueType",
|
|
51
52
|
client: _Client,
|
|
52
53
|
last_index: int,
|
|
54
|
+
deadline: Optional[float] = None,
|
|
53
55
|
) -> AsyncGenerator[tuple[Optional[bytes], int], None]:
|
|
54
56
|
req = api_pb2.ContainerExecGetOutputRequest(
|
|
55
57
|
exec_id=process_id,
|
|
@@ -58,7 +60,18 @@ async def _container_process_logs_iterator(
|
|
|
58
60
|
get_raw_bytes=True,
|
|
59
61
|
last_batch_index=last_index,
|
|
60
62
|
)
|
|
61
|
-
|
|
63
|
+
|
|
64
|
+
stream = client.stub.ContainerExecGetOutput.unary_stream(req)
|
|
65
|
+
while True:
|
|
66
|
+
# Check deadline before attempting to receive the next batch
|
|
67
|
+
try:
|
|
68
|
+
remaining = (deadline - time.monotonic()) if deadline else None
|
|
69
|
+
batch = await asyncio.wait_for(stream.__anext__(), timeout=remaining)
|
|
70
|
+
except asyncio.TimeoutError:
|
|
71
|
+
yield None, -1
|
|
72
|
+
break
|
|
73
|
+
except StopAsyncIteration:
|
|
74
|
+
break
|
|
62
75
|
if batch.HasField("exit_code"):
|
|
63
76
|
yield None, batch.batch_index
|
|
64
77
|
break
|
|
@@ -102,6 +115,7 @@ class _StreamReader(Generic[T]):
|
|
|
102
115
|
stream_type: StreamType = StreamType.PIPE,
|
|
103
116
|
text: bool = True,
|
|
104
117
|
by_line: bool = False,
|
|
118
|
+
deadline: Optional[float] = None,
|
|
105
119
|
) -> None:
|
|
106
120
|
"""mdmd:hidden"""
|
|
107
121
|
self._file_descriptor = file_descriptor
|
|
@@ -111,6 +125,7 @@ class _StreamReader(Generic[T]):
|
|
|
111
125
|
self._stream = None
|
|
112
126
|
self._last_entry_id: str = ""
|
|
113
127
|
self._line_buffer = b""
|
|
128
|
+
self._deadline = deadline
|
|
114
129
|
|
|
115
130
|
# Sandbox logs are streamed to the client as strings, so StreamReaders reading
|
|
116
131
|
# them must have text mode enabled.
|
|
@@ -187,11 +202,12 @@ class _StreamReader(Generic[T]):
|
|
|
187
202
|
retries_remaining = 10
|
|
188
203
|
last_index = 0
|
|
189
204
|
while not completed:
|
|
205
|
+
if self._deadline and time.monotonic() >= self._deadline:
|
|
206
|
+
break
|
|
190
207
|
try:
|
|
191
208
|
iterator = _container_process_logs_iterator(
|
|
192
|
-
self._object_id, self._file_descriptor, self._client, last_index
|
|
209
|
+
self._object_id, self._file_descriptor, self._client, last_index, self._deadline
|
|
193
210
|
)
|
|
194
|
-
|
|
195
211
|
async for message, batch_index in iterator:
|
|
196
212
|
if self._stream_type == StreamType.STDOUT and message:
|
|
197
213
|
print(message.decode("utf-8"), end="")
|
|
@@ -8,7 +8,11 @@ def _sandbox_logs_iterator(
|
|
|
8
8
|
sandbox_id: str, file_descriptor: int, last_entry_id: str, client: modal.client._Client
|
|
9
9
|
) -> collections.abc.AsyncGenerator[tuple[typing.Optional[bytes], str], None]: ...
|
|
10
10
|
def _container_process_logs_iterator(
|
|
11
|
-
process_id: str,
|
|
11
|
+
process_id: str,
|
|
12
|
+
file_descriptor: int,
|
|
13
|
+
client: modal.client._Client,
|
|
14
|
+
last_index: int,
|
|
15
|
+
deadline: typing.Optional[float] = None,
|
|
12
16
|
) -> collections.abc.AsyncGenerator[tuple[typing.Optional[bytes], int], None]: ...
|
|
13
17
|
|
|
14
18
|
T = typing.TypeVar("T")
|
|
@@ -46,6 +50,7 @@ class _StreamReader(typing.Generic[T]):
|
|
|
46
50
|
stream_type: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
|
47
51
|
text: bool = True,
|
|
48
52
|
by_line: bool = False,
|
|
53
|
+
deadline: typing.Optional[float] = None,
|
|
49
54
|
) -> None:
|
|
50
55
|
"""mdmd:hidden"""
|
|
51
56
|
...
|
|
@@ -211,6 +216,7 @@ class StreamReader(typing.Generic[T]):
|
|
|
211
216
|
stream_type: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
|
212
217
|
text: bool = True,
|
|
213
218
|
by_line: bool = False,
|
|
219
|
+
deadline: typing.Optional[float] = None,
|
|
214
220
|
) -> None:
|
|
215
221
|
"""mdmd:hidden"""
|
|
216
222
|
...
|
|
@@ -50,10 +50,11 @@ _default_image: _Image = _Image.debian_slim()
|
|
|
50
50
|
# e.g. 'runsc exec ...'. So we use 2**16 as the limit.
|
|
51
51
|
ARG_MAX_BYTES = 2**16
|
|
52
52
|
|
|
53
|
-
|
|
54
53
|
# This buffer extends the user-supplied timeout on ContainerExec-related RPCs. This was introduced to
|
|
55
54
|
# give any in-flight status codes/IO data more time to reach the client before the stream is closed.
|
|
56
55
|
CONTAINER_EXEC_TIMEOUT_BUFFER = 5
|
|
56
|
+
|
|
57
|
+
|
|
57
58
|
if TYPE_CHECKING:
|
|
58
59
|
import modal.app
|
|
59
60
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|