mirror of
https://github.com/BerriAI/litellm.git
synced 2026-08-28 05:25:59 +00:00
Merge pull request #36336 from BerriAI/litellm_/standard-lists-api-d1dc4a
test(proxy): guard management_v1 against fastapi names removed in supported releases
This commit is contained in:
commit
3726bceb53
1 changed files with 62 additions and 1 deletions
|
|
@ -1,11 +1,18 @@
|
|||
import ast
|
||||
import importlib.util
|
||||
from pathlib import Path
|
||||
from types import ModuleType
|
||||
from typing import Annotated
|
||||
|
||||
import fastapi.dependencies.utils as fastapi_dependency_utils
|
||||
import pytest
|
||||
from fastapi import Depends, FastAPI, Header, Query, Request
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
import litellm.proxy.management_endpoints.management_v1.common as common_module
|
||||
from litellm.proxy.management_endpoints.management_v1.common import (
|
||||
ManagementProblem,
|
||||
PROBLEM_CONTENT_TYPE,
|
||||
ManagementProblem,
|
||||
_declared_query_params,
|
||||
problem_response,
|
||||
reject_unknown_query_params,
|
||||
|
|
@ -93,3 +100,57 @@ def test_declared_query_params_is_empty_when_the_route_has_no_dependant():
|
|||
}
|
||||
)
|
||||
assert _declared_query_params(request) == frozenset()
|
||||
|
||||
|
||||
# fastapi removed these in 0.140.7, which `pyproject.toml` still allows via
|
||||
# `fastapi>=0.136.3,<1.0`. Add a name here whenever a supported release drops one.
|
||||
FASTAPI_NAMES_REMOVED_IN_0_140_7 = frozenset({"get_flat_dependant"})
|
||||
|
||||
MANAGEMENT_V1_PACKAGE = Path(str(common_module.__file__)).parent
|
||||
|
||||
|
||||
def _public_names(module: ModuleType) -> frozenset[str]:
|
||||
return frozenset(name for name in vars(module) if not name.startswith("_"))
|
||||
|
||||
|
||||
def _fastapi_names_imported_by(source_file: Path) -> frozenset[str]:
|
||||
tree = ast.parse(source_file.read_text())
|
||||
return frozenset(
|
||||
alias.name
|
||||
for node in ast.walk(tree)
|
||||
if isinstance(node, ast.ImportFrom) and (node.module or "").startswith("fastapi")
|
||||
for alias in node.names
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"source_file", sorted(MANAGEMENT_V1_PACKAGE.glob("*.py")), ids=lambda path: path.name
|
||||
)
|
||||
def test_no_module_imports_a_fastapi_name_removed_in_a_supported_release(source_file: Path):
|
||||
"""`pyproject.toml` allows fastapi up to <1.0, but CI only ever resolves 0.136.3.
|
||||
|
||||
Every other test here passes just as well against a module importing a name
|
||||
fastapi has since deleted, because the pinned fastapi still has it. On a user's
|
||||
fastapi>=0.140.7 that import is an ImportError, and `proxy_server` imports this
|
||||
package unguarded at module level, so it takes the whole proxy down rather than
|
||||
just these routes. Globbing the package means a new module is covered on sight.
|
||||
"""
|
||||
assert not _fastapi_names_imported_by(source_file) & FASTAPI_NAMES_REMOVED_IN_0_140_7
|
||||
|
||||
|
||||
def test_common_still_imports_when_fastapi_has_dropped_those_names(monkeypatch: pytest.MonkeyPatch):
|
||||
"""The static check above cannot prove the module actually loads; this does.
|
||||
|
||||
Behaviour cannot be asserted under the same simulation: on 0.136.3
|
||||
`get_flat_params` calls `get_flat_dependant` internally, so it raises NameError
|
||||
once the name is gone. Loading is the part this pins.
|
||||
"""
|
||||
for name in FASTAPI_NAMES_REMOVED_IN_0_140_7:
|
||||
monkeypatch.delattr(fastapi_dependency_utils, name, raising=False)
|
||||
spec = importlib.util.spec_from_file_location(
|
||||
"management_v1_common__simulated_fastapi", Path(str(common_module.__file__))
|
||||
)
|
||||
assert spec is not None and spec.loader is not None
|
||||
reimported = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(reimported)
|
||||
assert _public_names(reimported) == _public_names(common_module)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue