modal 1.6.2.dev11__tar.gz → 1.6.2.dev13__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.6.2.dev11 → modal-1.6.2.dev13}/PKG-INFO +1 -1
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/app.py +1 -1
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/app.pyi +2 -2
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/cli/dict.py +3 -7
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/cli/function.py +38 -13
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/cli/import_refs.py +57 -6
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/cli/network_file_system.py +2 -4
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/cli/queues.py +3 -7
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/cli/run.py +4 -1
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/cli/secret.py +2 -4
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/cli/server.py +29 -11
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/cli/shell.py +4 -1
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/cli/volume.py +3 -7
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/client.pyi +2 -2
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/config.py +4 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/functions.pyi +6 -6
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal.egg-info/PKG-INFO +1 -1
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal_proto/api_pb2.py +808 -808
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal_proto/api_pb2.pyi +5 -1
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal_version/__init__.py +1 -1
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/LICENSE +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/README.md +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/__init__.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/__main__.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_billing.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_cluster.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_cluster.pyi +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_container_entrypoint.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_environments.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_function_variants.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_functions.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_grpc_client.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_image.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_ipython.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_load_context.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_location.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_logs.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_logs_manager.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_logs_manager.pyi +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_metrics.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_metrics.pyi +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_object.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_outbound_policy.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_outbound_policy.pyi +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_output/__init__.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_output/manager.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_output/pty.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_output/rich.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_output/status.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_partial_function.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_resolver.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_resources.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_runtime/__init__.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_runtime/asgi.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_runtime/container_io_manager.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_runtime/container_io_manager.pyi +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_runtime/execution_context.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_runtime/execution_context.pyi +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_runtime/gpu_memory_snapshot.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_runtime/task_lifecycle_manager.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_runtime/task_lifecycle_manager.pyi +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_runtime/telemetry.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_runtime/user_code_event_loop.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_runtime/user_code_imports.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_serialization.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_server.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_server.pyi +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_supports_logs.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_traceback.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_tunnel.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_tunnel.pyi +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_type_manager.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_utils/__init__.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_utils/app_utils.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_utils/async_utils.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_utils/auth_token_manager.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_utils/blob_utils.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_utils/browser_utils.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_utils/bytes_io_segment_payload.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_utils/curl_utils.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_utils/deprecation.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_utils/display_utils.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_utils/docker_utils.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_utils/function_utils.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_utils/git_utils.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_utils/grpc_testing.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_utils/grpc_utils.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_utils/hash_utils.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_utils/http_utils.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_utils/idle_countdown.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_utils/jwt_utils.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_utils/logger.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_utils/mount_utils.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_utils/name_utils.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_utils/package_utils.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_utils/pattern_utils.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_utils/proxy_support.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_utils/rand_pb_testing.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_utils/sandbox_fs_utils.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_utils/shell_utils.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_utils/time_utils.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_vendor/__init__.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_vendor/a2wsgi_wsgi.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_vendor/cloudpickle.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_vendor/tblib.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_vendor/version.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_watcher.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/_workspace.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/billing.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/billing.pyi +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/builder/2023.12.312.txt +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/builder/2023.12.txt +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/builder/2024.04.txt +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/builder/2024.10.txt +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/builder/2025.06.txt +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/builder/PREVIEW.txt +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/builder/README.md +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/builder/base-images.json +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/call_graph.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/cli/__init__.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/cli/_download.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/cli/_help.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/cli/_logs.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/cli/_stats.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/cli/_traceback.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/cli/app.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/cli/billing.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/cli/changelog.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/cli/config.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/cli/container.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/cli/curl.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/cli/dashboard.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/cli/endpoint.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/cli/entry_point.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/cli/environment.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/cli/image.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/cli/logo.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/cli/profile.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/cli/selector.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/cli/skills.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/cli/token.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/cli/utils.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/cli/workspace.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/client.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/cloud_bucket_mount.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/cloud_bucket_mount.pyi +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/cls.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/cls.pyi +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/cluster.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/cluster.pyi +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/container_process.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/container_process.pyi +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/dict.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/dict.pyi +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/environments.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/environments.pyi +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/exception.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/experimental/__init__.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/experimental/_flash_container_entry.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/experimental/flash.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/experimental/flash.pyi +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/experimental/flash_server.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/experimental/flash_server.pyi +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/experimental/ipython.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/file_pattern_matcher.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/functions.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/image.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/image.pyi +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/io_streams.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/io_streams.pyi +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/mount.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/mount.pyi +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/network_file_system.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/network_file_system.pyi +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/object.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/object.pyi +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/output.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/parallel_map.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/parallel_map.pyi +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/partial_function.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/partial_function.pyi +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/proxy.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/proxy.pyi +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/py.typed +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/queue.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/queue.pyi +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/retries.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/runner.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/runner.pyi +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/running_app.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/sandbox/__init__.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/sandbox/_common.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/sandbox/_filesystem.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/sandbox/_sandbox.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/sandbox/_sidecar.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/sandbox/_snapshot.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/sandbox/_task_command_router_client.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/sandbox/sandbox.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/sandbox/sandbox.pyi +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/schedule.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/scheduler_placement.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/secret.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/secret.pyi +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/server.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/server.pyi +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/serving.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/serving.pyi +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/skills/modal/SKILL.md +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/stream_type.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/token_flow.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/token_flow.pyi +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/types.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/volume.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/volume.pyi +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/workspace.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal/workspace.pyi +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal.egg-info/SOURCES.txt +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal.egg-info/dependency_links.txt +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal.egg-info/entry_points.txt +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal.egg-info/requires.txt +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal.egg-info/top_level.txt +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal_docs/__init__.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal_docs/gen_cli_docs.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal_docs/gen_cli_docs_main.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal_docs/gen_reference_docs.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal_docs/gen_reference_docs_main.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal_docs/mdmd/__init__.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal_docs/mdmd/mdmd.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal_docs/mdmd/signatures.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal_docs/mdmd/types.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal_docs/reference_intro.md +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal_proto/__init__.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal_proto/api_grpc.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal_proto/api_pb2_grpc.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal_proto/api_pb2_grpc.pyi +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal_proto/modal_api_grpc.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal_proto/py.typed +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal_proto/task_command_router_grpc.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal_proto/task_command_router_pb2.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal_proto/task_command_router_pb2.pyi +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal_proto/task_command_router_pb2_grpc.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal_proto/task_command_router_pb2_grpc.pyi +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/modal_version/__main__.py +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/pyproject.toml +0 -0
- {modal-1.6.2.dev11 → modal-1.6.2.dev13}/setup.cfg +0 -0
|
@@ -1358,7 +1358,7 @@ class _App:
|
|
|
1358
1358
|
fractional, e.g. 1.5 to target three concurrent requests per two containers.
|
|
1359
1359
|
max_concurrency:
|
|
1360
1360
|
Maximum number of concurrent requests per container. Requests above this limit
|
|
1361
|
-
receive a
|
|
1361
|
+
receive a 429 response. If set to 0 or unset, request concurrency is unlimited.
|
|
1362
1362
|
min_containers: Minimum number of containers to keep running regardless of demand.
|
|
1363
1363
|
max_containers: Limit on the number of containers that can be concurrently running.
|
|
1364
1364
|
buffer_containers: Extra containers to scale up beyond current demand.
|
|
@@ -799,7 +799,7 @@ class _App:
|
|
|
799
799
|
fractional, e.g. 1.5 to target three concurrent requests per two containers.
|
|
800
800
|
max_concurrency:
|
|
801
801
|
Maximum number of concurrent requests per container. Requests above this limit
|
|
802
|
-
receive a
|
|
802
|
+
receive a 429 response. If set to 0 or unset, request concurrency is unlimited.
|
|
803
803
|
min_containers: Minimum number of containers to keep running regardless of demand.
|
|
804
804
|
max_containers: Limit on the number of containers that can be concurrently running.
|
|
805
805
|
buffer_containers: Extra containers to scale up beyond current demand.
|
|
@@ -1837,7 +1837,7 @@ class App:
|
|
|
1837
1837
|
fractional, e.g. 1.5 to target three concurrent requests per two containers.
|
|
1838
1838
|
max_concurrency:
|
|
1839
1839
|
Maximum number of concurrent requests per container. Requests above this limit
|
|
1840
|
-
receive a
|
|
1840
|
+
receive a 429 response. If set to 0 or unset, request concurrency is unlimited.
|
|
1841
1841
|
min_containers: Minimum number of containers to keep running regardless of demand.
|
|
1842
1842
|
max_containers: Limit on the number of containers that can be concurrently running.
|
|
1843
1843
|
buffer_containers: Extra containers to scale up beyond current demand.
|
|
@@ -8,7 +8,7 @@ from modal._load_context import LoadContext
|
|
|
8
8
|
from modal._resolver import Resolver
|
|
9
9
|
from modal._utils.async_utils import TaskContext, synchronizer
|
|
10
10
|
from modal._utils.time_utils import timestamp_to_localized_str
|
|
11
|
-
from modal.cli.utils import display_table, env_option, yes_option
|
|
11
|
+
from modal.cli.utils import confirm_or_suggest_yes, display_table, env_option, yes_option
|
|
12
12
|
from modal.client import _Client
|
|
13
13
|
from modal.dict import _Dict
|
|
14
14
|
from modal.output import OutputManager
|
|
@@ -64,10 +64,8 @@ async def clear(name: str, *, yes: bool = False, env: str | None = None):
|
|
|
64
64
|
"""Clear the contents of a named Dict by deleting all of its data."""
|
|
65
65
|
d = _Dict.from_name(name, environment_name=env)
|
|
66
66
|
if not yes:
|
|
67
|
-
|
|
67
|
+
confirm_or_suggest_yes(
|
|
68
68
|
f"Are you sure you want to irrevocably delete the contents of modal.Dict '{name}'?",
|
|
69
|
-
default=False,
|
|
70
|
-
abort=True,
|
|
71
69
|
)
|
|
72
70
|
await d.clear()
|
|
73
71
|
|
|
@@ -87,10 +85,8 @@ async def delete(
|
|
|
87
85
|
):
|
|
88
86
|
"""Delete a named Dict and all of its data."""
|
|
89
87
|
if not yes:
|
|
90
|
-
|
|
88
|
+
confirm_or_suggest_yes(
|
|
91
89
|
f"Are you sure you want to irrevocably delete the modal.Dict '{name}'?",
|
|
92
|
-
default=False,
|
|
93
|
-
abort=True,
|
|
94
90
|
)
|
|
95
91
|
await _Dict.objects.delete(name, environment_name=env, allow_missing=allow_missing)
|
|
96
92
|
|
|
@@ -7,7 +7,8 @@ from typing import Any, AsyncGenerator, Sequence, cast
|
|
|
7
7
|
|
|
8
8
|
import click
|
|
9
9
|
from click import UsageError
|
|
10
|
-
from rich.box import SIMPLE
|
|
10
|
+
from rich.box import SIMPLE, SIMPLE_HEAD
|
|
11
|
+
from rich.style import Style
|
|
11
12
|
from rich.table import Column, Table
|
|
12
13
|
from rich.text import Text
|
|
13
14
|
|
|
@@ -212,18 +213,20 @@ async def info(
|
|
|
212
213
|
enabled = "Enabled"
|
|
213
214
|
disabled = "Disabled"
|
|
214
215
|
|
|
215
|
-
rows: list[str | Text | tuple[str | Text, str | Text]] = []
|
|
216
|
+
rows: list[str | Text | tuple[str | Text, str | Text] | None] = []
|
|
216
217
|
|
|
217
218
|
if function_proto.is_class:
|
|
218
|
-
rows.append(("Cls Name:", function_proto.function_name))
|
|
219
|
+
rows.append((Text("Cls Name:", style="bold"), function_proto.function_name))
|
|
219
220
|
else:
|
|
220
|
-
rows.append(("Function Name:", function_proto.function_name))
|
|
221
|
+
rows.append((Text("Function Name:", style="bold"), function_proto.function_name))
|
|
221
222
|
|
|
222
|
-
rows.append(
|
|
223
|
-
rows.append(("
|
|
224
|
-
rows.append(("
|
|
223
|
+
rows.append(None)
|
|
224
|
+
rows.append((Text("Object ID:", style="bold"), f.object_id))
|
|
225
|
+
rows.append((Text("App ID:", style="bold"), handle_metadata.app_id))
|
|
226
|
+
rows.append((Text("Image ID:", style="bold"), str(info.image_info.image_id)))
|
|
225
227
|
|
|
226
228
|
# --- Resources ---
|
|
229
|
+
rows.append(None)
|
|
227
230
|
rows.append("Resources:")
|
|
228
231
|
rows.append(
|
|
229
232
|
(
|
|
@@ -261,6 +264,7 @@ async def info(
|
|
|
261
264
|
)
|
|
262
265
|
|
|
263
266
|
# --- Autoscaling ---
|
|
267
|
+
rows.append(None)
|
|
264
268
|
rows.append("Autoscaling:")
|
|
265
269
|
rows.append(
|
|
266
270
|
(
|
|
@@ -289,6 +293,7 @@ async def info(
|
|
|
289
293
|
)
|
|
290
294
|
)
|
|
291
295
|
|
|
296
|
+
rows.append(None)
|
|
292
297
|
rows.append("Execution:")
|
|
293
298
|
if info.startup_timeout:
|
|
294
299
|
rows.append((" Startup Timeout:", f"{info.startup_timeout} seconds"))
|
|
@@ -297,6 +302,7 @@ async def info(
|
|
|
297
302
|
rows.append((" Max Retries:", not_configured if info.max_retries is None else str(info.max_retries)))
|
|
298
303
|
|
|
299
304
|
if info.concurrency_info:
|
|
305
|
+
rows.append(None)
|
|
300
306
|
rows.append("Concurrency:")
|
|
301
307
|
rows.append((" Max Inputs:", str(info.concurrency_info.max_inputs)))
|
|
302
308
|
rows.append(
|
|
@@ -309,11 +315,13 @@ async def info(
|
|
|
309
315
|
)
|
|
310
316
|
|
|
311
317
|
if info.batching_info:
|
|
318
|
+
rows.append(None)
|
|
312
319
|
rows.append("Batching:")
|
|
313
320
|
rows.append((" Max Batch Size:", str(info.batching_info.max_batch_size)))
|
|
314
321
|
rows.append((" Wait Time:", f"{info.batching_info.wait_ms} milliseconds"))
|
|
315
322
|
|
|
316
323
|
# --- Scheduling ---
|
|
324
|
+
rows.append(None)
|
|
317
325
|
rows.append("Scheduling:")
|
|
318
326
|
rows.append((" Compute Region(s):", not_configured if not info.regions else " | ".join(info.regions)))
|
|
319
327
|
rows.append((" Nonpreemptible Capacity:", not_configured if not info.nonpreemptible else enabled))
|
|
@@ -322,6 +330,7 @@ async def info(
|
|
|
322
330
|
rows.append((" Routing Region:", not_configured if not info.routing_region else info.routing_region))
|
|
323
331
|
|
|
324
332
|
if info.cluster_info:
|
|
333
|
+
rows.append(None)
|
|
325
334
|
rows.append("Clustering:")
|
|
326
335
|
rows.append((" Cluster Size:", str(info.cluster_info.size)))
|
|
327
336
|
rows.append((" RDMA:", enabled if info.cluster_info.rdma else disabled))
|
|
@@ -329,8 +338,10 @@ async def info(
|
|
|
329
338
|
rows.append((" Fabric Size:", str(info.cluster_info.fabric_size)))
|
|
330
339
|
|
|
331
340
|
if info.schedule is not None:
|
|
341
|
+
rows.append(None)
|
|
332
342
|
rows.append(("Schedule:", info.schedule))
|
|
333
343
|
|
|
344
|
+
rows.append(None)
|
|
334
345
|
rows.append("Security:")
|
|
335
346
|
rows.append((" Outbound Networking:", disabled if info.block_network else enabled))
|
|
336
347
|
rows.append((" Modal API Access:", disabled if info.restrict_modal_access else enabled))
|
|
@@ -338,6 +349,7 @@ async def info(
|
|
|
338
349
|
|
|
339
350
|
# --- Web Functions ---
|
|
340
351
|
if info.web_info is not None:
|
|
352
|
+
rows.append(None)
|
|
341
353
|
rows.append("Web Info:")
|
|
342
354
|
|
|
343
355
|
if info.web_info.web_url:
|
|
@@ -345,7 +357,9 @@ async def info(
|
|
|
345
357
|
if info.web_info.method:
|
|
346
358
|
url_str = f" URL ({info.web_info.method}):"
|
|
347
359
|
|
|
348
|
-
|
|
360
|
+
url_text = Text(info.web_info.web_url, overflow="fold")
|
|
361
|
+
url_text.stylize(style=Style(link=info.web_info.web_url), end=len(info.web_info.web_url))
|
|
362
|
+
rows.append((url_str, url_text))
|
|
349
363
|
|
|
350
364
|
rows.append((" Authentication:", disabled if info.web_info.unauthenticated else enabled))
|
|
351
365
|
|
|
@@ -353,6 +367,7 @@ async def info(
|
|
|
353
367
|
if info.method_names is not None:
|
|
354
368
|
assert info.method_details is not None
|
|
355
369
|
|
|
370
|
+
rows.append(None)
|
|
356
371
|
rows.append("Methods:")
|
|
357
372
|
|
|
358
373
|
for method_name in info.method_names:
|
|
@@ -368,10 +383,14 @@ async def info(
|
|
|
368
383
|
if web_info.method:
|
|
369
384
|
url_str = f" URL ({web_info.method}):"
|
|
370
385
|
|
|
371
|
-
|
|
386
|
+
url_text = Text(web_info.web_url, overflow="fold")
|
|
387
|
+
url_text.stylize(style=Style(link=web_info.web_url), end=len(web_info.web_url))
|
|
388
|
+
|
|
389
|
+
rows.append((url_str, url_text))
|
|
372
390
|
|
|
373
391
|
# --- Mounts ---
|
|
374
392
|
if info.volumes:
|
|
393
|
+
rows.append(None)
|
|
375
394
|
rows.append("Volume Mounts:")
|
|
376
395
|
for mount_path, volume in info.volumes.items():
|
|
377
396
|
assert volume.volume_id is not None
|
|
@@ -390,6 +409,7 @@ async def info(
|
|
|
390
409
|
rows.append((f" {mount_path}", volume_text))
|
|
391
410
|
|
|
392
411
|
if info.cloud_bucket_mounts:
|
|
412
|
+
rows.append(None)
|
|
393
413
|
rows.append("Cloud Bucket Mounts:")
|
|
394
414
|
for mount_path, cbm in info.cloud_bucket_mounts.items():
|
|
395
415
|
extra = []
|
|
@@ -407,6 +427,7 @@ async def info(
|
|
|
407
427
|
|
|
408
428
|
# --- Secrets ---
|
|
409
429
|
if info.secrets:
|
|
430
|
+
rows.append(None)
|
|
410
431
|
rows.append("Secrets:")
|
|
411
432
|
|
|
412
433
|
async def _hydrate(secret_id: str) -> tuple[str, _Secret | None]:
|
|
@@ -446,18 +467,20 @@ async def info(
|
|
|
446
467
|
|
|
447
468
|
rows.append((f" {secret_identifier}", ", ".join(display_keys)))
|
|
448
469
|
|
|
470
|
+
t = Table(box=SIMPLE_HEAD, show_header=False)
|
|
449
471
|
for row in rows:
|
|
450
|
-
|
|
472
|
+
if row is None:
|
|
473
|
+
t.add_row()
|
|
474
|
+
continue
|
|
451
475
|
|
|
452
476
|
if not isinstance(row, tuple):
|
|
453
477
|
if isinstance(row, str):
|
|
454
|
-
row = Text(row)
|
|
478
|
+
row = Text(row, style="bold")
|
|
455
479
|
|
|
456
480
|
if not tty:
|
|
457
481
|
output_manager.print(row)
|
|
458
482
|
else:
|
|
459
483
|
t.add_row(row)
|
|
460
|
-
output_manager.print(t)
|
|
461
484
|
|
|
462
485
|
continue
|
|
463
486
|
|
|
@@ -470,9 +493,11 @@ async def info(
|
|
|
470
493
|
if isinstance(left, str):
|
|
471
494
|
left = Text(left, overflow="fold")
|
|
472
495
|
if isinstance(right, str):
|
|
473
|
-
right = Text(right, overflow="fold"
|
|
496
|
+
right = Text(right, overflow="fold")
|
|
474
497
|
|
|
475
498
|
t.add_row(left, right)
|
|
499
|
+
|
|
500
|
+
if tty:
|
|
476
501
|
output_manager.print(t)
|
|
477
502
|
|
|
478
503
|
|
|
@@ -15,6 +15,7 @@ import inspect
|
|
|
15
15
|
import shutil
|
|
16
16
|
import sys
|
|
17
17
|
import tempfile
|
|
18
|
+
import types
|
|
18
19
|
import typing
|
|
19
20
|
from collections import defaultdict
|
|
20
21
|
from dataclasses import dataclass
|
|
@@ -177,6 +178,41 @@ class AutoRunPriority:
|
|
|
177
178
|
APP_FUNCTION = 3
|
|
178
179
|
|
|
179
180
|
|
|
181
|
+
_LazyImportType = getattr(types, "LazyImportType", None) # Python 3.15+ (PEP 810)
|
|
182
|
+
|
|
183
|
+
_MAX_LISTED_LAZY_IMPORTS = 10
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def _is_lazy_import(module: types.ModuleType, name: str) -> bool:
|
|
187
|
+
return _LazyImportType is not None and isinstance(vars(module).get(name), _LazyImportType)
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def _check_not_lazy_import(module: types.ModuleType, name: str, import_ref: ImportRef) -> None:
|
|
191
|
+
if _is_lazy_import(module, name):
|
|
192
|
+
raise InvalidError(
|
|
193
|
+
f"'{name}' is imported lazily in '{import_ref.file_or_module}'. Modal Apps, Functions, and Classes "
|
|
194
|
+
"can't be imported lazily; change it to a regular import."
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def _get_module_members(module: types.ModuleType) -> tuple[dict[str, typing.Any], list[str]]:
|
|
199
|
+
"""Like `dict(inspect.getmembers(module))`, but skips lazy imports instead of resolving them.
|
|
200
|
+
|
|
201
|
+
Returns the members and the names of the skipped lazy imports.
|
|
202
|
+
"""
|
|
203
|
+
members = {}
|
|
204
|
+
lazy_imports = []
|
|
205
|
+
for name in dir(module):
|
|
206
|
+
if _is_lazy_import(module, name):
|
|
207
|
+
lazy_imports.append(name)
|
|
208
|
+
continue
|
|
209
|
+
try:
|
|
210
|
+
members[name] = getattr(module, name)
|
|
211
|
+
except AttributeError:
|
|
212
|
+
continue # matches inspect.getmembers
|
|
213
|
+
return members, lazy_imports
|
|
214
|
+
|
|
215
|
+
|
|
180
216
|
def list_cli_commands(
|
|
181
217
|
module_members: dict[str, typing.Any],
|
|
182
218
|
include_service_functions: bool = False,
|
|
@@ -308,6 +344,7 @@ def import_app_from_ref(import_ref: ImportRef, base_cmd: str = "") -> App:
|
|
|
308
344
|
if "." in object_path:
|
|
309
345
|
raise click.UsageError(f"{object_path} is not a Modal App")
|
|
310
346
|
|
|
347
|
+
_check_not_lazy_import(module, object_path, import_ref)
|
|
311
348
|
app = getattr(module, object_path)
|
|
312
349
|
|
|
313
350
|
if app is None:
|
|
@@ -385,9 +422,9 @@ def import_and_filter(
|
|
|
385
422
|
accept_webhook=False,
|
|
386
423
|
accept_service_functions=False,
|
|
387
424
|
allow_stdin=False,
|
|
388
|
-
) -> tuple[Runnable | None, list[CLICommand]]:
|
|
389
|
-
"""Takes a function ref string and returns a single determined "runnable" to use,
|
|
390
|
-
runnables.
|
|
425
|
+
) -> tuple[Runnable | None, list[CLICommand], list[str]]:
|
|
426
|
+
"""Takes a function ref string and returns a single determined "runnable" to use, a list of all available
|
|
427
|
+
runnables, and the names of the lazy imports that were not searched for runnables.
|
|
391
428
|
|
|
392
429
|
The function ref can leave out partial information (apart from the file name/module)
|
|
393
430
|
as long as the runnable is uniquely identifiable by the provided information.
|
|
@@ -401,8 +438,10 @@ def import_and_filter(
|
|
|
401
438
|
"""
|
|
402
439
|
# all commands:
|
|
403
440
|
module = import_file_or_module(import_ref, base_cmd, allow_stdin=allow_stdin)
|
|
441
|
+
_check_not_lazy_import(module, import_ref.object_path.split(".", 1)[0], import_ref)
|
|
442
|
+
module_members, lazy_imports = _get_module_members(module)
|
|
404
443
|
cli_commands = list_cli_commands(
|
|
405
|
-
|
|
444
|
+
module_members,
|
|
406
445
|
include_service_functions=accept_service_functions,
|
|
407
446
|
)
|
|
408
447
|
|
|
@@ -413,10 +452,22 @@ def import_and_filter(
|
|
|
413
452
|
|
|
414
453
|
if inferred_runnable:
|
|
415
454
|
# if there is a single command with "highest run prio" - use that
|
|
416
|
-
return inferred_runnable, all_usable_commands
|
|
455
|
+
return inferred_runnable, all_usable_commands, lazy_imports
|
|
417
456
|
|
|
418
457
|
# otherwise, just return the list of all commands
|
|
419
|
-
return None, all_usable_commands
|
|
458
|
+
return None, all_usable_commands, lazy_imports
|
|
459
|
+
|
|
460
|
+
|
|
461
|
+
def format_lazy_imports_note(lazy_imports: list[str], found_commands: bool) -> str:
|
|
462
|
+
if found_commands or not lazy_imports:
|
|
463
|
+
return ""
|
|
464
|
+
details = "\n".join(f" {name}" for name in lazy_imports[:_MAX_LISTED_LAZY_IMPORTS])
|
|
465
|
+
if len(lazy_imports) > _MAX_LISTED_LAZY_IMPORTS:
|
|
466
|
+
details += f"\n ... and {len(lazy_imports) - _MAX_LISTED_LAZY_IMPORTS} more"
|
|
467
|
+
return (
|
|
468
|
+
"\n\nNote: Modal does not look inside lazy imports, and Modal Apps, Functions, and Classes can't be "
|
|
469
|
+
f"imported lazily. If one of these is a Modal object, change it to a regular import:\n{details}"
|
|
470
|
+
)
|
|
420
471
|
|
|
421
472
|
|
|
422
473
|
def infer_runnable(
|
|
@@ -14,7 +14,7 @@ from modal._location import display_location
|
|
|
14
14
|
from modal._utils.async_utils import synchronizer
|
|
15
15
|
from modal._utils.time_utils import timestamp_to_localized_str
|
|
16
16
|
from modal.cli._download import _volume_download
|
|
17
|
-
from modal.cli.utils import display_table, env_option, yes_option
|
|
17
|
+
from modal.cli.utils import confirm_or_suggest_yes, display_table, env_option, yes_option
|
|
18
18
|
from modal.client import _Client
|
|
19
19
|
from modal.network_file_system import _NetworkFileSystem
|
|
20
20
|
from modal.output import OutputManager
|
|
@@ -86,10 +86,8 @@ async def delete(
|
|
|
86
86
|
# Lookup first to validate the name, even though delete is a staticmethod
|
|
87
87
|
await _NetworkFileSystem.from_name(nfs_name, environment_name=env).hydrate()
|
|
88
88
|
if not yes:
|
|
89
|
-
|
|
89
|
+
confirm_or_suggest_yes(
|
|
90
90
|
f"Are you sure you want to irrevocably delete the modal.NetworkFileSystem '{nfs_name}'?",
|
|
91
|
-
default=False,
|
|
92
|
-
abort=True,
|
|
93
91
|
)
|
|
94
92
|
|
|
95
93
|
await _NetworkFileSystem.delete(nfs_name, environment_name=env)
|
|
@@ -8,7 +8,7 @@ from modal._load_context import LoadContext
|
|
|
8
8
|
from modal._resolver import Resolver
|
|
9
9
|
from modal._utils.async_utils import TaskContext, synchronizer
|
|
10
10
|
from modal._utils.time_utils import timestamp_to_localized_str
|
|
11
|
-
from modal.cli.utils import display_table, env_option, yes_option
|
|
11
|
+
from modal.cli.utils import confirm_or_suggest_yes, display_table, env_option, yes_option
|
|
12
12
|
from modal.client import _Client
|
|
13
13
|
from modal.output import OutputManager
|
|
14
14
|
from modal.queue import _Queue
|
|
@@ -127,10 +127,8 @@ async def clear(
|
|
|
127
127
|
"""Clear the contents of a Queue by removing all of its data."""
|
|
128
128
|
q = _Queue.from_name(name, environment_name=env)
|
|
129
129
|
if not yes:
|
|
130
|
-
|
|
130
|
+
confirm_or_suggest_yes(
|
|
131
131
|
f"Are you sure you want to irrevocably delete the contents of modal.Queue '{name}'?",
|
|
132
|
-
default=False,
|
|
133
|
-
abort=True,
|
|
134
132
|
)
|
|
135
133
|
await q.clear(partition=partition, all=all)
|
|
136
134
|
|
|
@@ -151,10 +149,8 @@ async def delete(
|
|
|
151
149
|
"""Delete a named Queue and all of its data."""
|
|
152
150
|
env = ensure_env(env)
|
|
153
151
|
if not yes:
|
|
154
|
-
|
|
152
|
+
confirm_or_suggest_yes(
|
|
155
153
|
f"Are you sure you want to irrevocably delete the modal.Queue '{name}'?",
|
|
156
|
-
default=False,
|
|
157
|
-
abort=True,
|
|
158
154
|
)
|
|
159
155
|
await _Queue.objects.delete(name, environment_name=env, allow_missing=allow_missing)
|
|
160
156
|
|
|
@@ -31,6 +31,7 @@ from .import_refs import (
|
|
|
31
31
|
CLICommand,
|
|
32
32
|
MethodReference,
|
|
33
33
|
_get_runnable_app,
|
|
34
|
+
format_lazy_imports_note,
|
|
34
35
|
import_and_filter,
|
|
35
36
|
import_app_from_ref,
|
|
36
37
|
parse_import_ref,
|
|
@@ -472,7 +473,7 @@ class RunGroup(ModalGroup):
|
|
|
472
473
|
from_stdin = import_ref.file_or_module == STDIN_REF
|
|
473
474
|
if from_stdin and ctx.params["interactive"]:
|
|
474
475
|
raise ClickException("Interactive mode can't be used when reading a script from stdin.")
|
|
475
|
-
runnable, all_usable_commands = import_and_filter(
|
|
476
|
+
runnable, all_usable_commands, lazy_imports = import_and_filter(
|
|
476
477
|
import_ref, base_cmd="modal run", accept_local_entrypoint=True, accept_webhook=False, allow_stdin=True
|
|
477
478
|
)
|
|
478
479
|
if not runnable and from_stdin:
|
|
@@ -498,6 +499,8 @@ class RunGroup(ModalGroup):
|
|
|
498
499
|
else:
|
|
499
500
|
help_footer = f"'{import_ref.file_or_module}' has no functions or local entrypoints."
|
|
500
501
|
|
|
502
|
+
help_footer += format_lazy_imports_note(lazy_imports, found_commands=bool(all_usable_commands))
|
|
503
|
+
|
|
501
504
|
raise ClickException(f"{help_header}\n\n{help_footer}")
|
|
502
505
|
|
|
503
506
|
app = _get_runnable_app(runnable)
|
|
@@ -13,7 +13,7 @@ from rich.syntax import Syntax
|
|
|
13
13
|
from modal._environments import ensure_env
|
|
14
14
|
from modal._utils.async_utils import synchronizer
|
|
15
15
|
from modal._utils.time_utils import timestamp_to_localized_str
|
|
16
|
-
from modal.cli.utils import display_table, env_option, yes_option
|
|
16
|
+
from modal.cli.utils import confirm_or_suggest_yes, display_table, env_option, yes_option
|
|
17
17
|
from modal.client import _Client
|
|
18
18
|
from modal.output import OutputManager
|
|
19
19
|
from modal.secret import _Secret
|
|
@@ -194,10 +194,8 @@ async def delete(
|
|
|
194
194
|
):
|
|
195
195
|
env = ensure_env(env)
|
|
196
196
|
if not yes:
|
|
197
|
-
|
|
197
|
+
confirm_or_suggest_yes(
|
|
198
198
|
f"Are you sure you want to irrevocably delete the modal.Secret '{name}'?",
|
|
199
|
-
default=False,
|
|
200
|
-
abort=True,
|
|
201
199
|
)
|
|
202
200
|
await _Secret.objects.delete(name, environment_name=env, allow_missing=allow_missing)
|
|
203
201
|
|
|
@@ -9,7 +9,8 @@ from typing import AsyncGenerator, Sequence, cast
|
|
|
9
9
|
|
|
10
10
|
import click
|
|
11
11
|
from click import UsageError
|
|
12
|
-
from rich.box import SIMPLE
|
|
12
|
+
from rich.box import SIMPLE, SIMPLE_HEAD
|
|
13
|
+
from rich.style import Style
|
|
13
14
|
from rich.table import Column, Table
|
|
14
15
|
from rich.text import Text
|
|
15
16
|
|
|
@@ -174,16 +175,22 @@ async def info(
|
|
|
174
175
|
enabled = "Enabled"
|
|
175
176
|
disabled = "Disabled"
|
|
176
177
|
|
|
177
|
-
rows: list[str | Text | tuple[str | Text, str | Text]] = []
|
|
178
|
+
rows: list[str | Text | tuple[str | Text, str | Text] | None] = []
|
|
178
179
|
|
|
179
|
-
rows.append(("Server Name:", handle_metadata.function_name))
|
|
180
|
-
rows.append(
|
|
181
|
-
rows.append(("
|
|
182
|
-
rows.append(("
|
|
180
|
+
rows.append((Text("Server Name:", style="bold"), handle_metadata.function_name))
|
|
181
|
+
rows.append(None)
|
|
182
|
+
rows.append((Text("Object ID:", style="bold"), server_id))
|
|
183
|
+
rows.append((Text("App ID:", style="bold"), handle_metadata.app_id))
|
|
184
|
+
rows.append((Text("Image ID:", style="bold"), str(info.image_info.image_id)))
|
|
183
185
|
|
|
184
186
|
# --- HTTP ---
|
|
187
|
+
rows.append(None)
|
|
185
188
|
rows.append("HTTP Info:")
|
|
186
|
-
|
|
189
|
+
|
|
190
|
+
url = Text(info.server_url, overflow="fold")
|
|
191
|
+
url.stylize(style=Style(link=info.server_url), end=len(info.server_url))
|
|
192
|
+
|
|
193
|
+
rows.append((" URL:", url))
|
|
187
194
|
rows.append((" Port:", not_configured if not info.port else str(info.port)))
|
|
188
195
|
rows.append((" Authentication:", disabled if info.unauthenticated else enabled))
|
|
189
196
|
rows.append((" HTTP/2:", disabled if not info.h2_enabled else enabled))
|
|
@@ -193,6 +200,7 @@ async def info(
|
|
|
193
200
|
rows.append((" Exit Grace Period:", f"{info.exit_grace_period} seconds"))
|
|
194
201
|
|
|
195
202
|
# --- Resources ---
|
|
203
|
+
rows.append(None)
|
|
196
204
|
rows.append("Resources:")
|
|
197
205
|
rows.append(
|
|
198
206
|
(
|
|
@@ -230,6 +238,7 @@ async def info(
|
|
|
230
238
|
)
|
|
231
239
|
|
|
232
240
|
# --- Autoscaling ---
|
|
241
|
+
rows.append(None)
|
|
233
242
|
rows.append("Autoscaling:")
|
|
234
243
|
rows.append(
|
|
235
244
|
(
|
|
@@ -276,6 +285,7 @@ async def info(
|
|
|
276
285
|
)
|
|
277
286
|
|
|
278
287
|
# --- Scheduling ---
|
|
288
|
+
rows.append(None)
|
|
279
289
|
rows.append("Scheduling:")
|
|
280
290
|
rows.append(
|
|
281
291
|
(" Compute Region(s):", not_configured if not info.compute_regions else " | ".join(info.compute_regions))
|
|
@@ -285,6 +295,7 @@ async def info(
|
|
|
285
295
|
rows.append((" Cloud Provider:", info.cloud))
|
|
286
296
|
|
|
287
297
|
if info.cluster_info:
|
|
298
|
+
rows.append(None)
|
|
288
299
|
rows.append("Clustering:")
|
|
289
300
|
rows.append((" Cluster Size:", str(info.cluster_info.size)))
|
|
290
301
|
rows.append((" RDMA:", enabled if info.cluster_info.rdma else disabled))
|
|
@@ -293,6 +304,7 @@ async def info(
|
|
|
293
304
|
|
|
294
305
|
# --- Mounts ---
|
|
295
306
|
if info.volumes:
|
|
307
|
+
rows.append(None)
|
|
296
308
|
rows.append("Volume Mounts:")
|
|
297
309
|
for mount_path, volume in info.volumes.items():
|
|
298
310
|
assert volume.volume_id is not None
|
|
@@ -311,6 +323,7 @@ async def info(
|
|
|
311
323
|
rows.append((f" {mount_path}", volume_text))
|
|
312
324
|
|
|
313
325
|
if info.cloud_bucket_mounts:
|
|
326
|
+
rows.append(None)
|
|
314
327
|
rows.append("Cloud Bucket Mounts:")
|
|
315
328
|
for mount_path, cbm in info.cloud_bucket_mounts.items():
|
|
316
329
|
extra = []
|
|
@@ -328,6 +341,7 @@ async def info(
|
|
|
328
341
|
|
|
329
342
|
# --- Secrets ---
|
|
330
343
|
if info.secrets:
|
|
344
|
+
rows.append(None)
|
|
331
345
|
rows.append("Secrets:")
|
|
332
346
|
|
|
333
347
|
async def _hydrate(secret_id: str) -> tuple[str, _Secret | None]:
|
|
@@ -367,18 +381,20 @@ async def info(
|
|
|
367
381
|
|
|
368
382
|
rows.append((f" {secret_identifier}", ", ".join(display_keys)))
|
|
369
383
|
|
|
384
|
+
t = Table(box=SIMPLE_HEAD, show_header=False)
|
|
370
385
|
for row in rows:
|
|
371
|
-
|
|
386
|
+
if row is None:
|
|
387
|
+
t.add_row()
|
|
388
|
+
continue
|
|
372
389
|
|
|
373
390
|
if not isinstance(row, tuple):
|
|
374
391
|
if isinstance(row, str):
|
|
375
|
-
row = Text(row)
|
|
392
|
+
row = Text(row, style="bold")
|
|
376
393
|
|
|
377
394
|
if not tty:
|
|
378
395
|
output_manager.print(row)
|
|
379
396
|
else:
|
|
380
397
|
t.add_row(row)
|
|
381
|
-
output_manager.print(t)
|
|
382
398
|
|
|
383
399
|
continue
|
|
384
400
|
|
|
@@ -391,9 +407,11 @@ async def info(
|
|
|
391
407
|
if isinstance(left, str):
|
|
392
408
|
left = Text(left, overflow="fold")
|
|
393
409
|
if isinstance(right, str):
|
|
394
|
-
right = Text(right, overflow="fold"
|
|
410
|
+
right = Text(right, overflow="fold")
|
|
395
411
|
|
|
396
412
|
t.add_row(left, right)
|
|
413
|
+
|
|
414
|
+
if tty:
|
|
397
415
|
output_manager.print(t)
|
|
398
416
|
|
|
399
417
|
|
|
@@ -28,6 +28,7 @@ from ..volume import Volume
|
|
|
28
28
|
from ._help import ModalCommand
|
|
29
29
|
from .import_refs import (
|
|
30
30
|
MethodReference,
|
|
31
|
+
format_lazy_imports_note,
|
|
31
32
|
import_and_filter,
|
|
32
33
|
parse_import_ref,
|
|
33
34
|
)
|
|
@@ -162,7 +163,7 @@ def _start_shell_in_running_container(ref: str, cmd: str, pty: bool) -> None:
|
|
|
162
163
|
|
|
163
164
|
def _function_spec_from_ref(ref: str, use_module_mode: bool) -> _FunctionSpec:
|
|
164
165
|
import_ref = parse_import_ref(ref, use_module_mode=use_module_mode, command="modal shell")
|
|
165
|
-
runnable, all_usable_commands = import_and_filter(
|
|
166
|
+
runnable, all_usable_commands, lazy_imports = import_and_filter(
|
|
166
167
|
import_ref,
|
|
167
168
|
base_cmd="modal shell",
|
|
168
169
|
accept_local_entrypoint=False,
|
|
@@ -181,6 +182,8 @@ def _function_spec_from_ref(ref: str, use_module_mode: bool) -> _FunctionSpec:
|
|
|
181
182
|
else:
|
|
182
183
|
help_footer = f"The selected module '{import_ref.file_or_module}' has no Modal functions or classes."
|
|
183
184
|
|
|
185
|
+
help_footer += format_lazy_imports_note(lazy_imports, found_commands=bool(all_usable_commands))
|
|
186
|
+
|
|
184
187
|
raise ClickException(f"{help_header}\n\n{help_footer}")
|
|
185
188
|
|
|
186
189
|
if isinstance(runnable, MethodReference):
|
|
@@ -13,7 +13,7 @@ from modal._utils.async_utils import synchronizer
|
|
|
13
13
|
from modal._utils.browser_utils import open_url_and_display
|
|
14
14
|
from modal._utils.time_utils import timestamp_to_localized_str
|
|
15
15
|
from modal.cli._download import _volume_download
|
|
16
|
-
from modal.cli.utils import display_table, env_option, humanize_filesize, yes_option
|
|
16
|
+
from modal.cli.utils import confirm_or_suggest_yes, display_table, env_option, humanize_filesize, yes_option
|
|
17
17
|
from modal.output import OutputManager
|
|
18
18
|
from modal.volume import _AbstractVolumeUploadContextManager, _Volume
|
|
19
19
|
from modal_proto import api_pb2
|
|
@@ -81,10 +81,8 @@ async def rename(
|
|
|
81
81
|
env: str | None = None,
|
|
82
82
|
):
|
|
83
83
|
if not yes:
|
|
84
|
-
|
|
84
|
+
confirm_or_suggest_yes(
|
|
85
85
|
f"Are you sure you want rename the modal.Volume '{old_name}'? This may break any Apps currently using it.",
|
|
86
|
-
default=False,
|
|
87
|
-
abort=True,
|
|
88
86
|
)
|
|
89
87
|
|
|
90
88
|
await _Volume.rename(old_name, new_name, environment_name=env)
|
|
@@ -132,10 +130,8 @@ async def delete(
|
|
|
132
130
|
):
|
|
133
131
|
env = ensure_env(env)
|
|
134
132
|
if not yes:
|
|
135
|
-
|
|
133
|
+
confirm_or_suggest_yes(
|
|
136
134
|
f"Are you sure you want to irrevocably delete the modal.Volume '{name}'?",
|
|
137
|
-
default=False,
|
|
138
|
-
abort=True,
|
|
139
135
|
)
|
|
140
136
|
|
|
141
137
|
await _Volume.objects.delete(name, environment_name=env, allow_missing=allow_missing)
|
|
@@ -80,7 +80,7 @@ class _Client:
|
|
|
80
80
|
server_url: str,
|
|
81
81
|
client_type: int,
|
|
82
82
|
credentials: typing.Optional[tuple[str, str]],
|
|
83
|
-
version: str = "1.6.2.
|
|
83
|
+
version: str = "1.6.2.dev13",
|
|
84
84
|
*,
|
|
85
85
|
oauth_credentials: typing.Optional[_OAuthCredentials] = None,
|
|
86
86
|
):
|
|
@@ -290,7 +290,7 @@ class Client:
|
|
|
290
290
|
server_url: str,
|
|
291
291
|
client_type: int,
|
|
292
292
|
credentials: typing.Optional[tuple[str, str]],
|
|
293
|
-
version: str = "1.6.2.
|
|
293
|
+
version: str = "1.6.2.dev13",
|
|
294
294
|
*,
|
|
295
295
|
oauth_credentials: typing.Optional[_OAuthCredentials] = None,
|
|
296
296
|
):
|