modal 1.5.3.dev4__tar.gz → 1.5.3.dev6__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.5.3.dev4 → modal-1.5.3.dev6}/PKG-INFO +1 -1
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_environments.py +18 -39
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_functions.py +11 -15
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_utils/task_command_router_client.py +127 -3
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/client.pyi +2 -2
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/container_process.py +13 -1
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/container_process.pyi +27 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/environments.pyi +8 -8
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/functions.pyi +20 -20
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/sandbox.py +37 -14
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/sandbox.pyi +6 -2
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/sandbox_fs.py +32 -80
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/sandbox_fs.pyi +24 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal.egg-info/PKG-INFO +1 -1
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal_docs/gen_reference_docs.py +0 -1
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal_docs/mdmd/mdmd.py +9 -2
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal_docs/mdmd/types.py +1 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal_proto/api_grpc.py +16 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal_proto/api_pb2.py +764 -744
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal_proto/api_pb2.pyi +63 -10
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal_proto/api_pb2_grpc.py +33 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal_proto/api_pb2_grpc.pyi +10 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal_proto/modal_api_grpc.py +1 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal_version/__init__.py +1 -1
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/LICENSE +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/README.md +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/__init__.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/__main__.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_billing.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_clustered_functions.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_clustered_functions.pyi +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_container_entrypoint.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_function_variants.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_grpc_client.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_image.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_ipython.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_load_context.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_location.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_logs.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_object.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_output/__init__.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_output/manager.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_output/pty.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_output/rich.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_output/status.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_partial_function.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_resolver.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_resources.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_runtime/__init__.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_runtime/asgi.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_runtime/container_io_manager.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_runtime/container_io_manager.pyi +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_runtime/execution_context.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_runtime/execution_context.pyi +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_runtime/gpu_memory_snapshot.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_runtime/task_lifecycle_manager.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_runtime/task_lifecycle_manager.pyi +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_runtime/telemetry.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_runtime/user_code_event_loop.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_runtime/user_code_imports.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_serialization.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_server.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_traceback.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_tunnel.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_tunnel.pyi +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_type_manager.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_utils/__init__.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_utils/app_utils.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_utils/async_utils.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_utils/auth_token_manager.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_utils/blob_utils.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_utils/browser_utils.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_utils/bytes_io_segment_payload.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_utils/curl_utils.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_utils/deprecation.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_utils/docker_utils.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_utils/function_utils.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_utils/git_utils.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_utils/grpc_testing.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_utils/grpc_utils.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_utils/hash_utils.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_utils/http_utils.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_utils/jwt_utils.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_utils/logger.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_utils/mount_utils.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_utils/name_utils.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_utils/package_utils.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_utils/pattern_utils.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_utils/proxy_support.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_utils/rand_pb_testing.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_utils/sandbox_fs_utils.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_utils/shell_utils.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_utils/time_utils.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_vendor/__init__.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_vendor/a2wsgi_wsgi.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_vendor/cloudpickle.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_vendor/tblib.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_vendor/version.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_watcher.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/_workspace.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/app.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/app.pyi +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/billing.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/billing.pyi +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/builder/2023.12.312.txt +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/builder/2023.12.txt +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/builder/2024.04.txt +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/builder/2024.10.txt +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/builder/2025.06.txt +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/builder/PREVIEW.txt +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/builder/README.md +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/builder/base-images.json +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/call_graph.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/cli/__init__.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/cli/_download.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/cli/_help.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/cli/_traceback.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/cli/app.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/cli/billing.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/cli/bootstrap.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/cli/changelog.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/cli/cluster.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/cli/config.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/cli/container.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/cli/curl.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/cli/dashboard.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/cli/dict.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/cli/endpoint.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/cli/entry_point.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/cli/environment.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/cli/image.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/cli/import_refs.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/cli/launch.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/cli/logo.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/cli/network_file_system.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/cli/profile.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/cli/programs/__init__.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/cli/programs/run_jupyter.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/cli/programs/vscode.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/cli/queues.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/cli/run.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/cli/secret.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/cli/selector.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/cli/shell.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/cli/skills.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/cli/token.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/cli/utils.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/cli/volume.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/cli/workspace.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/client.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/cloud_bucket_mount.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/cloud_bucket_mount.pyi +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/cls.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/cls.pyi +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/config.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/dict.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/dict.pyi +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/environments.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/exception.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/experimental/__init__.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/experimental/flash.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/experimental/flash.pyi +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/experimental/ipython.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/file_io.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/file_io.pyi +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/file_pattern_matcher.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/functions.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/image.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/image.pyi +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/io_streams.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/io_streams.pyi +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/mount.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/mount.pyi +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/network_file_system.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/network_file_system.pyi +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/object.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/object.pyi +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/output.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/parallel_map.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/parallel_map.pyi +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/partial_function.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/partial_function.pyi +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/proxy.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/proxy.pyi +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/py.typed +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/queue.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/queue.pyi +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/retries.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/runner.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/runner.pyi +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/running_app.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/schedule.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/scheduler_placement.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/secret.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/secret.pyi +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/server.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/server.pyi +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/serving.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/serving.pyi +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/skills/modal/SKILL.md +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/snapshot.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/snapshot.pyi +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/stream_type.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/token_flow.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/token_flow.pyi +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/types.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/volume.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/volume.pyi +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/workspace.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal/workspace.pyi +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal.egg-info/SOURCES.txt +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal.egg-info/dependency_links.txt +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal.egg-info/entry_points.txt +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal.egg-info/requires.txt +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal.egg-info/top_level.txt +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal_docs/__init__.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal_docs/gen_cli_docs.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal_docs/gen_cli_docs_main.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal_docs/gen_reference_docs_main.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal_docs/mdmd/__init__.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal_docs/mdmd/signatures.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal_proto/__init__.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal_proto/py.typed +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal_proto/task_command_router_grpc.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal_proto/task_command_router_pb2.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal_proto/task_command_router_pb2.pyi +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal_proto/task_command_router_pb2_grpc.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal_proto/task_command_router_pb2_grpc.pyi +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/modal_version/__main__.py +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/pyproject.toml +0 -0
- {modal-1.5.3.dev4 → modal-1.5.3.dev6}/setup.cfg +0 -0
|
@@ -103,26 +103,6 @@ class _EnvironmentManager:
|
|
|
103
103
|
await client.stub.EnvironmentDelete(api_pb2.EnvironmentDeleteRequest(name=name))
|
|
104
104
|
|
|
105
105
|
|
|
106
|
-
def _role_to_proto(role: str) -> "api_pb2.EnvironmentRole.ValueType":
|
|
107
|
-
match role:
|
|
108
|
-
case "viewer":
|
|
109
|
-
return api_pb2.ENVIRONMENT_ROLE_VIEWER
|
|
110
|
-
case "contributor":
|
|
111
|
-
return api_pb2.ENVIRONMENT_ROLE_CONTRIBUTOR
|
|
112
|
-
case _:
|
|
113
|
-
raise InvalidError(f"Invalid Environment role: {role!r} (expected 'viewer' or 'contributor')")
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
def _role_from_proto(proto_value: int) -> str:
|
|
117
|
-
match proto_value:
|
|
118
|
-
case api_pb2.ENVIRONMENT_ROLE_VIEWER:
|
|
119
|
-
return "viewer"
|
|
120
|
-
case api_pb2.ENVIRONMENT_ROLE_CONTRIBUTOR:
|
|
121
|
-
return "contributor"
|
|
122
|
-
case _:
|
|
123
|
-
raise ValueError(f"Unknown environment role: {proto_value}")
|
|
124
|
-
|
|
125
|
-
|
|
126
106
|
class _EnvironmentMembersManager:
|
|
127
107
|
"""mdmd:namespace
|
|
128
108
|
Namespace with methods for managing the membership of a restricted Environment.
|
|
@@ -135,31 +115,30 @@ class _EnvironmentMembersManager:
|
|
|
135
115
|
self._environment = environment
|
|
136
116
|
|
|
137
117
|
async def list(self) -> dict[Literal["users", "service_users"], dict[str, str]]:
|
|
138
|
-
"""
|
|
118
|
+
"""Enumerate the environment roles for each user and service user in the workspace.
|
|
139
119
|
|
|
140
120
|
**Examples:**
|
|
141
121
|
|
|
142
122
|
```python notest
|
|
143
|
-
members = modal.Environment.from_name("my-
|
|
123
|
+
members = modal.Environment.from_name("my-env").members.list()
|
|
144
124
|
print(members)
|
|
145
125
|
# {
|
|
146
|
-
# "users": {"alice": "contributor", "bob": "viewer"},
|
|
147
|
-
# "service_users": {"alice-bot": "contributor"},
|
|
126
|
+
# "users": {"alice": "contributor", "bob": "viewer", "carol": "contributor"},
|
|
127
|
+
# "service_users": {"alice-bot": "contributor", "ops-bot": "viewer", "ci-bot": "no-access"},
|
|
148
128
|
# }
|
|
149
129
|
```
|
|
150
130
|
"""
|
|
151
131
|
await self._environment.hydrate()
|
|
152
|
-
req = api_pb2.
|
|
153
|
-
resp = await self._environment.client.stub.
|
|
132
|
+
req = api_pb2.EnvironmentGetRolesRequest(environment_id=self._environment.object_id)
|
|
133
|
+
resp = await self._environment.client.stub.EnvironmentGetRoles(req)
|
|
154
134
|
|
|
155
135
|
users: dict[str, str] = {}
|
|
156
136
|
service_users: dict[str, str] = {}
|
|
157
137
|
for principal in resp.principal_roles:
|
|
158
|
-
role = _role_from_proto(principal.role)
|
|
159
138
|
if principal.user_id:
|
|
160
|
-
users[principal.user_name] =
|
|
139
|
+
users[principal.user_name] = principal.role_str
|
|
161
140
|
elif principal.service_user_id:
|
|
162
|
-
service_users[principal.service_user_name] =
|
|
141
|
+
service_users[principal.service_user_name] = principal.role_str
|
|
163
142
|
|
|
164
143
|
return {"users": users, "service_users": service_users}
|
|
165
144
|
|
|
@@ -188,13 +167,13 @@ class _EnvironmentMembersManager:
|
|
|
188
167
|
users = users or {}
|
|
189
168
|
service_users = service_users or {}
|
|
190
169
|
|
|
191
|
-
req = api_pb2.
|
|
192
|
-
resp = await self._environment.client.stub.
|
|
170
|
+
req = api_pb2.EnvironmentGetRolesRequest(environment_id=self._environment.object_id)
|
|
171
|
+
resp = await self._environment.client.stub.EnvironmentGetRoles(req)
|
|
193
172
|
|
|
194
|
-
#
|
|
173
|
+
# EnvironmentGetRoles returns every workspace principal
|
|
195
174
|
user_name_to_id: dict[str, str] = {}
|
|
196
175
|
service_user_name_to_id: dict[str, str] = {}
|
|
197
|
-
for principal in
|
|
176
|
+
for principal in resp.principal_roles:
|
|
198
177
|
if principal.user_id:
|
|
199
178
|
user_name_to_id[principal.user_name] = principal.user_id
|
|
200
179
|
elif principal.service_user_id:
|
|
@@ -207,7 +186,7 @@ class _EnvironmentMembersManager:
|
|
|
207
186
|
requests[f"User {name!r}"] = api_pb2.EnvironmentRoleSetRequest(
|
|
208
187
|
environment_id=self._environment.object_id,
|
|
209
188
|
user_id=user_name_to_id[name],
|
|
210
|
-
|
|
189
|
+
role_str=role,
|
|
211
190
|
)
|
|
212
191
|
for name, role in service_users.items():
|
|
213
192
|
if name not in service_user_name_to_id:
|
|
@@ -215,7 +194,7 @@ class _EnvironmentMembersManager:
|
|
|
215
194
|
requests[f"Service user {name!r}"] = api_pb2.EnvironmentRoleSetRequest(
|
|
216
195
|
environment_id=self._environment.object_id,
|
|
217
196
|
service_user_id=service_user_name_to_id[name],
|
|
218
|
-
|
|
197
|
+
role_str=role,
|
|
219
198
|
)
|
|
220
199
|
|
|
221
200
|
await self._dispatch_role_updates(requests)
|
|
@@ -242,8 +221,8 @@ class _EnvironmentMembersManager:
|
|
|
242
221
|
users = users or []
|
|
243
222
|
service_users = service_users or []
|
|
244
223
|
|
|
245
|
-
req = api_pb2.
|
|
246
|
-
resp = await self._environment.client.stub.
|
|
224
|
+
req = api_pb2.EnvironmentGetRolesRequest(environment_id=self._environment.object_id)
|
|
225
|
+
resp = await self._environment.client.stub.EnvironmentGetRoles(req)
|
|
247
226
|
|
|
248
227
|
user_name_to_id: dict[str, str] = {}
|
|
249
228
|
service_user_name_to_id: dict[str, str] = {}
|
|
@@ -256,7 +235,7 @@ class _EnvironmentMembersManager:
|
|
|
256
235
|
requests: dict[str, api_pb2.EnvironmentRoleSetRequest] = {}
|
|
257
236
|
for name in users:
|
|
258
237
|
if name not in user_name_to_id:
|
|
259
|
-
raise InvalidError(f"User {name!r}
|
|
238
|
+
raise InvalidError(f"User {name!r} not found in workspace")
|
|
260
239
|
requests[f"User {name!r}"] = api_pb2.EnvironmentRoleSetRequest(
|
|
261
240
|
environment_id=self._environment.object_id,
|
|
262
241
|
user_id=user_name_to_id[name],
|
|
@@ -264,7 +243,7 @@ class _EnvironmentMembersManager:
|
|
|
264
243
|
)
|
|
265
244
|
for name in service_users:
|
|
266
245
|
if name not in service_user_name_to_id:
|
|
267
|
-
raise InvalidError(f"Service user {name!r}
|
|
246
|
+
raise InvalidError(f"Service user {name!r} not found in workspace")
|
|
268
247
|
requests[f"Service user {name!r}"] = api_pb2.EnvironmentRoleSetRequest(
|
|
269
248
|
environment_id=self._environment.object_id,
|
|
270
249
|
service_user_id=service_user_name_to_id[name],
|
|
@@ -2073,11 +2073,13 @@ class _FunctionCall(typing.Generic[ReturnType], _Object, type_prefix="fc"):
|
|
|
2073
2073
|
|
|
2074
2074
|
@live_method
|
|
2075
2075
|
async def get_call_graph(self) -> list[InputInfo]:
|
|
2076
|
-
"""
|
|
2077
|
-
call ID, along with the status of execution for each node.
|
|
2076
|
+
"""Fetch information about the graph of Inputs this FunctionCall is part of.
|
|
2078
2077
|
|
|
2079
|
-
|
|
2080
|
-
|
|
2078
|
+
Note: the call graph data is not populated in real-time, and its capture is best-effort.
|
|
2079
|
+
We do not recommend relying on this method for critical use cases.
|
|
2080
|
+
|
|
2081
|
+
See the [`modal.types`](/docs/sdk/py/latest/modal.types) reference for information
|
|
2082
|
+
on the return values.
|
|
2081
2083
|
|
|
2082
2084
|
Returns:
|
|
2083
2085
|
A list of `InputInfo` nodes describing the call graph.
|
|
@@ -2088,19 +2090,13 @@ class _FunctionCall(typing.Generic[ReturnType], _Object, type_prefix="fc"):
|
|
|
2088
2090
|
return _reconstruct_call_graph(response)
|
|
2089
2091
|
|
|
2090
2092
|
@live_method
|
|
2091
|
-
async def cancel(
|
|
2092
|
-
|
|
2093
|
-
# if true, containers running the inputs are forcibly terminated
|
|
2094
|
-
terminate_containers: bool = False,
|
|
2095
|
-
):
|
|
2096
|
-
"""Cancels the function call, which will stop its execution and mark its inputs as
|
|
2097
|
-
[`TERMINATED`](https://modal.com/docs/sdk/py/latest/modal.call_graph#modalcall_graphinputstatus).
|
|
2098
|
-
|
|
2099
|
-
If `terminate_containers=True` - the containers running the cancelled inputs are all terminated
|
|
2100
|
-
causing any non-cancelled inputs on those containers to be rescheduled in new containers.
|
|
2093
|
+
async def cancel(self, terminate_containers: bool = False):
|
|
2094
|
+
"""Cancel the FunctionCall and terminate its inputs without retrying.
|
|
2101
2095
|
|
|
2102
2096
|
Args:
|
|
2103
|
-
terminate_containers: If True,
|
|
2097
|
+
terminate_containers: If True, terminate the containers running the cancelled
|
|
2098
|
+
inputs. Any other inputs running concurrently on those containers will be
|
|
2099
|
+
rescheduled.
|
|
2104
2100
|
"""
|
|
2105
2101
|
request = api_pb2.FunctionCallCancelRequest(
|
|
2106
2102
|
function_call_id=self.object_id, terminate_containers=terminate_containers
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Copyright Modal Labs 2025
|
|
2
2
|
import asyncio
|
|
3
3
|
import base64
|
|
4
|
+
import io
|
|
4
5
|
import json
|
|
5
6
|
import socket
|
|
6
7
|
import ssl
|
|
@@ -8,16 +9,16 @@ import time
|
|
|
8
9
|
import typing
|
|
9
10
|
import urllib.parse
|
|
10
11
|
import weakref
|
|
11
|
-
from collections.abc import AsyncGenerator, Callable
|
|
12
|
+
from collections.abc import AsyncGenerator, AsyncIterable, Callable
|
|
12
13
|
from contextlib import suppress
|
|
13
|
-
from typing import TypeVar
|
|
14
|
+
from typing import BinaryIO, TypeVar
|
|
14
15
|
|
|
15
16
|
import grpclib.client
|
|
16
17
|
from grpclib import GRPCError, Status
|
|
17
18
|
from grpclib.exceptions import StreamTerminatedError
|
|
18
19
|
|
|
19
20
|
from modal.config import logger
|
|
20
|
-
from modal.exception import ExecTimeoutError, TimeoutError as ModalTimeoutError
|
|
21
|
+
from modal.exception import AuthError, ExecTimeoutError, InternalError, ServiceError, TimeoutError as ModalTimeoutError
|
|
21
22
|
from modal_proto import api_pb2, task_command_router_pb2 as sr_pb2
|
|
22
23
|
from modal_proto.task_command_router_grpc import TaskCommandRouterStub
|
|
23
24
|
|
|
@@ -26,6 +27,17 @@ from .._utils.grpc_utils import ModalChannel, create_channel_config
|
|
|
26
27
|
from .async_utils import aclosing, retry
|
|
27
28
|
from .grpc_utils import RETRYABLE_GRPC_STATUS_CODES
|
|
28
29
|
|
|
30
|
+
STREAMING_STDIN_CHUNK_SIZE = 256 * 1024
|
|
31
|
+
|
|
32
|
+
_STREAMING_STDIN_RESUMABLE_EXCEPTIONS = (
|
|
33
|
+
AuthError,
|
|
34
|
+
InternalError,
|
|
35
|
+
ServiceError,
|
|
36
|
+
StreamTerminatedError,
|
|
37
|
+
OSError,
|
|
38
|
+
asyncio.TimeoutError,
|
|
39
|
+
)
|
|
40
|
+
|
|
29
41
|
|
|
30
42
|
@retry(n_attempts=34, base_delay=1, max_delay=10, attempt_timeout=10, total_timeout=310)
|
|
31
43
|
async def _connect_channel(channel: grpclib.client.Channel):
|
|
@@ -468,6 +480,118 @@ class TaskCommandRouterClient:
|
|
|
468
480
|
lambda: self._call_with_auth_retry(self._stub.TaskExecStdinWrite, request)
|
|
469
481
|
)
|
|
470
482
|
|
|
483
|
+
async def exec_stdin_write_stream(
|
|
484
|
+
self,
|
|
485
|
+
task_id: str,
|
|
486
|
+
exec_id: str,
|
|
487
|
+
source: BinaryIO,
|
|
488
|
+
chunk_size: int = STREAMING_STDIN_CHUNK_SIZE,
|
|
489
|
+
max_resume_attempts: int = 9,
|
|
490
|
+
) -> int:
|
|
491
|
+
"""Stream `source` into the exec's stdin, with bounded resume on transient failures.
|
|
492
|
+
|
|
493
|
+
Streams the full contents of `source` in one client-streaming RPC and
|
|
494
|
+
closes stdin (EOF) on success. On a resumable error, queries
|
|
495
|
+
`exec_stdin_status` for the server's canonical offset, seeks `source`
|
|
496
|
+
to that point, and reopens the stream.
|
|
497
|
+
|
|
498
|
+
Args:
|
|
499
|
+
task_id: The task ID of the task running the exec'd command.
|
|
500
|
+
exec_id: The execution ID of the command to write to.
|
|
501
|
+
source: A seekable byte source (file, BytesIO, etc.).
|
|
502
|
+
chunk_size: Bytes per outbound message.
|
|
503
|
+
max_resume_attempts: Upper bound on resume retries before giving up.
|
|
504
|
+
|
|
505
|
+
Returns:
|
|
506
|
+
The total number of bytes streamed into the exec's stdin.
|
|
507
|
+
"""
|
|
508
|
+
offset = 0
|
|
509
|
+
attempt = 0
|
|
510
|
+
while True:
|
|
511
|
+
|
|
512
|
+
async def _chunks():
|
|
513
|
+
while True:
|
|
514
|
+
chunk = source.read(chunk_size)
|
|
515
|
+
if not chunk:
|
|
516
|
+
return
|
|
517
|
+
yield chunk
|
|
518
|
+
|
|
519
|
+
try:
|
|
520
|
+
source.seek(offset)
|
|
521
|
+
await self._exec_stdin_write_stream(task_id, exec_id, offset, _chunks())
|
|
522
|
+
return source.tell()
|
|
523
|
+
except (*_STREAMING_STDIN_RESUMABLE_EXCEPTIONS, AttributeError) as e:
|
|
524
|
+
# StreamTerminatedError surfaces as AttributeError in grpclib<=0.4.7;
|
|
525
|
+
# see call_with_retries_on_transient_errors.
|
|
526
|
+
if isinstance(e, AttributeError) and "_write_appdata" not in str(e):
|
|
527
|
+
raise
|
|
528
|
+
attempt += 1
|
|
529
|
+
if attempt > max_resume_attempts:
|
|
530
|
+
raise
|
|
531
|
+
status = await self.exec_stdin_status(task_id=task_id, exec_id=exec_id)
|
|
532
|
+
if status.closed:
|
|
533
|
+
pos = source.tell()
|
|
534
|
+
if status.num_bytes_written == pos and source.seek(0, io.SEEK_END) == pos:
|
|
535
|
+
logger.debug(f"exec_stdin_write_stream completed but response was lost: {e}")
|
|
536
|
+
return pos
|
|
537
|
+
raise
|
|
538
|
+
offset = status.num_bytes_written
|
|
539
|
+
logger.debug(f"exec_stdin_write_stream resuming from offset {offset} after error: {e}")
|
|
540
|
+
|
|
541
|
+
async def _exec_stdin_write_stream(
|
|
542
|
+
self,
|
|
543
|
+
task_id: str,
|
|
544
|
+
exec_id: str,
|
|
545
|
+
start_offset: int,
|
|
546
|
+
chunks: AsyncIterable[bytes],
|
|
547
|
+
) -> sr_pb2.TaskExecStdinWriteStreamResponse | None:
|
|
548
|
+
"""Single client-streaming attempt: Start, Data chunks, then End (EOF).
|
|
549
|
+
|
|
550
|
+
Does not retry; `exec_stdin_write_stream` owns resume.
|
|
551
|
+
"""
|
|
552
|
+
with grpc_error_converter():
|
|
553
|
+
stream = self._stub.TaskExecStdinWriteStream.open(metadata=self._get_metadata())
|
|
554
|
+
async with stream as s:
|
|
555
|
+
start = sr_pb2.TaskExecStdinWriteStreamRequest(
|
|
556
|
+
start=sr_pb2.TaskExecStdinWriteStreamStart(
|
|
557
|
+
task_id=task_id,
|
|
558
|
+
exec_id=exec_id,
|
|
559
|
+
offset=start_offset,
|
|
560
|
+
),
|
|
561
|
+
)
|
|
562
|
+
await s.send_message(start)
|
|
563
|
+
async for data in chunks:
|
|
564
|
+
if not data:
|
|
565
|
+
continue
|
|
566
|
+
await s.send_message(sr_pb2.TaskExecStdinWriteStreamRequest(data=data))
|
|
567
|
+
# The server closes stdin only on this explicit End message. A
|
|
568
|
+
# stream that breaks before it leaves stdin open for resume.
|
|
569
|
+
await s.send_message(
|
|
570
|
+
sr_pb2.TaskExecStdinWriteStreamRequest(end=sr_pb2.TaskExecStdinWriteStreamEnd()),
|
|
571
|
+
end=True,
|
|
572
|
+
)
|
|
573
|
+
return await s.recv_message()
|
|
574
|
+
|
|
575
|
+
async def exec_stdin_status(self, task_id: str, exec_id: str) -> sr_pb2.TaskExecStdinStatusResponse:
|
|
576
|
+
"""Read the current stdin write status for an exec'd command, to support retries from the right offset.
|
|
577
|
+
|
|
578
|
+
Used by streaming clients to find the resume offset after a stream
|
|
579
|
+
failure. Evicts any in-flight stdin stream for the exec, so it is not
|
|
580
|
+
safe to call for read-only observability.
|
|
581
|
+
|
|
582
|
+
Args:
|
|
583
|
+
task_id: The task ID of the task running the exec'd command.
|
|
584
|
+
exec_id: The execution ID of the command to query.
|
|
585
|
+
Raises:
|
|
586
|
+
Other errors: If retries are exhausted on transient errors or if there's an error
|
|
587
|
+
from the RPC itself.
|
|
588
|
+
"""
|
|
589
|
+
request = sr_pb2.TaskExecStdinStatusRequest(task_id=task_id, exec_id=exec_id)
|
|
590
|
+
with grpc_error_converter():
|
|
591
|
+
return await call_with_retries_on_transient_errors(
|
|
592
|
+
lambda: self._call_with_auth_retry(self._stub.TaskExecStdinStatus, request)
|
|
593
|
+
)
|
|
594
|
+
|
|
471
595
|
async def sandbox_stdin_write_v2(
|
|
472
596
|
self, task_id: str, offset: int, data: bytes, eof: bool
|
|
473
597
|
) -> sr_pb2.SandboxStdinWriteV2Response:
|
|
@@ -37,7 +37,7 @@ class _Client:
|
|
|
37
37
|
server_url: str,
|
|
38
38
|
client_type: int,
|
|
39
39
|
credentials: typing.Optional[tuple[str, str]],
|
|
40
|
-
version: str = "1.5.3.
|
|
40
|
+
version: str = "1.5.3.dev6",
|
|
41
41
|
):
|
|
42
42
|
"""mdmd:hidden
|
|
43
43
|
The Modal client object is not intended to be instantiated directly by users.
|
|
@@ -207,7 +207,7 @@ class Client:
|
|
|
207
207
|
server_url: str,
|
|
208
208
|
client_type: int,
|
|
209
209
|
credentials: typing.Optional[tuple[str, str]],
|
|
210
|
-
version: str = "1.5.3.
|
|
210
|
+
version: str = "1.5.3.dev6",
|
|
211
211
|
):
|
|
212
212
|
"""mdmd:hidden
|
|
213
213
|
The Modal client object is not intended to be instantiated directly by users.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Copyright Modal Labs 2024
|
|
2
2
|
import asyncio
|
|
3
3
|
import platform
|
|
4
|
-
from typing import Generic, TypeVar
|
|
4
|
+
from typing import BinaryIO, Generic, TypeVar
|
|
5
5
|
|
|
6
6
|
from modal_proto import api_pb2
|
|
7
7
|
|
|
@@ -117,6 +117,18 @@ class _ContainerProcess(Generic[T]):
|
|
|
117
117
|
)
|
|
118
118
|
return self._returncode
|
|
119
119
|
|
|
120
|
+
async def _stdin_write_stream(self, source: BinaryIO) -> int:
|
|
121
|
+
"""mdmd:hidden
|
|
122
|
+
Stream `source` into the process's stdin and close it (EOF) on success.
|
|
123
|
+
|
|
124
|
+
Returns the total bytes streamed.
|
|
125
|
+
"""
|
|
126
|
+
return await self._command_router_client.exec_stdin_write_stream(
|
|
127
|
+
task_id=self._task_id,
|
|
128
|
+
exec_id=self._process_id,
|
|
129
|
+
source=source,
|
|
130
|
+
)
|
|
131
|
+
|
|
120
132
|
async def poll(self) -> int | None:
|
|
121
133
|
"""Check if the container process has finished running.
|
|
122
134
|
|
|
@@ -53,6 +53,14 @@ class _ContainerProcess(typing.Generic[T]):
|
|
|
53
53
|
|
|
54
54
|
@property
|
|
55
55
|
def returncode(self) -> int: ...
|
|
56
|
+
async def _stdin_write_stream(self, source: typing.BinaryIO) -> int:
|
|
57
|
+
"""mdmd:hidden
|
|
58
|
+
Stream `source` into the process's stdin and close it (EOF) on success.
|
|
59
|
+
|
|
60
|
+
Returns the total bytes streamed.
|
|
61
|
+
"""
|
|
62
|
+
...
|
|
63
|
+
|
|
56
64
|
async def poll(self) -> typing.Optional[int]:
|
|
57
65
|
"""Check if the container process has finished running.
|
|
58
66
|
|
|
@@ -105,6 +113,25 @@ class ContainerProcess(typing.Generic[T]):
|
|
|
105
113
|
@property
|
|
106
114
|
def returncode(self) -> int: ...
|
|
107
115
|
|
|
116
|
+
class ___stdin_write_stream_spec(typing_extensions.Protocol):
|
|
117
|
+
def __call__(self, /, source: typing.BinaryIO) -> int:
|
|
118
|
+
"""mdmd:hidden
|
|
119
|
+
Stream `source` into the process's stdin and close it (EOF) on success.
|
|
120
|
+
|
|
121
|
+
Returns the total bytes streamed.
|
|
122
|
+
"""
|
|
123
|
+
...
|
|
124
|
+
|
|
125
|
+
async def aio(self, /, source: typing.BinaryIO) -> int:
|
|
126
|
+
"""mdmd:hidden
|
|
127
|
+
Stream `source` into the process's stdin and close it (EOF) on success.
|
|
128
|
+
|
|
129
|
+
Returns the total bytes streamed.
|
|
130
|
+
"""
|
|
131
|
+
...
|
|
132
|
+
|
|
133
|
+
_stdin_write_stream: ___stdin_write_stream_spec
|
|
134
|
+
|
|
108
135
|
class __poll_spec(typing_extensions.Protocol):
|
|
109
136
|
def __call__(self, /) -> typing.Optional[int]:
|
|
110
137
|
"""Check if the container process has finished running.
|
|
@@ -113,32 +113,32 @@ class EnvironmentMembersManager:
|
|
|
113
113
|
|
|
114
114
|
class __list_spec(typing_extensions.Protocol):
|
|
115
115
|
def __call__(self, /) -> dict[typing.Literal["users", "service_users"], dict[str, str]]:
|
|
116
|
-
"""
|
|
116
|
+
"""Enumerate the environment roles for each user and service user in the workspace.
|
|
117
117
|
|
|
118
118
|
**Examples:**
|
|
119
119
|
|
|
120
120
|
```python notest
|
|
121
|
-
members = modal.Environment.from_name("my-
|
|
121
|
+
members = modal.Environment.from_name("my-env").members.list()
|
|
122
122
|
print(members)
|
|
123
123
|
# {
|
|
124
|
-
# "users": {"alice": "contributor", "bob": "viewer"},
|
|
125
|
-
# "service_users": {"alice-bot": "contributor"},
|
|
124
|
+
# "users": {"alice": "contributor", "bob": "viewer", "carol": "contributor"},
|
|
125
|
+
# "service_users": {"alice-bot": "contributor", "ops-bot": "viewer", "ci-bot": "no-access"},
|
|
126
126
|
# }
|
|
127
127
|
```
|
|
128
128
|
"""
|
|
129
129
|
...
|
|
130
130
|
|
|
131
131
|
async def aio(self, /) -> dict[typing.Literal["users", "service_users"], dict[str, str]]:
|
|
132
|
-
"""
|
|
132
|
+
"""Enumerate the environment roles for each user and service user in the workspace.
|
|
133
133
|
|
|
134
134
|
**Examples:**
|
|
135
135
|
|
|
136
136
|
```python notest
|
|
137
|
-
members = modal.Environment.from_name("my-
|
|
137
|
+
members = modal.Environment.from_name("my-env").members.list()
|
|
138
138
|
print(members)
|
|
139
139
|
# {
|
|
140
|
-
# "users": {"alice": "contributor", "bob": "viewer"},
|
|
141
|
-
# "service_users": {"alice-bot": "contributor"},
|
|
140
|
+
# "users": {"alice": "contributor", "bob": "viewer", "carol": "contributor"},
|
|
141
|
+
# "service_users": {"alice-bot": "contributor", "ops-bot": "viewer", "ci-bot": "no-access"},
|
|
142
142
|
# }
|
|
143
143
|
```
|
|
144
144
|
"""
|
|
@@ -1044,11 +1044,13 @@ class FunctionCall(typing.Generic[modal._functions.ReturnType], modal.object.Obj
|
|
|
1044
1044
|
|
|
1045
1045
|
class __get_call_graph_spec(typing_extensions.Protocol):
|
|
1046
1046
|
def __call__(self, /) -> list[modal.types.InputInfo]:
|
|
1047
|
-
"""
|
|
1048
|
-
call ID, along with the status of execution for each node.
|
|
1047
|
+
"""Fetch information about the graph of Inputs this FunctionCall is part of.
|
|
1049
1048
|
|
|
1050
|
-
|
|
1051
|
-
|
|
1049
|
+
Note: the call graph data is not populated in real-time, and its capture is best-effort.
|
|
1050
|
+
We do not recommend relying on this method for critical use cases.
|
|
1051
|
+
|
|
1052
|
+
See the [`modal.types`](/docs/sdk/py/latest/modal.types) reference for information
|
|
1053
|
+
on the return values.
|
|
1052
1054
|
|
|
1053
1055
|
Returns:
|
|
1054
1056
|
A list of `InputInfo` nodes describing the call graph.
|
|
@@ -1056,11 +1058,13 @@ class FunctionCall(typing.Generic[modal._functions.ReturnType], modal.object.Obj
|
|
|
1056
1058
|
...
|
|
1057
1059
|
|
|
1058
1060
|
async def aio(self, /) -> list[modal.types.InputInfo]:
|
|
1059
|
-
"""
|
|
1060
|
-
|
|
1061
|
+
"""Fetch information about the graph of Inputs this FunctionCall is part of.
|
|
1062
|
+
|
|
1063
|
+
Note: the call graph data is not populated in real-time, and its capture is best-effort.
|
|
1064
|
+
We do not recommend relying on this method for critical use cases.
|
|
1061
1065
|
|
|
1062
|
-
See [`modal.
|
|
1063
|
-
|
|
1066
|
+
See the [`modal.types`](/docs/sdk/py/latest/modal.types) reference for information
|
|
1067
|
+
on the return values.
|
|
1064
1068
|
|
|
1065
1069
|
Returns:
|
|
1066
1070
|
A list of `InputInfo` nodes describing the call graph.
|
|
@@ -1071,26 +1075,22 @@ class FunctionCall(typing.Generic[modal._functions.ReturnType], modal.object.Obj
|
|
|
1071
1075
|
|
|
1072
1076
|
class __cancel_spec(typing_extensions.Protocol):
|
|
1073
1077
|
def __call__(self, /, terminate_containers: bool = False):
|
|
1074
|
-
"""
|
|
1075
|
-
[`TERMINATED`](https://modal.com/docs/sdk/py/latest/modal.call_graph#modalcall_graphinputstatus).
|
|
1076
|
-
|
|
1077
|
-
If `terminate_containers=True` - the containers running the cancelled inputs are all terminated
|
|
1078
|
-
causing any non-cancelled inputs on those containers to be rescheduled in new containers.
|
|
1078
|
+
"""Cancel the FunctionCall and terminate its inputs without retrying.
|
|
1079
1079
|
|
|
1080
1080
|
Args:
|
|
1081
|
-
terminate_containers: If True,
|
|
1081
|
+
terminate_containers: If True, terminate the containers running the cancelled
|
|
1082
|
+
inputs. Any other inputs running concurrently on those containers will be
|
|
1083
|
+
rescheduled.
|
|
1082
1084
|
"""
|
|
1083
1085
|
...
|
|
1084
1086
|
|
|
1085
1087
|
async def aio(self, /, terminate_containers: bool = False):
|
|
1086
|
-
"""
|
|
1087
|
-
[`TERMINATED`](https://modal.com/docs/sdk/py/latest/modal.call_graph#modalcall_graphinputstatus).
|
|
1088
|
-
|
|
1089
|
-
If `terminate_containers=True` - the containers running the cancelled inputs are all terminated
|
|
1090
|
-
causing any non-cancelled inputs on those containers to be rescheduled in new containers.
|
|
1088
|
+
"""Cancel the FunctionCall and terminate its inputs without retrying.
|
|
1091
1089
|
|
|
1092
1090
|
Args:
|
|
1093
|
-
terminate_containers: If True,
|
|
1091
|
+
terminate_containers: If True, terminate the containers running the cancelled
|
|
1092
|
+
inputs. Any other inputs running concurrently on those containers will be
|
|
1093
|
+
rescheduled.
|
|
1094
1094
|
"""
|
|
1095
1095
|
...
|
|
1096
1096
|
|