modal 1.0.6.dev28__tar.gz → 1.0.6.dev30__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.dev28 → modal-1.0.6.dev30}/PKG-INFO +1 -1
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/app.py +2 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/app.pyi +2 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/client.pyi +2 -2
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/container_process.py +28 -8
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/container_process.pyi +21 -3
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/sandbox.py +15 -1
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal.egg-info/PKG-INFO +1 -1
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal_version/__init__.py +1 -1
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/LICENSE +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/README.md +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/__init__.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/__main__.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_clustered_functions.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_clustered_functions.pyi +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_container_entrypoint.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_functions.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_ipython.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_location.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_object.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_output.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_partial_function.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_pty.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_resolver.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_resources.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_runtime/__init__.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_runtime/asgi.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_runtime/container_io_manager.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_runtime/container_io_manager.pyi +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_runtime/execution_context.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_runtime/execution_context.pyi +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_runtime/gpu_memory_snapshot.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_runtime/telemetry.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_runtime/user_code_imports.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_serialization.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_traceback.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_tunnel.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_tunnel.pyi +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_type_manager.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_utils/__init__.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_utils/app_utils.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_utils/async_utils.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_utils/blob_utils.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_utils/bytes_io_segment_payload.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_utils/deprecation.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_utils/docker_utils.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_utils/function_utils.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_utils/git_utils.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_utils/grpc_testing.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_utils/grpc_utils.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_utils/hash_utils.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_utils/http_utils.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_utils/jwt_utils.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_utils/logger.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_utils/mount_utils.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_utils/name_utils.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_utils/package_utils.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_utils/pattern_utils.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_utils/rand_pb_testing.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_utils/shell_utils.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_utils/time_utils.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_vendor/__init__.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_vendor/a2wsgi_wsgi.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_vendor/cloudpickle.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_vendor/tblib.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/_watcher.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/call_graph.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/cli/__init__.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/cli/_download.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/cli/_traceback.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/cli/app.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/cli/cluster.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/cli/config.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/cli/container.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/cli/dict.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/cli/entry_point.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/cli/environment.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/cli/import_refs.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/cli/launch.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/cli/network_file_system.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/cli/profile.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/cli/programs/__init__.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/cli/programs/run_jupyter.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/cli/programs/vscode.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/cli/queues.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/cli/run.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/cli/secret.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/cli/token.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/cli/utils.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/cli/volume.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/client.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/cloud_bucket_mount.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/cloud_bucket_mount.pyi +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/cls.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/cls.pyi +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/config.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/dict.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/dict.pyi +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/environments.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/environments.pyi +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/exception.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/experimental/__init__.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/experimental/ipython.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/file_io.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/file_io.pyi +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/file_pattern_matcher.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/functions.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/functions.pyi +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/gpu.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/image.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/image.pyi +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/io_streams.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/io_streams.pyi +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/mount.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/mount.pyi +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/network_file_system.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/network_file_system.pyi +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/object.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/object.pyi +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/output.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/parallel_map.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/parallel_map.pyi +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/partial_function.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/partial_function.pyi +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/proxy.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/proxy.pyi +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/py.typed +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/queue.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/queue.pyi +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/requirements/2023.12.312.txt +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/requirements/2023.12.txt +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/requirements/2024.04.txt +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/requirements/2024.10.txt +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/requirements/2025.06.txt +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/requirements/PREVIEW.txt +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/requirements/README.md +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/requirements/base-images.json +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/retries.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/runner.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/runner.pyi +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/running_app.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/sandbox.pyi +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/schedule.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/scheduler_placement.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/secret.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/secret.pyi +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/serving.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/serving.pyi +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/snapshot.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/snapshot.pyi +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/stream_type.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/token_flow.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/token_flow.pyi +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/volume.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal/volume.pyi +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal.egg-info/SOURCES.txt +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal.egg-info/dependency_links.txt +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal.egg-info/entry_points.txt +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal.egg-info/requires.txt +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal.egg-info/top_level.txt +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal_docs/__init__.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal_docs/gen_cli_docs.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal_docs/gen_reference_docs.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal_docs/mdmd/__init__.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal_docs/mdmd/mdmd.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal_docs/mdmd/signatures.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal_proto/__init__.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal_proto/api.proto +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal_proto/api_grpc.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal_proto/api_pb2.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal_proto/api_pb2.pyi +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal_proto/api_pb2_grpc.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal_proto/api_pb2_grpc.pyi +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal_proto/modal_api_grpc.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal_proto/modal_options_grpc.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal_proto/options.proto +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal_proto/options_grpc.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal_proto/options_pb2.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal_proto/options_pb2.pyi +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal_proto/options_pb2_grpc.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal_proto/options_pb2_grpc.pyi +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal_proto/py.typed +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/modal_version/__main__.py +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/pyproject.toml +0 -0
- {modal-1.0.6.dev28 → modal-1.0.6.dev30}/setup.cfg +0 -0
|
@@ -863,6 +863,7 @@ class _App:
|
|
|
863
863
|
# Limits the number of inputs a container handles before shutting down.
|
|
864
864
|
# Use `max_inputs = 1` for single-use containers.
|
|
865
865
|
max_inputs: Optional[int] = None,
|
|
866
|
+
i6pn: Optional[bool] = None, # Whether to enable IPv6 container networking within the region.
|
|
866
867
|
include_source: Optional[bool] = None, # When `False`, don't automatically add the App source to the container.
|
|
867
868
|
experimental_options: Optional[dict[str, Any]] = None,
|
|
868
869
|
# Parameters below here are experimental. Use with caution!
|
|
@@ -977,6 +978,7 @@ class _App:
|
|
|
977
978
|
restrict_modal_access=restrict_modal_access,
|
|
978
979
|
max_inputs=max_inputs,
|
|
979
980
|
scheduler_placement=scheduler_placement,
|
|
981
|
+
i6pn_enabled=i6pn or False,
|
|
980
982
|
include_source=include_source if include_source is not None else self._include_source_default,
|
|
981
983
|
experimental_options={k: str(v) for k, v in (experimental_options or {}).items()},
|
|
982
984
|
_experimental_proxy_ip=_experimental_proxy_ip,
|
|
@@ -455,6 +455,7 @@ class _App:
|
|
|
455
455
|
block_network: bool = False,
|
|
456
456
|
restrict_modal_access: bool = False,
|
|
457
457
|
max_inputs: typing.Optional[int] = None,
|
|
458
|
+
i6pn: typing.Optional[bool] = None,
|
|
458
459
|
include_source: typing.Optional[bool] = None,
|
|
459
460
|
experimental_options: typing.Optional[dict[str, typing.Any]] = None,
|
|
460
461
|
_experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
|
|
@@ -1043,6 +1044,7 @@ class App:
|
|
|
1043
1044
|
block_network: bool = False,
|
|
1044
1045
|
restrict_modal_access: bool = False,
|
|
1045
1046
|
max_inputs: typing.Optional[int] = None,
|
|
1047
|
+
i6pn: typing.Optional[bool] = None,
|
|
1046
1048
|
include_source: typing.Optional[bool] = None,
|
|
1047
1049
|
experimental_options: typing.Optional[dict[str, typing.Any]] = None,
|
|
1048
1050
|
_experimental_scheduler_placement: typing.Optional[modal.scheduler_placement.SchedulerPlacement] = None,
|
|
@@ -31,7 +31,7 @@ class _Client:
|
|
|
31
31
|
server_url: str,
|
|
32
32
|
client_type: int,
|
|
33
33
|
credentials: typing.Optional[tuple[str, str]],
|
|
34
|
-
version: str = "1.0.6.
|
|
34
|
+
version: str = "1.0.6.dev30",
|
|
35
35
|
):
|
|
36
36
|
"""mdmd:hidden
|
|
37
37
|
The Modal client object is not intended to be instantiated directly by users.
|
|
@@ -160,7 +160,7 @@ class Client:
|
|
|
160
160
|
server_url: str,
|
|
161
161
|
client_type: int,
|
|
162
162
|
credentials: typing.Optional[tuple[str, str]],
|
|
163
|
-
version: str = "1.0.6.
|
|
163
|
+
version: str = "1.0.6.dev30",
|
|
164
164
|
):
|
|
165
165
|
"""mdmd:hidden
|
|
166
166
|
The Modal client object is not intended to be instantiated directly by users.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Copyright Modal Labs 2024
|
|
2
2
|
import asyncio
|
|
3
3
|
import platform
|
|
4
|
+
import time
|
|
4
5
|
from typing import Generic, Optional, TypeVar
|
|
5
6
|
|
|
6
7
|
from modal_proto import api_pb2
|
|
@@ -21,6 +22,7 @@ class _ContainerProcess(Generic[T]):
|
|
|
21
22
|
_stdout: _StreamReader[T]
|
|
22
23
|
_stderr: _StreamReader[T]
|
|
23
24
|
_stdin: _StreamWriter
|
|
25
|
+
_exec_deadline: Optional[float] = None
|
|
24
26
|
_text: bool
|
|
25
27
|
_by_line: bool
|
|
26
28
|
_returncode: Optional[int] = None
|
|
@@ -31,11 +33,13 @@ class _ContainerProcess(Generic[T]):
|
|
|
31
33
|
client: _Client,
|
|
32
34
|
stdout: StreamType = StreamType.PIPE,
|
|
33
35
|
stderr: StreamType = StreamType.PIPE,
|
|
36
|
+
exec_deadline: Optional[float] = None,
|
|
34
37
|
text: bool = True,
|
|
35
38
|
by_line: bool = False,
|
|
36
39
|
) -> None:
|
|
37
40
|
self._process_id = process_id
|
|
38
41
|
self._client = client
|
|
42
|
+
self._exec_deadline = exec_deadline
|
|
39
43
|
self._text = text
|
|
40
44
|
self._by_line = by_line
|
|
41
45
|
self._stdout = _StreamReader[T](
|
|
@@ -92,6 +96,11 @@ class _ContainerProcess(Generic[T]):
|
|
|
92
96
|
"""
|
|
93
97
|
if self._returncode is not None:
|
|
94
98
|
return self._returncode
|
|
99
|
+
if self._exec_deadline and time.monotonic() >= self._exec_deadline:
|
|
100
|
+
# TODO(matt): In the future, it would be nice to raise a ContainerExecTimeoutError to make it
|
|
101
|
+
# clear to the user that their sandbox terminated due to a timeout
|
|
102
|
+
self._returncode = -1
|
|
103
|
+
return self._returncode
|
|
95
104
|
|
|
96
105
|
req = api_pb2.ContainerExecWaitRequest(exec_id=self._process_id, timeout=0)
|
|
97
106
|
resp: api_pb2.ContainerExecWaitResponse = await retry_transient_errors(self._client.stub.ContainerExecWait, req)
|
|
@@ -102,22 +111,33 @@ class _ContainerProcess(Generic[T]):
|
|
|
102
111
|
|
|
103
112
|
return None
|
|
104
113
|
|
|
105
|
-
async def
|
|
106
|
-
"""Wait for the container process to finish running. Returns the exit code."""
|
|
107
|
-
|
|
108
|
-
if self._returncode is not None:
|
|
109
|
-
return self._returncode
|
|
110
|
-
|
|
114
|
+
async def _wait_for_completion(self) -> int:
|
|
111
115
|
while True:
|
|
112
116
|
req = api_pb2.ContainerExecWaitRequest(exec_id=self._process_id, timeout=10)
|
|
113
117
|
resp: api_pb2.ContainerExecWaitResponse = await retry_transient_errors(
|
|
114
118
|
self._client.stub.ContainerExecWait, req
|
|
115
119
|
)
|
|
116
120
|
if resp.completed:
|
|
117
|
-
|
|
118
|
-
|
|
121
|
+
return resp.exit_code
|
|
122
|
+
|
|
123
|
+
async def wait(self) -> int:
|
|
124
|
+
"""Wait for the container process to finish running. Returns the exit code."""
|
|
125
|
+
if self._returncode is not None:
|
|
126
|
+
return self._returncode
|
|
127
|
+
|
|
128
|
+
try:
|
|
129
|
+
timeout = None
|
|
130
|
+
if self._exec_deadline:
|
|
131
|
+
timeout = self._exec_deadline - time.monotonic()
|
|
132
|
+
if timeout <= 0:
|
|
133
|
+
raise TimeoutError()
|
|
134
|
+
self._returncode = await asyncio.wait_for(self._wait_for_completion(), timeout=timeout)
|
|
135
|
+
except (asyncio.TimeoutError, TimeoutError):
|
|
136
|
+
self._returncode = -1
|
|
137
|
+
return self._returncode
|
|
119
138
|
|
|
120
139
|
async def attach(self):
|
|
140
|
+
"""mdmd:hidden"""
|
|
121
141
|
if platform.system() == "Windows":
|
|
122
142
|
print("interactive exec is not currently supported on Windows.")
|
|
123
143
|
return
|
|
@@ -31,6 +31,7 @@ class _ContainerProcess(typing.Generic[T]):
|
|
|
31
31
|
_stdout: modal.io_streams._StreamReader[T]
|
|
32
32
|
_stderr: modal.io_streams._StreamReader[T]
|
|
33
33
|
_stdin: modal.io_streams._StreamWriter
|
|
34
|
+
_exec_deadline: typing.Optional[float]
|
|
34
35
|
_text: bool
|
|
35
36
|
_by_line: bool
|
|
36
37
|
_returncode: typing.Optional[int]
|
|
@@ -41,6 +42,7 @@ class _ContainerProcess(typing.Generic[T]):
|
|
|
41
42
|
client: modal.client._Client,
|
|
42
43
|
stdout: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
|
43
44
|
stderr: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
|
45
|
+
exec_deadline: typing.Optional[float] = None,
|
|
44
46
|
text: bool = True,
|
|
45
47
|
by_line: bool = False,
|
|
46
48
|
) -> None:
|
|
@@ -75,11 +77,14 @@ class _ContainerProcess(typing.Generic[T]):
|
|
|
75
77
|
"""
|
|
76
78
|
...
|
|
77
79
|
|
|
80
|
+
async def _wait_for_completion(self) -> int: ...
|
|
78
81
|
async def wait(self) -> int:
|
|
79
82
|
"""Wait for the container process to finish running. Returns the exit code."""
|
|
80
83
|
...
|
|
81
84
|
|
|
82
|
-
async def attach(self):
|
|
85
|
+
async def attach(self):
|
|
86
|
+
"""mdmd:hidden"""
|
|
87
|
+
...
|
|
83
88
|
|
|
84
89
|
SUPERSELF = typing.TypeVar("SUPERSELF", covariant=True)
|
|
85
90
|
|
|
@@ -108,6 +113,7 @@ class ContainerProcess(typing.Generic[T]):
|
|
|
108
113
|
_stdout: modal.io_streams.StreamReader[T]
|
|
109
114
|
_stderr: modal.io_streams.StreamReader[T]
|
|
110
115
|
_stdin: modal.io_streams.StreamWriter
|
|
116
|
+
_exec_deadline: typing.Optional[float]
|
|
111
117
|
_text: bool
|
|
112
118
|
_by_line: bool
|
|
113
119
|
_returncode: typing.Optional[int]
|
|
@@ -118,6 +124,7 @@ class ContainerProcess(typing.Generic[T]):
|
|
|
118
124
|
client: modal.client.Client,
|
|
119
125
|
stdout: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
|
120
126
|
stderr: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
|
127
|
+
exec_deadline: typing.Optional[float] = None,
|
|
121
128
|
text: bool = True,
|
|
122
129
|
by_line: bool = False,
|
|
123
130
|
) -> None: ...
|
|
@@ -157,6 +164,12 @@ class ContainerProcess(typing.Generic[T]):
|
|
|
157
164
|
|
|
158
165
|
poll: __poll_spec[typing_extensions.Self]
|
|
159
166
|
|
|
167
|
+
class ___wait_for_completion_spec(typing_extensions.Protocol[SUPERSELF]):
|
|
168
|
+
def __call__(self, /) -> int: ...
|
|
169
|
+
async def aio(self, /) -> int: ...
|
|
170
|
+
|
|
171
|
+
_wait_for_completion: ___wait_for_completion_spec[typing_extensions.Self]
|
|
172
|
+
|
|
160
173
|
class __wait_spec(typing_extensions.Protocol[SUPERSELF]):
|
|
161
174
|
def __call__(self, /) -> int:
|
|
162
175
|
"""Wait for the container process to finish running. Returns the exit code."""
|
|
@@ -169,7 +182,12 @@ class ContainerProcess(typing.Generic[T]):
|
|
|
169
182
|
wait: __wait_spec[typing_extensions.Self]
|
|
170
183
|
|
|
171
184
|
class __attach_spec(typing_extensions.Protocol[SUPERSELF]):
|
|
172
|
-
def __call__(self, /):
|
|
173
|
-
|
|
185
|
+
def __call__(self, /):
|
|
186
|
+
"""mdmd:hidden"""
|
|
187
|
+
...
|
|
188
|
+
|
|
189
|
+
async def aio(self, /):
|
|
190
|
+
"""mdmd:hidden"""
|
|
191
|
+
...
|
|
174
192
|
|
|
175
193
|
attach: __attach_spec[typing_extensions.Self]
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Copyright Modal Labs 2022
|
|
2
2
|
import asyncio
|
|
3
3
|
import os
|
|
4
|
+
import time
|
|
4
5
|
from collections.abc import AsyncGenerator, Sequence
|
|
5
6
|
from typing import TYPE_CHECKING, AsyncIterator, Literal, Optional, Union, overload
|
|
6
7
|
|
|
@@ -49,6 +50,10 @@ _default_image: _Image = _Image.debian_slim()
|
|
|
49
50
|
# e.g. 'runsc exec ...'. So we use 2**16 as the limit.
|
|
50
51
|
ARG_MAX_BYTES = 2**16
|
|
51
52
|
|
|
53
|
+
|
|
54
|
+
# This buffer extends the user-supplied timeout on ContainerExec-related RPCs. This was introduced to
|
|
55
|
+
# give any in-flight status codes/IO data more time to reach the client before the stream is closed.
|
|
56
|
+
CONTAINER_EXEC_TIMEOUT_BUFFER = 5
|
|
52
57
|
if TYPE_CHECKING:
|
|
53
58
|
import modal.app
|
|
54
59
|
|
|
@@ -665,7 +670,16 @@ class _Sandbox(_Object, type_prefix="sb"):
|
|
|
665
670
|
)
|
|
666
671
|
resp = await retry_transient_errors(self._client.stub.ContainerExec, req)
|
|
667
672
|
by_line = bufsize == 1
|
|
668
|
-
|
|
673
|
+
exec_deadline = time.monotonic() + int(timeout) + CONTAINER_EXEC_TIMEOUT_BUFFER if timeout else None
|
|
674
|
+
return _ContainerProcess(
|
|
675
|
+
resp.exec_id,
|
|
676
|
+
self._client,
|
|
677
|
+
stdout=stdout,
|
|
678
|
+
stderr=stderr,
|
|
679
|
+
text=text,
|
|
680
|
+
exec_deadline=exec_deadline,
|
|
681
|
+
by_line=by_line,
|
|
682
|
+
)
|
|
669
683
|
|
|
670
684
|
async def _experimental_snapshot(self) -> _SandboxSnapshot:
|
|
671
685
|
await self._get_task_id()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|