diff --git a/litellm/proxy/_lazy_openapi_snapshot.py b/litellm/proxy/_lazy_openapi_snapshot.py index a895a0809b1..d5b49a473df 100644 --- a/litellm/proxy/_lazy_openapi_snapshot.py +++ b/litellm/proxy/_lazy_openapi_snapshot.py @@ -18,6 +18,8 @@ from dataclasses import dataclass from pathlib import Path from typing import TYPE_CHECKING, Final +from typing_extensions import ReadOnly, TypedDict + if TYPE_CHECKING: from fastapi import FastAPI @@ -90,9 +92,14 @@ def _normalize_operation_ids(paths: dict[str, dict]) -> None: break +class SnapshotFragment(TypedDict): + paths: ReadOnly[dict[str, dict[str, object]]] + components: ReadOnly[dict[str, dict[str, object]]] + + @dataclass(frozen=True, slots=True) class SnapshotResult: - fragments: dict[str, dict] + fragments: dict[str, SnapshotFragment] skipped: tuple[str, ...] @@ -115,7 +122,7 @@ def generate_snapshot() -> SnapshotResult: skipped: Final = tuple(name for feat in LAZY_FEATURES if (name := _register_feature(app, feat)) is not None) - fragments: Final[dict[str, dict]] = {} + fragments: Final[dict[str, SnapshotFragment]] = {} used_operation_ids: Final[set[str]] = set() for feat in LAZY_FEATURES: feat_routes = [r for r in app.routes if feat.matches(getattr(r, "path", ""))] diff --git a/tests/test_litellm/proxy/test_lazy_openapi_snapshot.py b/tests/test_litellm/proxy/test_lazy_openapi_snapshot.py index c513bd83b66..f9ef98bc474 100644 --- a/tests/test_litellm/proxy/test_lazy_openapi_snapshot.py +++ b/tests/test_litellm/proxy/test_lazy_openapi_snapshot.py @@ -200,7 +200,10 @@ def test_main_refuses_to_write_a_snapshot_missing_skipped_features(tmp_path, cap def test_main_writes_sorted_snapshot_when_every_feature_loads(tmp_path): snapshot_file = tmp_path / "snapshot.json" - fragments = {"zeta": {"paths": {"/z": {}}, "components": {"schemas": {}}}, "alpha": {"paths": {}, "components": {"schemas": {}}}} + fragments = { + "zeta": {"paths": {"/z": {}}, "components": {"schemas": {}}}, + "alpha": {"paths": {}, "components": {"schemas": {}}}, + } assert main(snapshot_file, generate=lambda: SnapshotResult(fragments=fragments, skipped=())) == 0 assert json.loads(snapshot_file.read_text()) == fragments