modal 1.5.5.dev15__tar.gz → 1.5.5.dev16__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.5.dev15 → modal-1.5.5.dev16}/PKG-INFO +1 -1
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_environments.py +2 -2
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_function_variants.py +2 -2
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_functions.py +2 -2
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_image.py +4 -4
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_resolver.py +5 -5
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_runtime/user_code_imports.py +5 -5
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_serialization.py +7 -2
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_utils/mount_utils.py +1 -1
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_workspace.py +6 -6
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/app.py +13 -13
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/cli/config.py +5 -1
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/cli/import_refs.py +9 -4
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/cli/launch.py +6 -2
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/cli/run.py +10 -6
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/client.py +137 -20
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/client.pyi +124 -3
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/cls.py +13 -13
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/config.py +15 -7
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/functions.pyi +6 -6
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/runner.py +5 -5
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/sandbox.py +72 -11
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/sandbox.pyi +42 -12
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal.egg-info/PKG-INFO +1 -1
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal_proto/api_grpc.py +16 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal_proto/api_pb2.py +799 -769
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal_proto/api_pb2.pyi +124 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal_proto/api_pb2_grpc.py +33 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal_proto/api_pb2_grpc.pyi +10 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal_proto/modal_api_grpc.py +1 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal_version/__init__.py +1 -1
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/pyproject.toml +1 -1
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/LICENSE +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/README.md +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/__init__.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/__main__.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_billing.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_clustered_functions.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_clustered_functions.pyi +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_container_entrypoint.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_grpc_client.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_ipython.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_load_context.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_location.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_logs.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_logs_manager.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_logs_manager.pyi +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_object.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_output/__init__.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_output/manager.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_output/pty.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_output/rich.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_output/status.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_partial_function.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_resources.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_runtime/__init__.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_runtime/asgi.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_runtime/container_io_manager.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_runtime/container_io_manager.pyi +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_runtime/execution_context.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_runtime/execution_context.pyi +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_runtime/gpu_memory_snapshot.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_runtime/task_lifecycle_manager.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_runtime/task_lifecycle_manager.pyi +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_runtime/telemetry.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_runtime/user_code_event_loop.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_server.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_supports_logs.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_traceback.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_tunnel.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_tunnel.pyi +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_type_manager.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_utils/__init__.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_utils/app_utils.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_utils/async_utils.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_utils/auth_token_manager.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_utils/blob_utils.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_utils/browser_utils.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_utils/bytes_io_segment_payload.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_utils/curl_utils.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_utils/deprecation.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_utils/display_utils.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_utils/docker_utils.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_utils/function_utils.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_utils/git_utils.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_utils/grpc_testing.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_utils/grpc_utils.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_utils/hash_utils.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_utils/http_utils.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_utils/jwt_utils.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_utils/logger.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_utils/name_utils.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_utils/package_utils.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_utils/pattern_utils.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_utils/proxy_support.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_utils/rand_pb_testing.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_utils/sandbox_fs_utils.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_utils/shell_utils.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_utils/task_command_router_client.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_utils/time_utils.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_vendor/__init__.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_vendor/a2wsgi_wsgi.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_vendor/cloudpickle.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_vendor/tblib.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_vendor/version.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/_watcher.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/app.pyi +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/billing.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/billing.pyi +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/builder/2023.12.312.txt +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/builder/2023.12.txt +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/builder/2024.04.txt +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/builder/2024.10.txt +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/builder/2025.06.txt +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/builder/PREVIEW.txt +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/builder/README.md +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/builder/base-images.json +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/call_graph.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/cli/__init__.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/cli/_download.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/cli/_help.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/cli/_traceback.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/cli/app.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/cli/billing.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/cli/bootstrap.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/cli/changelog.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/cli/cluster.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/cli/container.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/cli/curl.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/cli/dashboard.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/cli/dict.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/cli/endpoint.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/cli/entry_point.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/cli/environment.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/cli/image.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/cli/logo.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/cli/network_file_system.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/cli/profile.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/cli/programs/__init__.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/cli/programs/run_jupyter.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/cli/programs/vscode.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/cli/queues.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/cli/secret.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/cli/selector.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/cli/shell.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/cli/skills.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/cli/token.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/cli/utils.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/cli/volume.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/cli/workspace.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/cloud_bucket_mount.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/cloud_bucket_mount.pyi +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/cls.pyi +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/container_process.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/container_process.pyi +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/dict.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/dict.pyi +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/environments.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/environments.pyi +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/exception.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/experimental/__init__.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/experimental/flash.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/experimental/flash.pyi +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/experimental/ipython.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/file_io.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/file_io.pyi +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/file_pattern_matcher.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/functions.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/image.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/image.pyi +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/io_streams.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/io_streams.pyi +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/mount.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/mount.pyi +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/network_file_system.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/network_file_system.pyi +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/object.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/object.pyi +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/output.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/parallel_map.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/parallel_map.pyi +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/partial_function.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/partial_function.pyi +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/proxy.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/proxy.pyi +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/py.typed +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/queue.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/queue.pyi +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/retries.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/runner.pyi +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/running_app.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/sandbox_fs.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/sandbox_fs.pyi +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/schedule.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/scheduler_placement.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/secret.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/secret.pyi +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/server.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/server.pyi +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/serving.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/serving.pyi +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/skills/modal/SKILL.md +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/snapshot.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/snapshot.pyi +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/stream_type.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/token_flow.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/token_flow.pyi +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/types.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/volume.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/volume.pyi +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/workspace.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal/workspace.pyi +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal.egg-info/SOURCES.txt +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal.egg-info/dependency_links.txt +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal.egg-info/entry_points.txt +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal.egg-info/requires.txt +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal.egg-info/top_level.txt +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal_docs/__init__.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal_docs/gen_cli_docs.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal_docs/gen_cli_docs_main.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal_docs/gen_reference_docs.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal_docs/gen_reference_docs_main.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal_docs/mdmd/__init__.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal_docs/mdmd/mdmd.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal_docs/mdmd/signatures.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal_docs/mdmd/types.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal_docs/reference_intro.md +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal_proto/__init__.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal_proto/py.typed +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal_proto/task_command_router_grpc.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal_proto/task_command_router_pb2.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal_proto/task_command_router_pb2.pyi +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal_proto/task_command_router_pb2_grpc.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal_proto/task_command_router_pb2_grpc.pyi +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/modal_version/__main__.py +0 -0
- {modal-1.5.5.dev15 → modal-1.5.5.dev16}/setup.cfg +0 -0
|
@@ -478,7 +478,7 @@ class _EnvironmentBillingManager:
|
|
|
478
478
|
elif end.tzinfo != timezone.utc:
|
|
479
479
|
raise InvalidError("Timezone-aware 'end' parameter must be in UTC.")
|
|
480
480
|
|
|
481
|
-
if not self._environment.
|
|
481
|
+
if not self._environment._is_hydrated:
|
|
482
482
|
await self._environment.hydrate()
|
|
483
483
|
|
|
484
484
|
request = api_pb2.WorkspaceBillingReportRequest(
|
|
@@ -549,7 +549,7 @@ class _EnvironmentBillingManager:
|
|
|
549
549
|
if cycle > datetime.now(timezone.utc):
|
|
550
550
|
raise InvalidError("Provided 'cycle' parameter cannot be in the future.")
|
|
551
551
|
|
|
552
|
-
if not self._environment.
|
|
552
|
+
if not self._environment._is_hydrated:
|
|
553
553
|
await self._environment.hydrate()
|
|
554
554
|
|
|
555
555
|
request = api_pb2.EnvironmentBillingSummaryRequest(environment_id=self._environment.object_id)
|
|
@@ -157,7 +157,7 @@ class _FunctionOptions:
|
|
|
157
157
|
+ list(self.secrets)
|
|
158
158
|
+ [mount.secret for _, mount in self.cloud_bucket_mounts if mount.secret]
|
|
159
159
|
)
|
|
160
|
-
return [dep for dep in all_deps if not dep.
|
|
160
|
+
return [dep for dep in all_deps if not dep._is_hydrated]
|
|
161
161
|
|
|
162
162
|
def to_proto(self) -> api_pb2.FunctionOptions:
|
|
163
163
|
"""Convert the dataclass to a FunctionOptions protobuf message."""
|
|
@@ -246,7 +246,7 @@ def _make_function_variant(
|
|
|
246
246
|
load_context: "LoadContext",
|
|
247
247
|
existing_object_id: str | None,
|
|
248
248
|
):
|
|
249
|
-
if not base_function.
|
|
249
|
+
if not base_function._is_hydrated:
|
|
250
250
|
await base_function.hydrate(load_context.client)
|
|
251
251
|
assert base_function._client and base_function._client.stub
|
|
252
252
|
|
|
@@ -937,7 +937,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
|
|
|
937
937
|
with FunctionCreationStatus(tag) as function_creation_status:
|
|
938
938
|
timeout_secs = timeout
|
|
939
939
|
|
|
940
|
-
if app and app.
|
|
940
|
+
if app and app._is_interactive_ and not is_builder_function:
|
|
941
941
|
pty_info = get_pty_info(shell=False)
|
|
942
942
|
else:
|
|
943
943
|
pty_info = None
|
|
@@ -1934,7 +1934,7 @@ class _Function(typing.Generic[P, ReturnType, OriginalReturnType], _Object, type
|
|
|
1934
1934
|
# TODO: check if we end up here in a container for a serialized function?
|
|
1935
1935
|
raise ExecutionError("Can't call .local on service function")
|
|
1936
1936
|
|
|
1937
|
-
if is_local() and self.
|
|
1937
|
+
if is_local() and self._spec_.volumes or self._spec_.network_file_systems:
|
|
1938
1938
|
warnings.warn(
|
|
1939
1939
|
f"The {info.function_name} function is executing locally "
|
|
1940
1940
|
+ "and will not have access to the mounted Volume or NetworkFileSystem data"
|
|
@@ -704,7 +704,7 @@ class _Image(_Object, type_prefix="im"):
|
|
|
704
704
|
# TODO: better way to filter out types that don't have a stable hash?
|
|
705
705
|
build_function_globals = serialize(filtered_globals) if filtered_globals else b""
|
|
706
706
|
_build_function = api_pb2.BuildFunction(
|
|
707
|
-
definition=build_function.
|
|
707
|
+
definition=build_function._get_build_def(),
|
|
708
708
|
globals=build_function_globals,
|
|
709
709
|
input=build_function_input,
|
|
710
710
|
)
|
|
@@ -2756,7 +2756,7 @@ class _Image(_Object, type_prefix="im"):
|
|
|
2756
2756
|
|
|
2757
2757
|
info = FunctionInfo(raw_f)
|
|
2758
2758
|
|
|
2759
|
-
function = _Function.
|
|
2759
|
+
function = _Function._from_local(
|
|
2760
2760
|
info,
|
|
2761
2761
|
app=None,
|
|
2762
2762
|
image=self,
|
|
@@ -2938,7 +2938,7 @@ class _Image(_Object, type_prefix="im"):
|
|
|
2938
2938
|
try:
|
|
2939
2939
|
yield
|
|
2940
2940
|
except Exception as exc:
|
|
2941
|
-
if not self.
|
|
2941
|
+
if not self._is_hydrated:
|
|
2942
2942
|
# Might be hydrated later (if it's the container's used image)
|
|
2943
2943
|
self.inside_exceptions.append(exc)
|
|
2944
2944
|
elif env_image_id == self.object_id:
|
|
@@ -3051,7 +3051,7 @@ class _Image(_Object, type_prefix="im"):
|
|
|
3051
3051
|
"""mdmd:hidden"""
|
|
3052
3052
|
# Image inherits hydrate() from Object but can't be hydrated on demand
|
|
3053
3053
|
# Overriding the method lets us hide it from the docs and raise a better error message
|
|
3054
|
-
if not self.
|
|
3054
|
+
if not self._is_hydrated:
|
|
3055
3055
|
raise ExecutionError(
|
|
3056
3056
|
"Images cannot currently be hydrated on demand; you can build an Image by running an App that uses it."
|
|
3057
3057
|
)
|
|
@@ -44,19 +44,19 @@ class Resolver:
|
|
|
44
44
|
existing_object_id: str | None = None,
|
|
45
45
|
):
|
|
46
46
|
if obj._is_hydrated and obj._skip_reload:
|
|
47
|
-
if obj.
|
|
47
|
+
if obj._local_uuid not in self._local_uuid_to_future:
|
|
48
48
|
# a bit dumb - but we still need to store a reference to the object here
|
|
49
49
|
# to be able to include all referenced objects when setting up the app
|
|
50
50
|
fut: Future = Future()
|
|
51
51
|
fut.set_result(obj)
|
|
52
|
-
self._local_uuid_to_future[obj.
|
|
52
|
+
self._local_uuid_to_future[obj._local_uuid] = fut
|
|
53
53
|
return obj
|
|
54
54
|
|
|
55
55
|
deduplication_key: Hashable | None = None
|
|
56
56
|
if obj._deduplication_key:
|
|
57
57
|
deduplication_key = await obj._deduplication_key()
|
|
58
58
|
|
|
59
|
-
cached_future = self._local_uuid_to_future.get(obj.
|
|
59
|
+
cached_future = self._local_uuid_to_future.get(obj._local_uuid)
|
|
60
60
|
|
|
61
61
|
if not cached_future and deduplication_key is not None:
|
|
62
62
|
# deduplication cache makes sure duplicate mounts are resolved only
|
|
@@ -78,7 +78,7 @@ class Resolver:
|
|
|
78
78
|
# Use asyncio.gather here (not TaskContext.gather) - the shared TaskContext
|
|
79
79
|
# in load_context handles cancellation at the top level, preventing premature
|
|
80
80
|
# cancellation of shared dependencies when sibling tasks fail.
|
|
81
|
-
await asyncio.gather(*[self.load(dep, load_context) for dep in obj.
|
|
81
|
+
await asyncio.gather(*[self.load(dep, load_context) for dep in obj._deps_()])
|
|
82
82
|
|
|
83
83
|
# Load the object itself
|
|
84
84
|
if not obj._load:
|
|
@@ -102,7 +102,7 @@ class Resolver:
|
|
|
102
102
|
|
|
103
103
|
# use task_context from load_context to make sure tasks are cleaned up eventually
|
|
104
104
|
cached_future = parent_load_context.task_context.create_task(loader())
|
|
105
|
-
self._local_uuid_to_future[obj.
|
|
105
|
+
self._local_uuid_to_future[obj._local_uuid] = cached_future
|
|
106
106
|
if deduplication_key is not None:
|
|
107
107
|
self._deduplication_cache[deduplication_key] = cached_future
|
|
108
108
|
with suppress_tb_frame():
|
|
@@ -522,8 +522,8 @@ def import_single_function_service(
|
|
|
522
522
|
f = getattr(module, qual_name)
|
|
523
523
|
if isinstance(f, Function):
|
|
524
524
|
_function: modal._functions._Function[Any, Any, Any] = synchronizer._translate_in(f) # type: ignore
|
|
525
|
-
service_deps = _function.
|
|
526
|
-
user_defined_callable = _function.
|
|
525
|
+
service_deps = _function._deps_(only_explicit_mounts=True)
|
|
526
|
+
user_defined_callable = _function._raw_f_
|
|
527
527
|
assert _function._app # app should always be set on a decorated function
|
|
528
528
|
active_app = _function._app
|
|
529
529
|
else:
|
|
@@ -594,7 +594,7 @@ def import_class_service(
|
|
|
594
594
|
if isinstance(cls_or_user_cls, modal.cls.Cls):
|
|
595
595
|
_cls = typing.cast(modal.cls._Cls, synchronizer._translate_in(cls_or_user_cls))
|
|
596
596
|
class_service_function: _Function = _cls._get_class_service_function()
|
|
597
|
-
service_deps = class_service_function.
|
|
597
|
+
service_deps = class_service_function._deps_(only_explicit_mounts=True)
|
|
598
598
|
active_app = class_service_function.app
|
|
599
599
|
else:
|
|
600
600
|
# Undecorated user class (serialized or local scope-decoration).
|
|
@@ -606,7 +606,7 @@ def import_class_service(
|
|
|
606
606
|
service_function_hydration_data.function_handle_metadata,
|
|
607
607
|
skip_reload=True, # this skips re-loading the function, which is required since it doesn't have a loader
|
|
608
608
|
)
|
|
609
|
-
_cls = modal.cls._Cls.
|
|
609
|
+
_cls = modal.cls._Cls._from_local(cls_or_user_cls, active_app, _service_function)
|
|
610
610
|
# hydration of the class itself - just sets the id and triggers some side effects
|
|
611
611
|
# that transfers metadata from the service function to the class. TODO: cleanup!
|
|
612
612
|
_cls._hydrate(class_id, _client, api_pb2.ClassHandleMetadata())
|
|
@@ -647,7 +647,7 @@ def import_server_service(
|
|
|
647
647
|
if isinstance(cls_or_user_cls, modal.server.Server):
|
|
648
648
|
_server = typing.cast(modal._server._Server, synchronizer._translate_in(cls_or_user_cls))
|
|
649
649
|
server_service_function: _Function = _server._get_service_function()
|
|
650
|
-
service_deps = server_service_function.
|
|
650
|
+
service_deps = server_service_function._deps_(only_explicit_mounts=True)
|
|
651
651
|
active_app = _server._get_app()
|
|
652
652
|
|
|
653
653
|
else:
|
|
@@ -4,7 +4,7 @@ import io
|
|
|
4
4
|
import pickle
|
|
5
5
|
import typing
|
|
6
6
|
from inspect import Parameter
|
|
7
|
-
from typing import Any
|
|
7
|
+
from typing import Any, cast
|
|
8
8
|
|
|
9
9
|
from modal._traceback import extract_traceback
|
|
10
10
|
from modal.config import config
|
|
@@ -43,8 +43,11 @@ class Pickler(cloudpickle.Pickler):
|
|
|
43
43
|
|
|
44
44
|
if isinstance(obj, _Object):
|
|
45
45
|
flag = "_o"
|
|
46
|
+
is_hydrated = obj._is_hydrated
|
|
46
47
|
elif isinstance(obj, Object):
|
|
47
48
|
flag = "o"
|
|
49
|
+
inner = cast(_Object, synchronizer._translate_in(obj))
|
|
50
|
+
is_hydrated = inner._is_hydrated
|
|
48
51
|
elif isinstance(obj, PartialFunction):
|
|
49
52
|
# Special case for PartialObject since it's a synchronicity wrapped object
|
|
50
53
|
# that's set on serialized classes.
|
|
@@ -66,8 +69,10 @@ class Pickler(cloudpickle.Pickler):
|
|
|
66
69
|
return ("sync", (impl_object.__class__, attributes))
|
|
67
70
|
else:
|
|
68
71
|
return
|
|
69
|
-
|
|
72
|
+
|
|
73
|
+
if not is_hydrated:
|
|
70
74
|
raise InvalidError(f"Can't serialize object {obj} which hasn't been hydrated.")
|
|
75
|
+
|
|
71
76
|
return (obj.object_id, flag, obj._get_metadata())
|
|
72
77
|
|
|
73
78
|
|
|
@@ -108,7 +108,7 @@ def validate_volumes_by_object_id(validated_volumes: Sequence[tuple[str, _Volume
|
|
|
108
108
|
"""
|
|
109
109
|
object_id_to_paths: dict[str, list[str]] = {}
|
|
110
110
|
for path, volume in validated_volumes:
|
|
111
|
-
if not volume.
|
|
111
|
+
if not volume._is_hydrated:
|
|
112
112
|
# This should never happen since this function is only called at load time
|
|
113
113
|
raise RuntimeError(f"Internal error: Volume at '{path}' is not hydrated when validating mounts")
|
|
114
114
|
object_id_to_paths.setdefault(volume.object_id, []).append(path)
|
|
@@ -321,7 +321,7 @@ class _WorkspaceBillingManager:
|
|
|
321
321
|
A single mapping containing cost values. All values are reported as `decimal.Decimal`s.
|
|
322
322
|
"""
|
|
323
323
|
|
|
324
|
-
if not self._workspace.
|
|
324
|
+
if not self._workspace._is_hydrated:
|
|
325
325
|
await self._workspace.hydrate()
|
|
326
326
|
|
|
327
327
|
response = await self._workspace.client.stub.WorkspaceBillingRates(
|
|
@@ -386,7 +386,7 @@ class _WorkspaceBillingManager:
|
|
|
386
386
|
elif end.tzinfo != timezone.utc:
|
|
387
387
|
raise InvalidError("Timezone-aware 'end' parameter must be in UTC.")
|
|
388
388
|
|
|
389
|
-
if not self._workspace.
|
|
389
|
+
if not self._workspace._is_hydrated:
|
|
390
390
|
await self._workspace.hydrate()
|
|
391
391
|
|
|
392
392
|
request = api_pb2.WorkspaceBillingReportRequest(
|
|
@@ -457,7 +457,7 @@ class _WorkspaceBillingManager:
|
|
|
457
457
|
if cycle > datetime.now(timezone.utc):
|
|
458
458
|
raise InvalidError("Provided 'cycle' parameter cannot be in the future.")
|
|
459
459
|
|
|
460
|
-
if not self._workspace.
|
|
460
|
+
if not self._workspace._is_hydrated:
|
|
461
461
|
await self._workspace.hydrate()
|
|
462
462
|
|
|
463
463
|
request = api_pb2.WorkspaceBillingSummaryRequest()
|
|
@@ -483,7 +483,7 @@ class _WorkspaceSettingsManager:
|
|
|
483
483
|
Returns:
|
|
484
484
|
A `WorkspaceSettings` dataclass.
|
|
485
485
|
"""
|
|
486
|
-
if not self._workspace.
|
|
486
|
+
if not self._workspace._is_hydrated:
|
|
487
487
|
await self._workspace.hydrate()
|
|
488
488
|
resp = await self._workspace.client.stub.WorkspaceSettings(Empty())
|
|
489
489
|
return WorkspaceSettings(
|
|
@@ -494,14 +494,14 @@ class _WorkspaceSettingsManager:
|
|
|
494
494
|
"""mdmd:hidden
|
|
495
495
|
Set the image builder version for the Workspace.
|
|
496
496
|
"""
|
|
497
|
-
if not self._workspace.
|
|
497
|
+
if not self._workspace._is_hydrated:
|
|
498
498
|
await self._workspace.hydrate()
|
|
499
499
|
req = api_pb2.WorkspaceSetImageBuilderVersionRequest(new_image_builder_version=version)
|
|
500
500
|
await self._workspace.client.stub.WorkspaceSetImageBuilderVersion(req)
|
|
501
501
|
|
|
502
502
|
async def _set_default_environment(self, name: str) -> None:
|
|
503
503
|
"""Set the default environment for the Workspace."""
|
|
504
|
-
if not self._workspace.
|
|
504
|
+
if not self._workspace._is_hydrated:
|
|
505
505
|
await self._workspace.hydrate()
|
|
506
506
|
req = api_pb2.WorkspaceSetDefaultEnvironmentRequest(environment_name=name)
|
|
507
507
|
await self._workspace.client.stub.WorkspaceSetDefaultEnvironment(req)
|
|
@@ -599,14 +599,14 @@ class _App:
|
|
|
599
599
|
raise ExecutionError("`_get_watch_mounts` requires a running app.")
|
|
600
600
|
|
|
601
601
|
all_mounts = []
|
|
602
|
-
for function in self.
|
|
602
|
+
for function in self._local_state.functions.values():
|
|
603
603
|
all_mounts.extend(function._serve_mounts)
|
|
604
604
|
|
|
605
605
|
return [m for m in all_mounts if m.is_local()]
|
|
606
606
|
|
|
607
607
|
def _add_function(self, function: _Function, is_web_endpoint: bool):
|
|
608
608
|
local_state = self._local_state
|
|
609
|
-
if old_function := local_state.functions.get(function.
|
|
609
|
+
if old_function := local_state.functions.get(function._tag_, None):
|
|
610
610
|
if old_function is function:
|
|
611
611
|
return # already added the same exact instance, ignore
|
|
612
612
|
|
|
@@ -615,25 +615,25 @@ class _App:
|
|
|
615
615
|
# and we don't want to warn about a collision in that case.
|
|
616
616
|
if not is_interactive_ipython():
|
|
617
617
|
logger.warning(
|
|
618
|
-
f"Warning: function name '{function.
|
|
618
|
+
f"Warning: function name '{function._tag_}' collision!"
|
|
619
619
|
" Overriding existing function "
|
|
620
620
|
f"[{old_function._info.module_name}].{old_function._info.function_name}"
|
|
621
621
|
f" with new function [{function._info.module_name}].{function._info.function_name}"
|
|
622
622
|
)
|
|
623
|
-
if function.
|
|
624
|
-
logger.warning(f"Warning: tag {function.
|
|
623
|
+
if function._tag_ in local_state.classes:
|
|
624
|
+
logger.warning(f"Warning: tag {function._tag_} exists but is overridden by function")
|
|
625
625
|
|
|
626
626
|
if self._running_app:
|
|
627
627
|
# If this is inside a container, then objects can be defined after app initialization.
|
|
628
628
|
# So we may have to initialize objects once they get bound to the app.
|
|
629
|
-
if function.
|
|
630
|
-
object_id: str = self._running_app.function_ids[function.
|
|
629
|
+
if function._tag_ in self._running_app.function_ids:
|
|
630
|
+
object_id: str = self._running_app.function_ids[function._tag_]
|
|
631
631
|
metadata: Message = self._running_app.object_handle_metadata[object_id]
|
|
632
632
|
function._hydrate(object_id, self._client, metadata)
|
|
633
633
|
|
|
634
|
-
local_state.functions[function.
|
|
634
|
+
local_state.functions[function._tag_] = function
|
|
635
635
|
if is_web_endpoint:
|
|
636
|
-
local_state.web_endpoints.append(function.
|
|
636
|
+
local_state.web_endpoints.append(function._tag_)
|
|
637
637
|
|
|
638
638
|
def _add_class(self, tag: str, cls: _Cls):
|
|
639
639
|
if self._running_app:
|
|
@@ -995,7 +995,7 @@ class _App:
|
|
|
995
995
|
if is_generator is None:
|
|
996
996
|
is_generator = inspect.isgeneratorfunction(raw_f) or inspect.isasyncgenfunction(raw_f)
|
|
997
997
|
|
|
998
|
-
function = _Function.
|
|
998
|
+
function = _Function._from_local(
|
|
999
999
|
info,
|
|
1000
1000
|
app=self,
|
|
1001
1001
|
image=image,
|
|
@@ -1231,7 +1231,7 @@ class _App:
|
|
|
1231
1231
|
info = FunctionInfo(None, serialized=serialized, user_cls=user_cls)
|
|
1232
1232
|
|
|
1233
1233
|
i6pn_enabled = i6pn or cluster_size is not None
|
|
1234
|
-
cls_func = _Function.
|
|
1234
|
+
cls_func = _Function._from_local(
|
|
1235
1235
|
info,
|
|
1236
1236
|
app=self,
|
|
1237
1237
|
image=image or self._get_default_image(),
|
|
@@ -1274,7 +1274,7 @@ class _App:
|
|
|
1274
1274
|
|
|
1275
1275
|
self._add_function(cls_func, is_web_endpoint=False)
|
|
1276
1276
|
|
|
1277
|
-
cls: _Cls = _Cls.
|
|
1277
|
+
cls: _Cls = _Cls._from_local(user_cls, self, cls_func)
|
|
1278
1278
|
|
|
1279
1279
|
for method_name, partial_function in cls._method_partials.items():
|
|
1280
1280
|
if partial_function.params.webhook_config is not None:
|
|
@@ -1442,7 +1442,7 @@ class _App:
|
|
|
1442
1442
|
# Create the FunctionInfo for the server, note we treat FunctionInfo as a class for servers
|
|
1443
1443
|
info = FunctionInfo(None, serialized=serialized, user_cls=user_cls, name_override=name or user_cls.__name__)
|
|
1444
1444
|
# Create the service function
|
|
1445
|
-
service_function = _Function.
|
|
1445
|
+
service_function = _Function._from_local(
|
|
1446
1446
|
info,
|
|
1447
1447
|
app=self,
|
|
1448
1448
|
image=image or self._get_default_image(),
|
|
@@ -22,12 +22,16 @@ config_cli = ModalGroup(
|
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
@config_cli.command("show", help="Show current configuration values (debugging command).")
|
|
25
|
-
@click.option("--redact/--no-redact", default=True, help="Redact
|
|
25
|
+
@click.option("--redact/--no-redact", default=True, help="Redact secret credential values.")
|
|
26
26
|
def show(redact: bool):
|
|
27
27
|
# This is just a test command
|
|
28
28
|
config_dict = config.to_dict()
|
|
29
29
|
if redact and config_dict.get("token_secret"):
|
|
30
30
|
config_dict["token_secret"] = "***"
|
|
31
|
+
if redact and config_dict.get("oauth_refresh_token"):
|
|
32
|
+
config_dict["oauth_refresh_token"] = "***"
|
|
33
|
+
if redact and config_dict.get("oauth_client_secret"):
|
|
34
|
+
config_dict["oauth_client_secret"] = "***"
|
|
31
35
|
|
|
32
36
|
OutputManager.get().print_json(json.dumps(config_dict))
|
|
33
37
|
|
|
@@ -27,6 +27,8 @@ from modal.exception import InvalidError, _CliUserExecutionError
|
|
|
27
27
|
from modal.functions import Function
|
|
28
28
|
from modal.output import OutputManager
|
|
29
29
|
|
|
30
|
+
from .._utils.async_utils import synchronizer
|
|
31
|
+
|
|
30
32
|
|
|
31
33
|
@dataclasses.dataclass
|
|
32
34
|
class ImportRef:
|
|
@@ -165,15 +167,18 @@ def list_cli_commands(
|
|
|
165
167
|
all_runnables: dict[Runnable, list[str]] = defaultdict(list)
|
|
166
168
|
priorities: dict[Runnable, int] = defaultdict(lambda: AutoRunPriority.APP_FUNCTION)
|
|
167
169
|
for app_name, app in apps:
|
|
168
|
-
for name,
|
|
170
|
+
for name, inner_entrypoint in app._local_state.local_entrypoints.items():
|
|
171
|
+
local_entrypoint = cast(LocalEntrypoint, synchronizer._translate_out(inner_entrypoint))
|
|
169
172
|
all_runnables[local_entrypoint].append(f"{app_name}.{name}")
|
|
170
173
|
priorities[local_entrypoint] = AutoRunPriority.APP_LOCAL_ENTRYPOINT
|
|
171
|
-
for name,
|
|
172
|
-
|
|
174
|
+
for name, inner_function in app._local_state.functions.items():
|
|
175
|
+
function = cast(Function, synchronizer._translate_out(inner_function))
|
|
176
|
+
if function._info_.is_service_class() and not include_service_functions:
|
|
173
177
|
continue # Skip class and server service functions for all commands except `modal shell`.
|
|
174
178
|
all_runnables[function].append(f"{app_name}.{name}")
|
|
175
179
|
priorities[function] = AutoRunPriority.APP_FUNCTION
|
|
176
|
-
for cls_name,
|
|
180
|
+
for cls_name, inner_cls in app._local_state.classes.items():
|
|
181
|
+
cls = cast(Cls, synchronizer._translate_out(inner_cls))
|
|
177
182
|
for method_name in cls._get_method_names():
|
|
178
183
|
method_ref = MethodReference(cls, method_name)
|
|
179
184
|
all_runnables[method_ref].append(f"{app_name}.{cls_name}.{method_name}")
|
|
@@ -4,12 +4,15 @@ import inspect
|
|
|
4
4
|
import json
|
|
5
5
|
import os
|
|
6
6
|
from pathlib import Path
|
|
7
|
-
from typing import Any
|
|
7
|
+
from typing import Any, cast
|
|
8
8
|
|
|
9
9
|
import click
|
|
10
10
|
import rich.panel
|
|
11
11
|
from rich.markdown import Markdown
|
|
12
12
|
|
|
13
|
+
from modal.app import _App
|
|
14
|
+
|
|
15
|
+
from .._utils.async_utils import synchronizer
|
|
13
16
|
from ..exception import _CliUserExecutionError
|
|
14
17
|
from ..output import OutputManager
|
|
15
18
|
from ..runner import run_app
|
|
@@ -40,7 +43,8 @@ def _launch_program(
|
|
|
40
43
|
entrypoint = module.main
|
|
41
44
|
|
|
42
45
|
app = _get_runnable_app(entrypoint)
|
|
43
|
-
|
|
46
|
+
inner = cast(_App, synchronizer._translate_in(app))
|
|
47
|
+
inner._description = description if description else base_cmd
|
|
44
48
|
|
|
45
49
|
# `launch/` scripts must have a `local_entrypoint()` with no args, for simplicity here.
|
|
46
50
|
func = entrypoint.info.raw_f
|
|
@@ -8,14 +8,15 @@ import time
|
|
|
8
8
|
import typing
|
|
9
9
|
from collections.abc import Callable
|
|
10
10
|
from dataclasses import dataclass
|
|
11
|
-
from typing import Any, get_args
|
|
11
|
+
from typing import Any, cast, get_args
|
|
12
12
|
|
|
13
13
|
import click
|
|
14
14
|
from click import ClickException
|
|
15
15
|
from typing_extensions import TypedDict
|
|
16
16
|
|
|
17
17
|
from .._environments import ensure_env
|
|
18
|
-
from ..
|
|
18
|
+
from .._utils.async_utils import synchronizer
|
|
19
|
+
from ..app import App, LocalEntrypoint, _App
|
|
19
20
|
from ..cls import _get_class_constructor_signature
|
|
20
21
|
from ..config import config
|
|
21
22
|
from ..exception import ExecutionError, InvalidError, _CliUserExecutionError
|
|
@@ -466,9 +467,10 @@ class RunGroup(ModalGroup):
|
|
|
466
467
|
raise ClickException(f"{help_header}\n\n{help_footer}")
|
|
467
468
|
|
|
468
469
|
app = _get_runnable_app(runnable)
|
|
470
|
+
inner = cast(_App, synchronizer._translate_in(app))
|
|
469
471
|
|
|
470
|
-
if
|
|
471
|
-
|
|
472
|
+
if inner._description is None:
|
|
473
|
+
inner._description = _get_clean_app_description(func_ref)
|
|
472
474
|
|
|
473
475
|
if isinstance(runnable, LocalEntrypoint):
|
|
474
476
|
click_command = _get_click_command_for_local_entrypoint(app, runnable)
|
|
@@ -672,8 +674,10 @@ def serve(
|
|
|
672
674
|
|
|
673
675
|
OutputManager.get().set_timestamps(timestamps)
|
|
674
676
|
app = import_app_from_ref(import_ref, base_cmd="modal serve")
|
|
675
|
-
|
|
676
|
-
|
|
677
|
+
inner = cast(_App, synchronizer._translate_in(app))
|
|
678
|
+
|
|
679
|
+
if inner._description is None:
|
|
680
|
+
inner._description = _get_clean_app_description(app_ref)
|
|
677
681
|
with serve_app(app, import_ref, name=name, environment_name=env):
|
|
678
682
|
if timeout is None:
|
|
679
683
|
timeout = config["serve_timeout"]
|