modal 1.4.3.dev18__tar.gz → 1.4.3.dev19__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.dev18 → modal-1.4.3.dev19}/PKG-INFO +1 -1
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_utils/task_command_router_client.py +5 -14
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/app.py +0 -2
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/cli/cluster.py +1 -4
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/cli/container.py +1 -3
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/client.pyi +2 -2
- modal-1.4.3.dev19/modal/container_process.py +224 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/container_process.pyi +11 -120
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/functions.pyi +6 -6
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/io_streams.py +69 -199
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/io_streams.pyi +125 -64
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/sandbox.py +41 -88
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/sandbox.pyi +9 -76
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal.egg-info/PKG-INFO +1 -1
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal_proto/api_pb2.pyi +1 -1
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal_version/__init__.py +1 -1
- modal-1.4.3.dev18/modal/container_process.py +0 -470
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/LICENSE +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/README.md +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/__init__.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/__main__.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_billing.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_clustered_functions.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_clustered_functions.pyi +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_container_entrypoint.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_environments.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_functions.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_grpc_client.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_ipython.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_load_context.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_location.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_logs.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_object.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_output/__init__.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_output/manager.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_output/pty.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_output/rich.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_output/status.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_partial_function.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_resolver.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_resources.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_runtime/__init__.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_runtime/asgi.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_runtime/container_io_manager.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_runtime/container_io_manager.pyi +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_runtime/execution_context.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_runtime/execution_context.pyi +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_runtime/gpu_memory_snapshot.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_runtime/telemetry.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_runtime/user_code_event_loop.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_runtime/user_code_imports.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_serialization.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_server.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_traceback.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_tunnel.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_tunnel.pyi +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_type_manager.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_utils/__init__.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_utils/app_utils.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_utils/async_utils.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_utils/auth_token_manager.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_utils/blob_utils.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_utils/browser_utils.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_utils/bytes_io_segment_payload.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_utils/deprecation.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_utils/docker_utils.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_utils/function_utils.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_utils/git_utils.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_utils/grpc_testing.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_utils/grpc_utils.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_utils/hash_utils.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_utils/http_utils.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_utils/jwt_utils.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_utils/logger.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_utils/mount_utils.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_utils/name_utils.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_utils/package_utils.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_utils/pattern_utils.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_utils/rand_pb_testing.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_utils/sandbox_fs_utils.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_utils/shell_utils.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_utils/time_utils.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_vendor/__init__.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_vendor/a2wsgi_wsgi.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_vendor/cloudpickle.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_vendor/tblib.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_vendor/version.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/_watcher.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/app.pyi +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/billing.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/builder/2023.12.312.txt +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/builder/2023.12.txt +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/builder/2024.04.txt +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/builder/2024.10.txt +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/builder/2025.06.txt +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/builder/PREVIEW.txt +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/builder/README.md +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/builder/base-images.json +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/call_graph.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/cli/__init__.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/cli/_download.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/cli/_help.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/cli/_traceback.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/cli/app.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/cli/billing.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/cli/bootstrap.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/cli/changelog.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/cli/config.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/cli/dashboard.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/cli/dict.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/cli/entry_point.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/cli/environment.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/cli/import_refs.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/cli/launch.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/cli/logo.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/cli/network_file_system.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/cli/profile.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/cli/programs/__init__.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/cli/programs/run_jupyter.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/cli/programs/vscode.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/cli/queues.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/cli/run.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/cli/secret.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/cli/selector.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/cli/shell.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/cli/token.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/cli/utils.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/cli/volume.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/client.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/cloud_bucket_mount.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/cloud_bucket_mount.pyi +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/cls.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/cls.pyi +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/config.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/dict.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/dict.pyi +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/environments.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/environments.pyi +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/exception.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/experimental/__init__.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/experimental/flash.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/experimental/flash.pyi +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/experimental/ipython.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/file_io.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/file_io.pyi +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/file_pattern_matcher.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/functions.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/image.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/image.pyi +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/mount.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/mount.pyi +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/network_file_system.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/network_file_system.pyi +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/object.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/object.pyi +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/output.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/parallel_map.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/parallel_map.pyi +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/partial_function.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/partial_function.pyi +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/proxy.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/proxy.pyi +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/py.typed +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/queue.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/queue.pyi +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/retries.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/runner.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/runner.pyi +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/running_app.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/sandbox_fs.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/sandbox_fs.pyi +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/schedule.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/scheduler_placement.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/secret.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/secret.pyi +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/server.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/server.pyi +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/serving.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/serving.pyi +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/snapshot.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/snapshot.pyi +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/stream_type.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/token_flow.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/token_flow.pyi +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/volume.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal/volume.pyi +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal.egg-info/SOURCES.txt +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal.egg-info/dependency_links.txt +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal.egg-info/entry_points.txt +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal.egg-info/requires.txt +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal.egg-info/top_level.txt +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal_docs/__init__.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal_docs/gen_cli_docs.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal_docs/gen_cli_docs_main.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal_docs/gen_reference_docs.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal_docs/gen_reference_docs_main.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal_docs/mdmd/__init__.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal_docs/mdmd/mdmd.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal_docs/mdmd/signatures.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal_proto/__init__.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal_proto/api_grpc.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal_proto/api_pb2.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal_proto/api_pb2_grpc.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal_proto/api_pb2_grpc.pyi +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal_proto/modal_api_grpc.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal_proto/py.typed +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal_proto/task_command_router_grpc.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal_proto/task_command_router_pb2.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal_proto/task_command_router_pb2.pyi +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal_proto/task_command_router_pb2_grpc.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal_proto/task_command_router_pb2_grpc.pyi +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/modal_version/__main__.py +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/pyproject.toml +0 -0
- {modal-1.4.3.dev18 → modal-1.4.3.dev19}/setup.cfg +0 -0
|
@@ -16,7 +16,7 @@ from grpclib import GRPCError, Status
|
|
|
16
16
|
from grpclib.exceptions import StreamTerminatedError
|
|
17
17
|
|
|
18
18
|
from modal.config import logger
|
|
19
|
-
from modal.exception import
|
|
19
|
+
from modal.exception import ExecTimeoutError
|
|
20
20
|
from modal_proto import api_pb2, task_command_router_pb2 as sr_pb2
|
|
21
21
|
from modal_proto.task_command_router_grpc import TaskCommandRouterStub
|
|
22
22
|
|
|
@@ -196,21 +196,12 @@ class TaskCommandRouterClient:
|
|
|
196
196
|
return cls(server_client, task_id, url, jwt, channel, loop, jwt_refresh_lock, sandbox_id=sandbox_id)
|
|
197
197
|
|
|
198
198
|
@classmethod
|
|
199
|
-
async def
|
|
199
|
+
async def init(
|
|
200
200
|
cls,
|
|
201
201
|
server_client,
|
|
202
202
|
task_id: str,
|
|
203
|
-
) ->
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
Returns None if command router access is not enabled (FAILED_PRECONDITION).
|
|
207
|
-
"""
|
|
208
|
-
try:
|
|
209
|
-
resp = await fetch_command_router_access(server_client, task_id)
|
|
210
|
-
except ConflictError:
|
|
211
|
-
logger.debug(f"Command router access is not enabled for task {task_id}")
|
|
212
|
-
return None
|
|
213
|
-
|
|
203
|
+
) -> "TaskCommandRouterClient":
|
|
204
|
+
resp = await fetch_command_router_access(server_client, task_id)
|
|
214
205
|
logger.debug(f"Using command router access for task {task_id}")
|
|
215
206
|
return await cls._connect(server_client, task_id, resp.url, resp.jwt)
|
|
216
207
|
|
|
@@ -241,7 +232,7 @@ class TaskCommandRouterClient:
|
|
|
241
232
|
stream_stdio_retry_delay_factor: float = 2,
|
|
242
233
|
stream_stdio_max_retries: int = 10,
|
|
243
234
|
) -> None:
|
|
244
|
-
"""Callers should not use this directly. Use TaskCommandRouterClient.
|
|
235
|
+
"""Callers should not use this directly. Use TaskCommandRouterClient.init() instead."""
|
|
245
236
|
# Record the loop this instance is bound to so __del__ can safely schedule cleanup
|
|
246
237
|
# even if finalization happens from a different thread (e.g. via synchronicity).
|
|
247
238
|
self._loop = loop
|
|
@@ -778,7 +778,6 @@ class _App:
|
|
|
778
778
|
deprecation_warning(
|
|
779
779
|
(2025, 12, 16),
|
|
780
780
|
"The `max_inputs` parameter is deprecated. Please set `single_use_containers=True` instead.",
|
|
781
|
-
pending=True,
|
|
782
781
|
)
|
|
783
782
|
single_use_containers = max_inputs == 1
|
|
784
783
|
|
|
@@ -987,7 +986,6 @@ class _App:
|
|
|
987
986
|
deprecation_warning(
|
|
988
987
|
(2025, 12, 16),
|
|
989
988
|
"The `max_inputs` parameter is deprecated. Please set `single_use_containers=True` instead.",
|
|
990
|
-
pending=True,
|
|
991
989
|
)
|
|
992
990
|
single_use_containers = max_inputs == 1
|
|
993
991
|
|
|
@@ -16,7 +16,6 @@ from modal.cli.utils import display_table, env_option, is_tty
|
|
|
16
16
|
from modal.client import _Client
|
|
17
17
|
from modal.config import config
|
|
18
18
|
from modal.container_process import _ContainerProcess
|
|
19
|
-
from modal.exception import InvalidError
|
|
20
19
|
from modal.output import OutputManager
|
|
21
20
|
from modal.stream_type import StreamType
|
|
22
21
|
from modal_proto import api_pb2, task_command_router_pb2 as sr_pb2
|
|
@@ -79,9 +78,7 @@ async def shell(cluster_id: str, rank: int = 0):
|
|
|
79
78
|
|
|
80
79
|
pty = is_tty()
|
|
81
80
|
|
|
82
|
-
command_router_client = await TaskCommandRouterClient.
|
|
83
|
-
if command_router_client is None:
|
|
84
|
-
raise InvalidError(f"Command router access is not available for container {task_id}")
|
|
81
|
+
command_router_client = await TaskCommandRouterClient.init(client, task_id)
|
|
85
82
|
|
|
86
83
|
process_id = str(uuid.uuid4())
|
|
87
84
|
|
|
@@ -278,9 +278,7 @@ async def _exec_impl(
|
|
|
278
278
|
|
|
279
279
|
client = await _Client.from_env()
|
|
280
280
|
|
|
281
|
-
command_router_client = await TaskCommandRouterClient.
|
|
282
|
-
if command_router_client is None:
|
|
283
|
-
raise InvalidError(f"Command router access is not available for container {container_id}")
|
|
281
|
+
command_router_client = await TaskCommandRouterClient.init(client, container_id)
|
|
284
282
|
|
|
285
283
|
process_id = str(uuid.uuid4())
|
|
286
284
|
|
|
@@ -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.dev19",
|
|
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.dev19",
|
|
179
179
|
):
|
|
180
180
|
"""mdmd:hidden
|
|
181
181
|
The Modal client object is not intended to be instantiated directly by users.
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
# Copyright Modal Labs 2024
|
|
2
|
+
import asyncio
|
|
3
|
+
import platform
|
|
4
|
+
from typing import Generic, Optional, TypeVar
|
|
5
|
+
|
|
6
|
+
from modal_proto import api_pb2
|
|
7
|
+
|
|
8
|
+
from ._utils.async_utils import TaskContext, synchronize_api
|
|
9
|
+
from ._utils.shell_utils import stream_from_stdin, write_to_fd
|
|
10
|
+
from ._utils.task_command_router_client import TaskCommandRouterClient
|
|
11
|
+
from .client import _Client
|
|
12
|
+
from .config import logger
|
|
13
|
+
from .exception import ExecTimeoutError, InteractiveTimeoutError, InvalidError
|
|
14
|
+
from .io_streams import (
|
|
15
|
+
_StreamReader,
|
|
16
|
+
_StreamReaderThroughCommandRouterParams,
|
|
17
|
+
_StreamWriter,
|
|
18
|
+
_StreamWriterThroughCommandRouterParams,
|
|
19
|
+
)
|
|
20
|
+
from .stream_type import StreamType
|
|
21
|
+
|
|
22
|
+
T = TypeVar("T", str, bytes)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
async def _iter_stream_as_bytes(stream: _StreamReader[T]):
|
|
26
|
+
"""Yield raw bytes from a StreamReader regardless of text mode/backend."""
|
|
27
|
+
async for part in stream:
|
|
28
|
+
if isinstance(part, str):
|
|
29
|
+
yield part.encode("utf-8")
|
|
30
|
+
else:
|
|
31
|
+
yield part
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class _ContainerProcess(Generic[T]):
|
|
35
|
+
"""Represents a running process in a container.
|
|
36
|
+
|
|
37
|
+
Container processes communicate via direct communication with
|
|
38
|
+
the Modal worker where the container is running.
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
def __init__(
|
|
42
|
+
self,
|
|
43
|
+
process_id: str,
|
|
44
|
+
task_id: str,
|
|
45
|
+
client: _Client,
|
|
46
|
+
command_router_client: TaskCommandRouterClient,
|
|
47
|
+
stdout: StreamType = StreamType.PIPE,
|
|
48
|
+
stderr: StreamType = StreamType.PIPE,
|
|
49
|
+
exec_deadline: Optional[float] = None,
|
|
50
|
+
text: bool = True,
|
|
51
|
+
by_line: bool = False,
|
|
52
|
+
) -> None:
|
|
53
|
+
self._client = client
|
|
54
|
+
self._command_router_client = command_router_client
|
|
55
|
+
self._process_id = process_id
|
|
56
|
+
self._exec_deadline = exec_deadline
|
|
57
|
+
self._text = text
|
|
58
|
+
self._by_line = by_line
|
|
59
|
+
self._task_id = task_id
|
|
60
|
+
self._stdout = _StreamReader[T](
|
|
61
|
+
_StreamReaderThroughCommandRouterParams(
|
|
62
|
+
file_descriptor=api_pb2.FILE_DESCRIPTOR_STDOUT,
|
|
63
|
+
task_id=self._task_id,
|
|
64
|
+
object_id=process_id,
|
|
65
|
+
command_router_client=self._command_router_client,
|
|
66
|
+
deadline=exec_deadline,
|
|
67
|
+
),
|
|
68
|
+
stream_type=stdout,
|
|
69
|
+
text=text,
|
|
70
|
+
by_line=by_line,
|
|
71
|
+
)
|
|
72
|
+
self._stderr = _StreamReader[T](
|
|
73
|
+
_StreamReaderThroughCommandRouterParams(
|
|
74
|
+
file_descriptor=api_pb2.FILE_DESCRIPTOR_STDERR,
|
|
75
|
+
task_id=self._task_id,
|
|
76
|
+
object_id=process_id,
|
|
77
|
+
command_router_client=self._command_router_client,
|
|
78
|
+
deadline=exec_deadline,
|
|
79
|
+
),
|
|
80
|
+
stream_type=stderr,
|
|
81
|
+
text=text,
|
|
82
|
+
by_line=by_line,
|
|
83
|
+
)
|
|
84
|
+
self._stdin = _StreamWriter(
|
|
85
|
+
_StreamWriterThroughCommandRouterParams(
|
|
86
|
+
task_id=self._task_id,
|
|
87
|
+
object_id=process_id,
|
|
88
|
+
command_router_client=self._command_router_client,
|
|
89
|
+
)
|
|
90
|
+
)
|
|
91
|
+
self._returncode = None
|
|
92
|
+
|
|
93
|
+
def __repr__(self) -> str:
|
|
94
|
+
return f"ContainerProcess(process_id={self._process_id!r})"
|
|
95
|
+
|
|
96
|
+
@property
|
|
97
|
+
def stdout(self) -> _StreamReader[T]:
|
|
98
|
+
"""StreamReader for the container process's stdout stream."""
|
|
99
|
+
return self._stdout
|
|
100
|
+
|
|
101
|
+
@property
|
|
102
|
+
def stderr(self) -> _StreamReader[T]:
|
|
103
|
+
"""StreamReader for the container process's stderr stream."""
|
|
104
|
+
return self._stderr
|
|
105
|
+
|
|
106
|
+
@property
|
|
107
|
+
def stdin(self) -> _StreamWriter:
|
|
108
|
+
"""StreamWriter for the container process's stdin stream."""
|
|
109
|
+
return self._stdin
|
|
110
|
+
|
|
111
|
+
@property
|
|
112
|
+
def returncode(self) -> int:
|
|
113
|
+
if self._returncode is None:
|
|
114
|
+
raise InvalidError(
|
|
115
|
+
"You must call wait() before accessing the returncode. "
|
|
116
|
+
"To poll for the status of a running process, use poll() instead."
|
|
117
|
+
)
|
|
118
|
+
return self._returncode
|
|
119
|
+
|
|
120
|
+
async def poll(self) -> Optional[int]:
|
|
121
|
+
"""Check if the container process has finished running.
|
|
122
|
+
|
|
123
|
+
Returns `None` if the process is still running, else returns the exit code.
|
|
124
|
+
"""
|
|
125
|
+
if self._returncode is not None:
|
|
126
|
+
return self._returncode
|
|
127
|
+
try:
|
|
128
|
+
resp = await self._command_router_client.exec_poll(self._task_id, self._process_id, self._exec_deadline)
|
|
129
|
+
which = resp.WhichOneof("exit_status")
|
|
130
|
+
if which is None:
|
|
131
|
+
return None
|
|
132
|
+
|
|
133
|
+
if which == "code":
|
|
134
|
+
self._returncode = int(resp.code)
|
|
135
|
+
return self._returncode
|
|
136
|
+
elif which == "signal":
|
|
137
|
+
self._returncode = 128 + int(resp.signal)
|
|
138
|
+
return self._returncode
|
|
139
|
+
else:
|
|
140
|
+
logger.debug(f"ContainerProcess {self._process_id} exited with unexpected status: {which}")
|
|
141
|
+
raise InvalidError("Unexpected exit status")
|
|
142
|
+
except ExecTimeoutError:
|
|
143
|
+
logger.debug(f"ContainerProcess poll for {self._process_id} did not complete within deadline")
|
|
144
|
+
# TODO(saltzm): This is a weird API, but customers currently may rely on it. This
|
|
145
|
+
# should probably raise an ExecTimeoutError instead.
|
|
146
|
+
self._returncode = -1
|
|
147
|
+
return self._returncode
|
|
148
|
+
except Exception as e:
|
|
149
|
+
# Re-raise non-transient errors or errors resulting from exceeding retries on transient errors.
|
|
150
|
+
logger.warning(f"ContainerProcess poll for {self._process_id} failed: {e}")
|
|
151
|
+
raise
|
|
152
|
+
|
|
153
|
+
async def wait(self) -> int:
|
|
154
|
+
"""Wait for the container process to finish running. Returns the exit code."""
|
|
155
|
+
if self._returncode is not None:
|
|
156
|
+
return self._returncode
|
|
157
|
+
|
|
158
|
+
try:
|
|
159
|
+
resp = await self._command_router_client.exec_wait(self._task_id, self._process_id, self._exec_deadline)
|
|
160
|
+
which = resp.WhichOneof("exit_status")
|
|
161
|
+
if which == "code":
|
|
162
|
+
self._returncode = int(resp.code)
|
|
163
|
+
elif which == "signal":
|
|
164
|
+
self._returncode = 128 + int(resp.signal)
|
|
165
|
+
else:
|
|
166
|
+
logger.debug(f"ContainerProcess {self._process_id} exited with unexpected status: {which}")
|
|
167
|
+
self._returncode = -1
|
|
168
|
+
raise InvalidError("Unexpected exit status")
|
|
169
|
+
except ExecTimeoutError:
|
|
170
|
+
logger.debug(f"ContainerProcess {self._process_id} did not complete within deadline")
|
|
171
|
+
# TODO(saltzm): This is a weird API, but customers currently may rely on it. This
|
|
172
|
+
# should be a ExecTimeoutError.
|
|
173
|
+
self._returncode = -1
|
|
174
|
+
|
|
175
|
+
return self._returncode
|
|
176
|
+
|
|
177
|
+
async def attach(self):
|
|
178
|
+
"""mdmd:hidden"""
|
|
179
|
+
if platform.system() == "Windows":
|
|
180
|
+
print("interactive exec is not currently supported on Windows.") # noqa: T201
|
|
181
|
+
return
|
|
182
|
+
|
|
183
|
+
from .output import OutputManager
|
|
184
|
+
|
|
185
|
+
output = OutputManager.get()
|
|
186
|
+
connecting_status = output.status("Connecting...")
|
|
187
|
+
connecting_status.start()
|
|
188
|
+
on_connect = asyncio.Event()
|
|
189
|
+
|
|
190
|
+
async def _write_to_fd_loop(stream: _StreamReader[T]):
|
|
191
|
+
async for chunk in _iter_stream_as_bytes(stream):
|
|
192
|
+
if chunk is None:
|
|
193
|
+
break
|
|
194
|
+
|
|
195
|
+
if not on_connect.is_set():
|
|
196
|
+
connecting_status.stop()
|
|
197
|
+
on_connect.set()
|
|
198
|
+
|
|
199
|
+
await write_to_fd(stream.file_descriptor, chunk)
|
|
200
|
+
|
|
201
|
+
async def _handle_input(data: bytes, message_index: int):
|
|
202
|
+
self.stdin.write(data)
|
|
203
|
+
await self.stdin.drain()
|
|
204
|
+
|
|
205
|
+
async with TaskContext() as tc:
|
|
206
|
+
stdout_task = tc.create_task(_write_to_fd_loop(self.stdout))
|
|
207
|
+
stderr_task = tc.create_task(_write_to_fd_loop(self.stderr))
|
|
208
|
+
|
|
209
|
+
try:
|
|
210
|
+
# Time out if we can't connect fast enough.
|
|
211
|
+
await asyncio.wait_for(on_connect.wait(), timeout=60)
|
|
212
|
+
|
|
213
|
+
async with stream_from_stdin(_handle_input, use_raw_terminal=True):
|
|
214
|
+
await stdout_task
|
|
215
|
+
await stderr_task
|
|
216
|
+
|
|
217
|
+
except (asyncio.TimeoutError, TimeoutError):
|
|
218
|
+
connecting_status.stop()
|
|
219
|
+
stdout_task.cancel()
|
|
220
|
+
stderr_task.cancel()
|
|
221
|
+
raise InteractiveTimeoutError("Failed to establish connection to container. Please try again.")
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
ContainerProcess = synchronize_api(_ContainerProcess)
|
|
@@ -7,140 +7,27 @@ import typing_extensions
|
|
|
7
7
|
|
|
8
8
|
T = typing.TypeVar("T")
|
|
9
9
|
|
|
10
|
-
class _ContainerProcessThroughServer(typing.Generic[T]):
|
|
11
|
-
"""Abstract base class for generic types.
|
|
12
|
-
|
|
13
|
-
A generic type is typically declared by inheriting from
|
|
14
|
-
this class parameterized with one or more type variables.
|
|
15
|
-
For example, a generic mapping type might be defined as::
|
|
16
|
-
|
|
17
|
-
class Mapping(Generic[KT, VT]):
|
|
18
|
-
def __getitem__(self, key: KT) -> VT:
|
|
19
|
-
...
|
|
20
|
-
# Etc.
|
|
21
|
-
|
|
22
|
-
This class can then be used as follows::
|
|
23
|
-
|
|
24
|
-
def lookup_name(mapping: Mapping[KT, VT], key: KT, default: VT) -> VT:
|
|
25
|
-
try:
|
|
26
|
-
return mapping[key]
|
|
27
|
-
except KeyError:
|
|
28
|
-
return default
|
|
29
|
-
"""
|
|
30
|
-
|
|
31
|
-
_process_id: typing.Optional[str]
|
|
32
|
-
_stdout: modal.io_streams._StreamReader[T]
|
|
33
|
-
_stderr: modal.io_streams._StreamReader[T]
|
|
34
|
-
_stdin: modal.io_streams._StreamWriter
|
|
35
|
-
_exec_deadline: typing.Optional[float]
|
|
36
|
-
_text: bool
|
|
37
|
-
_by_line: bool
|
|
38
|
-
_returncode: typing.Optional[int]
|
|
39
|
-
|
|
40
|
-
def __init__(
|
|
41
|
-
self,
|
|
42
|
-
process_id: str,
|
|
43
|
-
task_id: str,
|
|
44
|
-
client: modal.client._Client,
|
|
45
|
-
stdout: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
|
46
|
-
stderr: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
|
47
|
-
exec_deadline: typing.Optional[float] = None,
|
|
48
|
-
text: bool = True,
|
|
49
|
-
by_line: bool = False,
|
|
50
|
-
) -> None:
|
|
51
|
-
"""Initialize self. See help(type(self)) for accurate signature."""
|
|
52
|
-
...
|
|
53
|
-
|
|
54
|
-
def __repr__(self) -> str:
|
|
55
|
-
"""Return repr(self)."""
|
|
56
|
-
...
|
|
57
|
-
|
|
58
|
-
@property
|
|
59
|
-
def stdout(self) -> modal.io_streams._StreamReader[T]:
|
|
60
|
-
"""StreamReader for the container process's stdout stream."""
|
|
61
|
-
...
|
|
62
|
-
|
|
63
|
-
@property
|
|
64
|
-
def stderr(self) -> modal.io_streams._StreamReader[T]:
|
|
65
|
-
"""StreamReader for the container process's stderr stream."""
|
|
66
|
-
...
|
|
67
|
-
|
|
68
|
-
@property
|
|
69
|
-
def stdin(self) -> modal.io_streams._StreamWriter:
|
|
70
|
-
"""StreamWriter for the container process's stdin stream."""
|
|
71
|
-
...
|
|
72
|
-
|
|
73
|
-
@property
|
|
74
|
-
def returncode(self) -> int: ...
|
|
75
|
-
async def poll(self) -> typing.Optional[int]:
|
|
76
|
-
"""Check if the container process has finished running.
|
|
77
|
-
|
|
78
|
-
Returns `None` if the process is still running, else returns the exit code.
|
|
79
|
-
"""
|
|
80
|
-
...
|
|
81
|
-
|
|
82
|
-
async def _wait_for_completion(self) -> int: ...
|
|
83
|
-
async def wait(self) -> int:
|
|
84
|
-
"""Wait for the container process to finish running. Returns the exit code."""
|
|
85
|
-
...
|
|
86
|
-
|
|
87
|
-
async def attach(self):
|
|
88
|
-
"""mdmd:hidden"""
|
|
89
|
-
...
|
|
90
|
-
|
|
91
10
|
def _iter_stream_as_bytes(stream: modal.io_streams._StreamReader[T]):
|
|
92
11
|
"""Yield raw bytes from a StreamReader regardless of text mode/backend."""
|
|
93
12
|
...
|
|
94
13
|
|
|
95
|
-
class
|
|
96
|
-
"""
|
|
14
|
+
class _ContainerProcess(typing.Generic[T]):
|
|
15
|
+
"""Represents a running process in a container.
|
|
16
|
+
|
|
17
|
+
Container processes communicate via direct communication with
|
|
97
18
|
the Modal worker where the container is running.
|
|
98
19
|
"""
|
|
99
|
-
def __init__(
|
|
100
|
-
self,
|
|
101
|
-
process_id: str,
|
|
102
|
-
client: modal.client._Client,
|
|
103
|
-
command_router_client: modal._utils.task_command_router_client.TaskCommandRouterClient,
|
|
104
|
-
task_id: str,
|
|
105
|
-
*,
|
|
106
|
-
stdout: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
|
107
|
-
stderr: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
|
108
|
-
exec_deadline: typing.Optional[float] = None,
|
|
109
|
-
text: bool = True,
|
|
110
|
-
by_line: bool = False,
|
|
111
|
-
) -> None:
|
|
112
|
-
"""Initialize self. See help(type(self)) for accurate signature."""
|
|
113
|
-
...
|
|
114
|
-
|
|
115
|
-
def __repr__(self) -> str:
|
|
116
|
-
"""Return repr(self)."""
|
|
117
|
-
...
|
|
118
|
-
|
|
119
|
-
@property
|
|
120
|
-
def stdout(self) -> modal.io_streams._StreamReader[T]: ...
|
|
121
|
-
@property
|
|
122
|
-
def stderr(self) -> modal.io_streams._StreamReader[T]: ...
|
|
123
|
-
@property
|
|
124
|
-
def stdin(self) -> modal.io_streams._StreamWriter: ...
|
|
125
|
-
@property
|
|
126
|
-
def returncode(self) -> int: ...
|
|
127
|
-
async def poll(self) -> typing.Optional[int]: ...
|
|
128
|
-
async def wait(self) -> int: ...
|
|
129
|
-
async def attach(self): ...
|
|
130
|
-
|
|
131
|
-
class _ContainerProcess(typing.Generic[T]):
|
|
132
|
-
"""Represents a running process in a container."""
|
|
133
20
|
def __init__(
|
|
134
21
|
self,
|
|
135
22
|
process_id: str,
|
|
136
23
|
task_id: str,
|
|
137
24
|
client: modal.client._Client,
|
|
25
|
+
command_router_client: modal._utils.task_command_router_client.TaskCommandRouterClient,
|
|
138
26
|
stdout: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
|
139
27
|
stderr: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
|
140
28
|
exec_deadline: typing.Optional[float] = None,
|
|
141
29
|
text: bool = True,
|
|
142
30
|
by_line: bool = False,
|
|
143
|
-
command_router_client: typing.Optional[modal._utils.task_command_router_client.TaskCommandRouterClient] = None,
|
|
144
31
|
) -> None:
|
|
145
32
|
"""Initialize self. See help(type(self)) for accurate signature."""
|
|
146
33
|
...
|
|
@@ -182,18 +69,22 @@ class _ContainerProcess(typing.Generic[T]):
|
|
|
182
69
|
...
|
|
183
70
|
|
|
184
71
|
class ContainerProcess(typing.Generic[T]):
|
|
185
|
-
"""Represents a running process in a container.
|
|
72
|
+
"""Represents a running process in a container.
|
|
73
|
+
|
|
74
|
+
Container processes communicate via direct communication with
|
|
75
|
+
the Modal worker where the container is running.
|
|
76
|
+
"""
|
|
186
77
|
def __init__(
|
|
187
78
|
self,
|
|
188
79
|
process_id: str,
|
|
189
80
|
task_id: str,
|
|
190
81
|
client: modal.client.Client,
|
|
82
|
+
command_router_client: modal._utils.task_command_router_client.TaskCommandRouterClient,
|
|
191
83
|
stdout: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
|
192
84
|
stderr: modal.stream_type.StreamType = modal.stream_type.StreamType.PIPE,
|
|
193
85
|
exec_deadline: typing.Optional[float] = None,
|
|
194
86
|
text: bool = True,
|
|
195
87
|
by_line: bool = False,
|
|
196
|
-
command_router_client: typing.Optional[modal._utils.task_command_router_client.TaskCommandRouterClient] = None,
|
|
197
88
|
) -> None: ...
|
|
198
89
|
def __repr__(self) -> str: ...
|
|
199
90
|
@property
|
|
@@ -347,7 +347,7 @@ class Function(
|
|
|
347
347
|
|
|
348
348
|
_call_generator: ___call_generator_spec
|
|
349
349
|
|
|
350
|
-
class __remote_spec(typing_extensions.Protocol[
|
|
350
|
+
class __remote_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER]):
|
|
351
351
|
def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> ReturnType_INNER:
|
|
352
352
|
"""Calls the function remotely, executing it with the given arguments and returning the execution's result."""
|
|
353
353
|
...
|
|
@@ -356,7 +356,7 @@ class Function(
|
|
|
356
356
|
"""Calls the function remotely, executing it with the given arguments and returning the execution's result."""
|
|
357
357
|
...
|
|
358
358
|
|
|
359
|
-
remote: __remote_spec[modal._functions.
|
|
359
|
+
remote: __remote_spec[modal._functions.P, modal._functions.ReturnType]
|
|
360
360
|
|
|
361
361
|
class __remote_gen_spec(typing_extensions.Protocol):
|
|
362
362
|
def __call__(self, /, *args, **kwargs) -> typing.Generator[typing.Any, None, None]:
|
|
@@ -383,7 +383,7 @@ class Function(
|
|
|
383
383
|
"""
|
|
384
384
|
...
|
|
385
385
|
|
|
386
|
-
class ___experimental_spawn_spec(typing_extensions.Protocol[
|
|
386
|
+
class ___experimental_spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER]):
|
|
387
387
|
def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]:
|
|
388
388
|
"""[Experimental] Calls the function with the given arguments, without waiting for the results.
|
|
389
389
|
|
|
@@ -406,7 +406,7 @@ class Function(
|
|
|
406
406
|
"""
|
|
407
407
|
...
|
|
408
408
|
|
|
409
|
-
_experimental_spawn: ___experimental_spawn_spec[modal._functions.
|
|
409
|
+
_experimental_spawn: ___experimental_spawn_spec[modal._functions.P, modal._functions.ReturnType]
|
|
410
410
|
|
|
411
411
|
class ___spawn_map_inner_spec(typing_extensions.Protocol[P_INNER]):
|
|
412
412
|
def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> None: ...
|
|
@@ -414,7 +414,7 @@ class Function(
|
|
|
414
414
|
|
|
415
415
|
_spawn_map_inner: ___spawn_map_inner_spec[modal._functions.P]
|
|
416
416
|
|
|
417
|
-
class __spawn_spec(typing_extensions.Protocol[
|
|
417
|
+
class __spawn_spec(typing_extensions.Protocol[P_INNER, ReturnType_INNER]):
|
|
418
418
|
def __call__(self, /, *args: P_INNER.args, **kwargs: P_INNER.kwargs) -> FunctionCall[ReturnType_INNER]:
|
|
419
419
|
"""Calls the function with the given arguments, without waiting for the results.
|
|
420
420
|
|
|
@@ -435,7 +435,7 @@ class Function(
|
|
|
435
435
|
"""
|
|
436
436
|
...
|
|
437
437
|
|
|
438
|
-
spawn: __spawn_spec[modal._functions.
|
|
438
|
+
spawn: __spawn_spec[modal._functions.P, modal._functions.ReturnType]
|
|
439
439
|
|
|
440
440
|
def get_raw_f(self) -> collections.abc.Callable[..., typing.Any]:
|
|
441
441
|
"""Return the inner Python object wrapped by this Modal Function."""
|