From 2dfc9b93d4a611ea7317ba8a5e505861d9f2217a Mon Sep 17 00:00:00 2001 From: mateo-berri <277851410+mateo-berri@users.noreply.github.com> Date: Wed, 28 Oct 2026 21:25:21 -0700 Subject: [PATCH] refactor(types): keep /cache/delete on main's behavior Restores the cache delete route and its test to main, so this types PR changes no response. Rejecting a non-list keys is left for its own change, since an object keys deletes its keys on main today. --- litellm/proxy/caching_routes.py | 16 ++----------- tests/unit/proxy/test_caching_routes.py | 32 ------------------------- 2 files changed, 2 insertions(+), 46 deletions(-) diff --git a/litellm/proxy/caching_routes.py b/litellm/proxy/caching_routes.py index fe71ee121b1..775d00ed53e 100644 --- a/litellm/proxy/caching_routes.py +++ b/litellm/proxy/caching_routes.py @@ -2,8 +2,6 @@ from collections.abc import Mapping from typing import Final from fastapi import APIRouter, Depends, HTTPException, Request -from pydantic import ConfigDict, TypeAdapter, ValidationError, with_config -from typing_extensions import NotRequired, ReadOnly, TypedDict import litellm from litellm._logging import verbose_proxy_logger @@ -14,14 +12,6 @@ from litellm.proxy._types import ProxyErrorTypes, ProxyException from litellm.proxy.auth.user_api_key_auth import user_api_key_auth from litellm.types.caching import CachePingResponse, HealthCheckCacheParams - -@with_config(ConfigDict(extra="allow", strict=True)) -class _CacheDeleteRequest(TypedDict): - keys: ReadOnly[NotRequired[list[str | int | float] | None]] - - -_CACHE_DELETE_REQUEST: Final = TypeAdapter(_CacheDeleteRequest) - masker: Final = SensitiveDataMasker() router: Final = APIRouter( @@ -159,8 +149,8 @@ async def cache_delete(request: Request): if litellm.cache is None: raise HTTPException(status_code=503, detail="Cache not initialized. litellm.cache is None") - request_data: Final = _CACHE_DELETE_REQUEST.validate_python(await request.json()) - keys: Final = request_data.get("keys") + request_data: Final = await request.json() + keys: Final = request_data.get("keys", None) if litellm.cache.type == "redis": await litellm.cache.delete_cache_keys(keys=keys) @@ -172,8 +162,6 @@ async def cache_delete(request: Request): status_code=500, detail=f"Cache type {litellm.cache.type} does not support deleting a key. only `redis` is supported", ) - except ValidationError as e: - raise HTTPException(status_code=400, detail=e.errors(include_url=False, include_input=False)) except Exception as e: raise HTTPException( status_code=500, diff --git a/tests/unit/proxy/test_caching_routes.py b/tests/unit/proxy/test_caching_routes.py index 5acc2513fd1..8a59793495a 100644 --- a/tests/unit/proxy/test_caching_routes.py +++ b/tests/unit/proxy/test_caching_routes.py @@ -1,11 +1,8 @@ import json -from typing import Final -from unittest.mock import MagicMock import pytest from fastapi.testclient import TestClient from pydantic import ValidationError -from pytest_mock import MockerFixture @@ -55,35 +52,6 @@ def mock_redis_failure(mocker): return mock_cache -@pytest.fixture -def mock_redis_delete(mocker: MockerFixture) -> MagicMock: - mock_cache: Final = mocker.MagicMock() - mock_cache.type = "redis" - mock_cache.delete_cache_keys = mocker.AsyncMock() - mocker.patch.object(litellm, "cache", mock_cache) - return mock_cache - - -@pytest.mark.parametrize("keys", [["a-key", "b-key"], [12345, 1.5]]) -def test_cache_delete_passes_string_and_numeric_keys_to_the_cache( - mock_redis_delete: MagicMock, keys: list[str | int | float] -) -> None: - response: Final = client.post("/cache/delete", headers={"Authorization": "Bearer sk-9876"}, json={"keys": keys}) - - assert response.status_code == 200 - assert response.json() == {"status": "success"} - mock_redis_delete.delete_cache_keys.assert_awaited_once_with(keys=keys) - - -def test_cache_delete_rejects_keys_that_are_not_a_list_with_a_400_that_hides_them(mock_redis_delete: MagicMock) -> None: - response: Final = client.post("/cache/delete", headers={"Authorization": "Bearer sk-9876"}, json={"keys": "sk-secret-key"}) - - assert response.status_code == 400 - assert response.json()["detail"][0]["loc"] == ["keys"] - assert "sk-secret-key" not in response.text - mock_redis_delete.delete_cache_keys.assert_not_awaited() - - def test_cache_ping_success(mock_redis_success): """Test successful cache ping with regular response""" response = client.get("/cache/ping", headers={"Authorization": "Bearer sk-9876"})