diff --git a/litellm/proxy/auth/auth_utils.py b/litellm/proxy/auth/auth_utils.py index b2467457eb4..dd57fffc6de 100644 --- a/litellm/proxy/auth/auth_utils.py +++ b/litellm/proxy/auth/auth_utils.py @@ -3,7 +3,7 @@ import os import re import sys from collections.abc import Callable, Collection, Iterator, Mapping -from functools import lru_cache, partial +from functools import lru_cache from itertools import accumulate, chain, repeat from logging import Logger from types import MappingProxyType @@ -532,7 +532,7 @@ _BANNED_METADATA_PARAMS: Final[tuple[str, ...]] = tuple( ) -class _ClientSideStorageAllowlist(BaseModel): +class ClientSideStorageAllowlist(BaseModel): model_config = ConfigDict(frozen=True) allowed_client_side_s3_buckets: tuple[str, ...] | None = None @@ -542,7 +542,7 @@ class _ClientSideStorageAllowlist(BaseModel): def client_side_s3_bucket_check(general_settings: Mapping[str, object]) -> Callable[[str], bool]: - return _ClientSideStorageAllowlist.model_validate(general_settings).admits_s3_bucket + return ClientSideStorageAllowlist.model_validate(general_settings).admits_s3_bucket def _check_banned_params( diff --git a/litellm/proxy/rag_endpoints/endpoints.py b/litellm/proxy/rag_endpoints/endpoints.py index 4b06c430755..ea3c9036d20 100644 --- a/litellm/proxy/rag_endpoints/endpoints.py +++ b/litellm/proxy/rag_endpoints/endpoints.py @@ -767,8 +767,8 @@ async def rag_query( general_settings, llm_router, proxy_config, - select_data_generator, proxy_logging_obj, + select_data_generator, version, ) diff --git a/tests/unit/litellm_core_utils/test_cloud_storage_security.py b/tests/unit/litellm_core_utils/test_cloud_storage_security.py index dd9c16025ac..5e711d58d28 100644 --- a/tests/unit/litellm_core_utils/test_cloud_storage_security.py +++ b/tests/unit/litellm_core_utils/test_cloud_storage_security.py @@ -10,8 +10,8 @@ from litellm.litellm_core_utils.cloud_storage_security import ( MAX_FILE_ID_DECODE_PASSES, is_managed_cloud_storage_uri, is_managed_s3_uri, - names_an_unlisted_s3_bucket, media_file_ids, + names_an_unlisted_s3_bucket, s3_media_uris, ) diff --git a/tests/unit/proxy/rag_endpoints/test_rag_endpoints.py b/tests/unit/proxy/rag_endpoints/test_rag_endpoints.py index 79a2b950c31..680813bcc3e 100644 --- a/tests/unit/proxy/rag_endpoints/test_rag_endpoints.py +++ b/tests/unit/proxy/rag_endpoints/test_rag_endpoints.py @@ -7,6 +7,7 @@ Covers: import io import json +from typing import Final from unittest.mock import AsyncMock, MagicMock, patch import pytest @@ -1177,39 +1178,59 @@ class TestVectorStoreUploadControls: assert content_bytes == b"benign document text\n" - @pytest.mark.usefixtures("httpx_transport") @pytest.mark.parametrize("listed, expected_status", [(False, 403), (True, 200)]) def test_rag_query_checks_the_s3_image_bucket_before_search( - client_internal_user: TestClient, respx_mock: respx.MockRouter, monkeypatch: pytest.MonkeyPatch, - listed: bool, expected_status: int, + client_internal_user: TestClient, + respx_mock: respx.MockRouter, + monkeypatch: pytest.MonkeyPatch, + listed: bool, + expected_status: int, ) -> None: monkeypatch.setenv("OPENAI_API_KEY", "sk-test") - search = respx_mock.post("https://api.openai.com/v1/vector_stores/provider-native-store/search").respond( - json={"object": "vector_store.search_results.page", "search_query": ["hello"], "data": [], - "has_more": False, "next_page": None} + search: Final = respx_mock.post("https://api.openai.com/v1/vector_stores/provider-native-store/search").respond( + json={ + "object": "vector_store.search_results.page", + "search_query": ["hello"], + "data": [], + "has_more": False, + "next_page": None, + } ) - completion = respx_mock.post("https://api.openai.com/v1/chat/completions").respond( - json={"id": "chatcmpl-test", "object": "chat.completion", "created": 1, "model": "gpt-4o-mini", - "choices": [{"index": 0, "message": {"role": "assistant", "content": "hello"}, - "finish_reason": "stop"}], - "usage": {"prompt_tokens": 1, "completion_tokens": 1, "total_tokens": 2}} + completion: Final = respx_mock.post("https://api.openai.com/v1/chat/completions").respond( + json={ + "id": "chatcmpl-test", + "object": "chat.completion", + "created": 1, + "model": "gpt-4o-mini", + "choices": [{"index": 0, "message": {"role": "assistant", "content": "hello"}, "finish_reason": "stop"}], + "usage": {"prompt_tokens": 1, "completion_tokens": 1, "total_tokens": 2}, + } ) with ( - patch("litellm.proxy.proxy_server.general_settings", - {"allowed_client_side_s3_buckets": ["private-bucket"]} if listed else {}), + patch( + "litellm.proxy.proxy_server.general_settings", + {"allowed_client_side_s3_buckets": ["private-bucket"]} if listed else {}, + ), patch("litellm.proxy.proxy_server.llm_router", None), patch("litellm.proxy.proxy_server.prisma_client", None), patch("litellm.vector_store_registry", None), ): - response = client_internal_user.post( + response: Final = client_internal_user.post( "/v1/rag/query", - json={"model": "gpt-4o-mini", - "messages": [{"role": "user", "content": [ - {"type": "text", "text": "hello"}, - {"type": "image_url", "image_url": {"url": "s3://private-bucket/cat.png"}} - ]}], - "retrieval_config": {"vector_store_id": "provider-native-store", "custom_llm_provider": "openai"}}, + json={ + "model": "gpt-4o-mini", + "messages": [ + { + "role": "user", + "content": [ + {"type": "text", "text": "hello"}, + {"type": "image_url", "image_url": {"url": "s3://private-bucket/cat.png"}}, + ], + } + ], + "retrieval_config": {"vector_store_id": "provider-native-store", "custom_llm_provider": "openai"}, + }, ) assert response.status_code == expected_status, response.text assert search.call_count == int(listed)