diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index bf2143e4a12..7ae79aa666f 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -4,3 +4,4 @@ /model_prices_and_context_window.json @mateo-berri /litellm/model_prices_and_context_window_backup.json @mateo-berri /litellm-proxy-extras/litellm_proxy_extras/migrations/ @yuneng-berri @ryan-crabbe-berri +/.github/CODEOWNERS @yuneng-berri diff --git a/.github/workflows/image-scan.yml b/.github/workflows/image-scan.yml index 8faf3ef6229..d798df4c3a4 100644 --- a/.github/workflows/image-scan.yml +++ b/.github/workflows/image-scan.yml @@ -17,6 +17,8 @@ on: - backend/Dockerfile - backend/main.py - docker/component_entrypoint.sh + - docker/entrypoint.sh + - litellm/proxy/prisma_migration.py - litellm-proxy-extras/** - tests/proxy_migration_tests/** - uv.lock diff --git a/Dockerfile b/Dockerfile index 66ce3af4a65..700b0d6525e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,10 +1,10 @@ # syntax=docker/dockerfile:1.7 # Base image for building -ARG LITELLM_BUILD_IMAGE=cgr.dev/chainguard/wolfi-base@sha256:42df77a9974d6ec8b17a5ee8bc23b532600a44d705acef2409e0933c1251b45f +ARG LITELLM_BUILD_IMAGE=cgr.dev/chainguard/wolfi-base@sha256:a31344ab2cb8618db84f535eec56f76f6178b142cb92cb2e48676cc2dcebea72 # Runtime image -ARG LITELLM_RUNTIME_IMAGE=cgr.dev/chainguard/wolfi-base@sha256:42df77a9974d6ec8b17a5ee8bc23b532600a44d705acef2409e0933c1251b45f +ARG LITELLM_RUNTIME_IMAGE=cgr.dev/chainguard/wolfi-base@sha256:a31344ab2cb8618db84f535eec56f76f6178b142cb92cb2e48676cc2dcebea72 ARG UV_IMAGE=ghcr.io/astral-sh/uv:0.11.7@sha256:240fb85ab0f263ef12f492d8476aa3a2e4e1e333f7d67fbdd923d00a506a516a # Pinned by digest like the other base images; bump explicitly on Node upgrades. ARG UI_BUILD_IMAGE=node:24.19-alpine3.24@sha256:d32cdf619f63fe0471182d08996dd516c6275bb5fd31ae06e55a570bd9e1ad43 diff --git a/backend/Dockerfile b/backend/Dockerfile index 853c74b05ca..4ca40944606 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -1,5 +1,5 @@ -ARG LITELLM_BUILD_IMAGE=cgr.dev/chainguard/wolfi-base@sha256:42df77a9974d6ec8b17a5ee8bc23b532600a44d705acef2409e0933c1251b45f -ARG LITELLM_RUNTIME_IMAGE=cgr.dev/chainguard/wolfi-base@sha256:42df77a9974d6ec8b17a5ee8bc23b532600a44d705acef2409e0933c1251b45f +ARG LITELLM_BUILD_IMAGE=cgr.dev/chainguard/wolfi-base@sha256:a31344ab2cb8618db84f535eec56f76f6178b142cb92cb2e48676cc2dcebea72 +ARG LITELLM_RUNTIME_IMAGE=cgr.dev/chainguard/wolfi-base@sha256:a31344ab2cb8618db84f535eec56f76f6178b142cb92cb2e48676cc2dcebea72 ARG UV_IMAGE=ghcr.io/astral-sh/uv:0.11.7@sha256:240fb85ab0f263ef12f492d8476aa3a2e4e1e333f7d67fbdd923d00a506a516a FROM $UV_IMAGE AS uvbin diff --git a/docker/Dockerfile.database b/docker/Dockerfile.database index 4bf3ae2b417..f0d6d02fccf 100644 --- a/docker/Dockerfile.database +++ b/docker/Dockerfile.database @@ -1,10 +1,10 @@ # syntax=docker/dockerfile:1.7 # Base image for building -ARG LITELLM_BUILD_IMAGE=cgr.dev/chainguard/wolfi-base@sha256:42df77a9974d6ec8b17a5ee8bc23b532600a44d705acef2409e0933c1251b45f +ARG LITELLM_BUILD_IMAGE=cgr.dev/chainguard/wolfi-base@sha256:a31344ab2cb8618db84f535eec56f76f6178b142cb92cb2e48676cc2dcebea72 # Runtime image -ARG LITELLM_RUNTIME_IMAGE=cgr.dev/chainguard/wolfi-base@sha256:42df77a9974d6ec8b17a5ee8bc23b532600a44d705acef2409e0933c1251b45f +ARG LITELLM_RUNTIME_IMAGE=cgr.dev/chainguard/wolfi-base@sha256:a31344ab2cb8618db84f535eec56f76f6178b142cb92cb2e48676cc2dcebea72 ARG UV_IMAGE=ghcr.io/astral-sh/uv:0.11.7@sha256:240fb85ab0f263ef12f492d8476aa3a2e4e1e333f7d67fbdd923d00a506a516a # Pinned by digest like the other base images; bump explicitly on Node upgrades. ARG UI_BUILD_IMAGE=node:24.19-alpine3.24@sha256:d32cdf619f63fe0471182d08996dd516c6275bb5fd31ae06e55a570bd9e1ad43 diff --git a/docker/Dockerfile.non_root b/docker/Dockerfile.non_root index 7392cc09a0d..4a5df6ecd69 100644 --- a/docker/Dockerfile.non_root +++ b/docker/Dockerfile.non_root @@ -1,8 +1,8 @@ # syntax=docker/dockerfile:1.7 # Base images -ARG LITELLM_BUILD_IMAGE=cgr.dev/chainguard/wolfi-base@sha256:42df77a9974d6ec8b17a5ee8bc23b532600a44d705acef2409e0933c1251b45f -ARG LITELLM_RUNTIME_IMAGE=cgr.dev/chainguard/wolfi-base@sha256:42df77a9974d6ec8b17a5ee8bc23b532600a44d705acef2409e0933c1251b45f +ARG LITELLM_BUILD_IMAGE=cgr.dev/chainguard/wolfi-base@sha256:a31344ab2cb8618db84f535eec56f76f6178b142cb92cb2e48676cc2dcebea72 +ARG LITELLM_RUNTIME_IMAGE=cgr.dev/chainguard/wolfi-base@sha256:a31344ab2cb8618db84f535eec56f76f6178b142cb92cb2e48676cc2dcebea72 ARG PROXY_EXTRAS_SOURCE=published ARG UV_IMAGE=ghcr.io/astral-sh/uv:0.11.7@sha256:240fb85ab0f263ef12f492d8476aa3a2e4e1e333f7d67fbdd923d00a506a516a # Pinned by digest like the other base images; bump explicitly on Node upgrades. diff --git a/enterprise/litellm_enterprise/proxy/hooks/managed_files.py b/enterprise/litellm_enterprise/proxy/hooks/managed_files.py index c986e835e4f..39f8de0b0cc 100644 --- a/enterprise/litellm_enterprise/proxy/hooks/managed_files.py +++ b/enterprise/litellm_enterprise/proxy/hooks/managed_files.py @@ -45,6 +45,8 @@ from litellm.proxy._types import ( UserAPIKeyAuth, ) from litellm.proxy.openai_files_endpoints.common_utils import ( + FILE_LIST_CONTINUATION_CHUNK_SIZE, + MAX_FILE_LIST_LIMIT, _is_base64_encoded_unified_file_id, apply_unified_file_ids, ensure_batch_response_managed_file_ids, @@ -54,6 +56,8 @@ from litellm.proxy.openai_files_endpoints.common_utils import ( map_raw_file_ids_to_unified, normalize_mime_type_for_provider, resolve_managed_output_file_model_name, + validate_file_list_limit, + validate_file_list_purpose, ) from litellm.proxy.pass_through_endpoints.llm_provider_handlers.batch_attribution import ( request_tags_from_metadata, @@ -63,9 +67,9 @@ from litellm.types.llms.openai import ( # pyright: ignore[reportAttributeAccess AsyncCursorPage, ChatCompletionFileObject, CreateFileRequest, + FileListPage, FileObject, OpenAIFileObject, - OpenAIFilesPurpose, ResponsesAPIResponse, ) from litellm.types.utils import ( @@ -144,7 +148,14 @@ class _ManagedFileRow(Protocol): class _ManagedFileTableActions(Protocol): async def find_first(self, where: Mapping[str, object]) -> Optional[_ManagedFileRow]: ... - async def find_many(self, where: Mapping[str, object]) -> Sequence[_ManagedFileRow]: ... + async def find_many( + self, + where: Mapping[str, object], + take: int = ..., + order: Union[Mapping[str, str], Sequence[Mapping[str, str]]] = ..., + cursor: Mapping[str, str] = ..., + skip: int = ..., + ) -> Sequence[_ManagedFileRow]: ... async def upsert(self, where: Mapping[str, str], data: Mapping[str, Mapping[str, object]]) -> _ManagedFileRow: ... @@ -1365,12 +1376,76 @@ class _PROXY_LiteLLMManagedFiles(CustomLogger, BaseFileEndpoints): async def afile_list( self, - purpose: Optional[OpenAIFilesPurpose], + purpose: Optional[str], litellm_parent_otel_span: Optional[Span], + user_api_key_dict: UserAPIKeyAuth, + limit: Optional[int] = None, + after: Optional[str] = None, **data: Dict, - ) -> List[OpenAIFileObject]: - """Handled in files_endpoints.py""" - return [] + ) -> FileListPage: + """List the managed files the caller owns, newest first. + + Pagination is keyset based on ``unified_file_id`` so a key that owns + every file on the proxy still reads one bounded page at a time. + ``purpose`` is applied after parsing, because the managed file table + keeps it inside the ``file_object`` blob instead of a column, and rows + whose blob will not parse drop out there too, so a chunk of rows can + yield fewer matches than the page holds. Successive chunks are read + until the page is full or the caller's rows run out, which keeps + ``data`` non-empty while matches remain and its last id usable as the + next cursor. A first chunk that fills the page costs one query; once a + scan has to continue past it, the chunk widens to + ``FILE_LIST_CONTINUATION_CHUNK_SIZE``, so the walk costs one query per + that many rows instead of one per page. That bound is per query, not + per request: the work is still linear in the rows the caller owns, and + a filter matching nothing reads every one of them, with no index + covering either the owner filter or the sort. + """ + validate_file_list_limit(limit) + validate_file_list_purpose(purpose) + + owner_filter: Final = build_owner_filter(user_api_key_dict) + if owner_filter is None: + return FileListPage(**build_list_page([])) + + if after: + cursor_row = await _managed_file_table(self.prisma_client).find_first( + where={**owner_filter, "unified_file_id": after} + ) + if cursor_row is None: + raise ProxyException( + message=f"Invalid 'after' cursor: no file found with id '{after}'.", + type="invalid_request_error", + param="after", + code=400, + openai_code="invalid_value", + ) + + page_size: Final = min(limit or MAX_FILE_LIST_LIMIT, MAX_FILE_LIST_LIMIT) + matches: Final[List[OpenAIFileObject]] = [] + cursor_id = after + chunk_size = page_size + 1 + + while len(matches) <= page_size: + cursor_args: _CursorPageArgs = {"cursor": {"unified_file_id": cursor_id}, "skip": 1} if cursor_id else {} + chunk = await _managed_file_table(self.prisma_client).find_many( + where=owner_filter, + take=chunk_size, + order=[{"created_at": "desc"}, {"unified_file_id": "desc"}], + **cursor_args, + ) + matches.extend( + parsed_file_object.model_copy(update={"id": row.unified_file_id}) + for row in chunk + if (parsed_file_object := _parse_managed_file_object(row.file_object, row.unified_file_id)) is not None + and (purpose is None or parsed_file_object.purpose == purpose) + ) + if len(chunk) < chunk_size: + break + cursor_id = chunk[-1].unified_file_id + chunk_size = max(chunk_size, FILE_LIST_CONTINUATION_CHUNK_SIZE) + + return FileListPage(**build_list_page(matches[:page_size], has_more=len(matches) > page_size)) def _is_batch_polling_enabled(self) -> bool: """ diff --git a/enterprise/pyproject.toml b/enterprise/pyproject.toml index 8bbde7f3764..ccfe7eda5e2 100644 --- a/enterprise/pyproject.toml +++ b/enterprise/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "litellm-enterprise" -version = "0.1.58" +version = "0.1.59" description = "Package for LiteLLM Enterprise features" readme = "README.md" requires-python = ">=3.9" @@ -26,7 +26,7 @@ required-version = ">=0.10.9" module-root = "" [tool.commitizen] -version = "0.1.58" +version = "0.1.59" version_files = [ "pyproject.toml:^version", "../pyproject.toml:litellm-enterprise==", diff --git a/gateway/Dockerfile b/gateway/Dockerfile index 223df524d7c..4a2e32e186e 100644 --- a/gateway/Dockerfile +++ b/gateway/Dockerfile @@ -1,5 +1,5 @@ -ARG LITELLM_BUILD_IMAGE=cgr.dev/chainguard/wolfi-base@sha256:42df77a9974d6ec8b17a5ee8bc23b532600a44d705acef2409e0933c1251b45f -ARG LITELLM_RUNTIME_IMAGE=cgr.dev/chainguard/wolfi-base@sha256:42df77a9974d6ec8b17a5ee8bc23b532600a44d705acef2409e0933c1251b45f +ARG LITELLM_BUILD_IMAGE=cgr.dev/chainguard/wolfi-base@sha256:a31344ab2cb8618db84f535eec56f76f6178b142cb92cb2e48676cc2dcebea72 +ARG LITELLM_RUNTIME_IMAGE=cgr.dev/chainguard/wolfi-base@sha256:a31344ab2cb8618db84f535eec56f76f6178b142cb92cb2e48676cc2dcebea72 ARG UV_IMAGE=ghcr.io/astral-sh/uv:0.11.7@sha256:240fb85ab0f263ef12f492d8476aa3a2e4e1e333f7d67fbdd923d00a506a516a FROM $UV_IMAGE AS uvbin diff --git a/litellm-proxy-extras/pyproject.toml b/litellm-proxy-extras/pyproject.toml index 26d42a33b29..98a3d8d535e 100644 --- a/litellm-proxy-extras/pyproject.toml +++ b/litellm-proxy-extras/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "litellm-proxy-extras" -version = "0.4.88" +version = "0.4.89" description = "Additional files for the LiteLLM Proxy. Reduces the size of the main litellm package." readme = "README.md" requires-python = ">=3.9" @@ -26,7 +26,7 @@ required-version = ">=0.10.9" module-root = "" [tool.commitizen] -version = "0.4.88" +version = "0.4.89" version_files = [ "pyproject.toml:^version", "../pyproject.toml:litellm-proxy-extras==", diff --git a/litellm/integrations/otel/__init__.py b/litellm/integrations/otel/__init__.py index 9c1205bb277..d7627d4d63d 100644 --- a/litellm/integrations/otel/__init__.py +++ b/litellm/integrations/otel/__init__.py @@ -49,6 +49,7 @@ from litellm.integrations.otel.model.semconv import ( Error, GenAI, GenAIOperation, + GenAIOutputType, GenAIProvider, JsonRpc, LiteLLM, @@ -60,6 +61,7 @@ from litellm.integrations.otel.model.semconv import ( RpcSystem, Server, resolve_operation, + resolve_output_type, resolve_provider, ) from litellm.integrations.otel.model.spans import ( @@ -84,6 +86,7 @@ __all__ = [ "Error", "GenAI", "GenAIOperation", + "GenAIOutputType", "GenAIProvider", "GuardrailSpanData", "JsonRpc", @@ -116,6 +119,7 @@ __all__ = [ "is_otel_v2_enabled", "promoted_baggage", "resolve_operation", + "resolve_output_type", "resolve_provider", "span_role_for_service", "validate_registry", diff --git a/litellm/integrations/otel/mappers/genai.py b/litellm/integrations/otel/mappers/genai.py index 79487e69ac4..5e3401cd62c 100644 --- a/litellm/integrations/otel/mappers/genai.py +++ b/litellm/integrations/otel/mappers/genai.py @@ -42,6 +42,7 @@ class GenAIMapper: _LLM_CALL_ATTRS: dict[str, Callable[[LLMCallSpanData], AttrValue | None]] = { GenAI.OPERATION_NAME: lambda d: d.operation.value, GenAI.PROVIDER_NAME: lambda d: d.provider or None, + GenAI.OUTPUT_TYPE: lambda d: d.output_type.value if d.output_type else None, GenAI.REQUEST_MODEL: lambda d: d.request_model or None, GenAI.REQUEST_TEMPERATURE: lambda d: d.request_params.temperature, GenAI.REQUEST_TOP_P: lambda d: d.request_params.top_p, @@ -65,6 +66,7 @@ class GenAIMapper: Server.ADDRESS: lambda d: d.server.address if d.server else None, Server.PORT: lambda d: d.server.port if d.server else None, LiteLLM.CALL_ID: lambda d: d.identity.call_id or None, + LiteLLM.CALL_TYPE: lambda d: d.call_type, # The provider/underlying model is only known once routing has picked a # deployment, so it can't ride identity Baggage (seeded at auth, before # routing) onto the boundary-born LLM span — stamp it directly here. diff --git a/litellm/integrations/otel/model/payloads.py b/litellm/integrations/otel/model/payloads.py index aba9cc80240..4e4ed4b7513 100644 --- a/litellm/integrations/otel/model/payloads.py +++ b/litellm/integrations/otel/model/payloads.py @@ -15,8 +15,10 @@ from litellm.integrations.otel.model.metadata import ( ) from litellm.integrations.otel.model.semconv import ( GenAIOperation, + GenAIOutputType, MCPMethod, resolve_operation, + resolve_output_type, resolve_provider, ) from litellm.integrations.otel.model.utils import ( @@ -310,6 +312,11 @@ class LLMCallSpanData: choices_out: tuple[Mapping[str, object], ...] = () system_fingerprint: str | None = None time_to_first_chunk_seconds: float | None = None + # The requested output modality, set only on the routes that pin one (image + # generation, speech, transcription, OCR), and the litellm route itself, which + # keeps routes the convention folds into one operation distinguishable. + output_type: GenAIOutputType | None = None + call_type: str | None = None @classmethod def from_standard_logging_payload( @@ -334,8 +341,9 @@ class LLMCallSpanData: # otherwise the content-bearing mappers receive empty sequences and emit # no prompt/response text. finish_reasons: Final = _finish_reasons(choices_out) + call_type: Final = as_str(payload.get("call_type")) return cls( - operation=resolve_operation(as_str(payload.get("call_type"))), + operation=resolve_operation(call_type), provider=resolve_provider(as_str(payload.get("custom_llm_provider"))), request_model=context.request_model, response_model=context.response_model, @@ -358,6 +366,8 @@ class LLMCallSpanData: choices_out=choices_out if capture_content else (), system_fingerprint=as_str(response.get("system_fingerprint")), time_to_first_chunk_seconds=time_to_first_chunk_seconds, + output_type=resolve_output_type(call_type), + call_type=call_type or None, ) diff --git a/litellm/integrations/otel/model/semconv.py b/litellm/integrations/otel/model/semconv.py index ada2822ba66..1647e0a5bd1 100644 --- a/litellm/integrations/otel/model/semconv.py +++ b/litellm/integrations/otel/model/semconv.py @@ -3,7 +3,9 @@ Keys follow the OpenTelemetry GenAI semantic conventions (experimental). Anythin without a semconv equivalent lives under the ``litellm.*`` vendor namespace. """ +from collections.abc import Mapping from enum import Enum +from types import MappingProxyType from typing import Final from litellm._logging import verbose_logger @@ -30,6 +32,21 @@ class GenAIOperation(str, Enum): EXECUTE_TOOL = "execute_tool" # MCP tool-call spans LITELLM_VECTOR_STORE_MANAGEMENT = "litellm.vector_store_management" LITELLM_VECTOR_STORE_FILE_MANAGEMENT = "litellm.vector_store_file_management" + LITELLM_MODERATION = "litellm.moderation" + + +class GenAIOutputType(str, Enum): + """Values for ``gen_ai.output.type``, the modality the client asked for. + + It is what separates the inference routes that share ``generate_content``: + image generation requests ``image``, speech requests ``speech``, and + transcription and OCR both request ``text``. + """ + + TEXT = "text" + JSON = "json" + IMAGE = "image" + SPEECH = "speech" class GenAIProvider(str, Enum): @@ -258,6 +275,11 @@ class LiteLLM: """Vendor-extension keys (no semconv equivalent). Always ``litellm.*``.""" CALL_ID: Final = "litellm.call_id" + # The litellm route that produced the call. Needed because the convention maps + # several routes onto one operation: transcription and OCR are both + # ``generate_content`` with a ``text`` output type, so this is the only thing + # that tells them apart. + CALL_TYPE: Final = "litellm.call_type" COST_PREFIX: Final = "litellm.cost." METADATA_PREFIX: Final = "litellm.metadata." TEAM_ID: Final = "litellm.team.id" @@ -352,6 +374,16 @@ _OPERATION_BY_CALL_TYPE: Final[dict[str, GenAIOperation]] = { "aembedding": GenAIOperation.EMBEDDINGS, "responses": GenAIOperation.CHAT, "aresponses": GenAIOperation.CHAT, + "image_generation": GenAIOperation.GENERATE_CONTENT, + "aimage_generation": GenAIOperation.GENERATE_CONTENT, + "moderation": GenAIOperation.LITELLM_MODERATION, + "amoderation": GenAIOperation.LITELLM_MODERATION, + "ocr": GenAIOperation.GENERATE_CONTENT, + "aocr": GenAIOperation.GENERATE_CONTENT, + "speech": GenAIOperation.GENERATE_CONTENT, + "aspeech": GenAIOperation.GENERATE_CONTENT, + "transcription": GenAIOperation.GENERATE_CONTENT, + "atranscription": GenAIOperation.GENERATE_CONTENT, "call_mcp_tool": GenAIOperation.EXECUTE_TOOL, "vector_store_search": GenAIOperation.RETRIEVAL, "avector_store_search": GenAIOperation.RETRIEVAL, @@ -385,6 +417,23 @@ _OPERATION_BY_CALL_TYPE: Final[dict[str, GenAIOperation]] = { } +# litellm ``call_type`` -> ``gen_ai.output.type``. Only the call types whose route +# fixes the requested modality are listed; the attribute is conditionally required +# on a request that asks for an output format, so anything else is left unstamped. +_OUTPUT_TYPE_BY_CALL_TYPE: Final[Mapping[str, GenAIOutputType]] = MappingProxyType( + { + "image_generation": GenAIOutputType.IMAGE, + "aimage_generation": GenAIOutputType.IMAGE, + "speech": GenAIOutputType.SPEECH, + "aspeech": GenAIOutputType.SPEECH, + "transcription": GenAIOutputType.TEXT, + "atranscription": GenAIOutputType.TEXT, + "ocr": GenAIOutputType.TEXT, + "aocr": GenAIOutputType.TEXT, + } +) + + def resolve_provider(custom_llm_provider: str | None) -> str: """Map a litellm provider string to a ``gen_ai.provider.name`` value. @@ -416,3 +465,11 @@ def resolve_operation(call_type: str | None) -> GenAIOperation: GenAIOperation.CHAT.value, ) return GenAIOperation.CHAT + + +def resolve_output_type(call_type: str | None) -> GenAIOutputType | None: + """Map a litellm ``call_type`` to a ``gen_ai.output.type`` value, or ``None`` + for a route that doesn't pin the output modality.""" + if not call_type: + return None + return _OUTPUT_TYPE_BY_CALL_TYPE.get(call_type.lower()) diff --git a/litellm/integrations/websearch_interception/ARCHITECTURE.md b/litellm/integrations/websearch_interception/ARCHITECTURE.md index ce7f01c5a2a..4ea7a7ae527 100644 --- a/litellm/integrations/websearch_interception/ARCHITECTURE.md +++ b/litellm/integrations/websearch_interception/ARCHITECTURE.md @@ -207,6 +207,59 @@ response = await litellm.messages.acreate( --- +## Loop Ceiling + +One intercepted request can chain several follow-up model calls, since the model often searches again after +reading the first set of results. `max_agentic_loops` caps how many of those follow-ups run, and it defaults +to 3. LiteLLM also breaks the loop early when the model asks for the exact same tool call twice in a row. + +Set the ceiling on the feature, which the interceptor applies to `/v1/messages` requests: + +```yaml +litellm_settings: + websearch_interception_params: + enabled_providers: ["bedrock"] + max_agentic_loops: 5 +``` + +Or per deployment, which wins over the feature-level setting: + +```yaml +model_list: + - model_name: claude-sonnet-4-5 + litellm_params: + model: bedrock/us.anthropic.claude-sonnet-4-5-20250929-v1:0 + max_agentic_loops: 5 +``` + +Clients cannot set it. `max_agentic_loops` is on the proxy's untrusted-field list, so a request body that +carries it is ignored and one request can never drive an unbounded number of upstream model calls. + +Both places are validated at config load, and a value that is not an integer of at least 1 stops the proxy +from starting rather than surfacing later. The per-deployment one is checked while the model list is read, +not on `LiteLLM_Params`, because the proxy builds its router with `ignore_invalid_deployments=True` and a +validator down there would drop the deployment silently instead of refusing to start. + +When the ceiling is reached on a non-streaming `/v1/messages` request, the turn ends there and the client gets +the last response back with the internal `litellm_web_search` tool call removed and `stop_reason: end_turn`. +The client never declared that tool, so leaving the block in would hand it a tool call it has no way to answer. +The answer can be less complete than it would have been with more loops, which is the tradeoff the ceiling +buys. Where the refused call was the only block left, the turn comes back with no text in it at all. + +Non-streaming is not a limitation on the client here, because a client that asked for a stream gets the same +treatment. Interception converts an intercepted `stream=True` request to non-streaming before the loop runs and +rebuilds the SSE stream from the finalized turn afterwards, so the ceiling is always reached on a response the +client has not seen yet. `AgenticStreamingIterator` is the one caller that reaches the loop with its events +already on the wire, and it keeps raising, because a finalized turn would arrive there as a second message +rather than as a replacement. + +Two other surfaces do not get that treatment yet. `/v1/responses` returns its own shape that the finalizer does +not rewrite, so it still hands back the internal call. And `/v1/chat/completions` runs its own copy of these +rails in `litellm_core_utils/chat_completion_agentic_loop.py`, which still raises rather than ending the turn. +Both are tracked separately + +--- + ## Streaming Support WebSearch interception works transparently with both streaming and non-streaming requests. diff --git a/litellm/integrations/websearch_interception/handler.py b/litellm/integrations/websearch_interception/handler.py index e59ef0449d0..13a16947fb4 100644 --- a/litellm/integrations/websearch_interception/handler.py +++ b/litellm/integrations/websearch_interception/handler.py @@ -31,6 +31,9 @@ from litellm.integrations.websearch_interception.tools import ( from litellm.integrations.websearch_interception.transformation import ( WebSearchTransformation, ) +from litellm.litellm_core_utils.agentic_loop_settings import ( + validated_max_agentic_loops, +) from litellm.llms.base_llm.search.transformation import SearchResponse from litellm.types.integrations.custom_logger import ( CHAT_COMPLETION_AGENTIC_SURFACE, @@ -122,6 +125,7 @@ class WebSearchInterceptionLogger(CustomLogger): self, enabled_providers: list[LlmProviders | str] | None = None, search_tool_name: str | None = None, + max_agentic_loops: int | None = None, ): """ Args: @@ -131,6 +135,9 @@ class WebSearchInterceptionLogger(CustomLogger): Default: None (all providers enabled) search_tool_name: Name of search tool configured in router's search_tools. If None, will attempt to use first available search tool. + max_agentic_loops: How many follow-up model calls one intercepted request + may chain before the loop is refused and the turn ends. + If None, LiteLLM's default of 3 applies. """ super().__init__() # Convert enum values to strings for comparison @@ -139,8 +146,16 @@ class WebSearchInterceptionLogger(CustomLogger): else: self.enabled_providers = [p.value if isinstance(p, LlmProviders) else p for p in enabled_providers] self.search_tool_name = search_tool_name + self.max_agentic_loops = self._validated_max_agentic_loops(max_agentic_loops) self._request_has_websearch = False # Track if current request has web search + @staticmethod + def _validated_max_agentic_loops(max_agentic_loops: object) -> int | None: + """ + Reject loop ceilings the agentic loop cannot honor, at config load time. + """ + return validated_max_agentic_loops(max_agentic_loops, field="websearch_interception_params.max_agentic_loops") + async def try_short_circuit_search( self, model: str, @@ -398,6 +413,7 @@ class WebSearchInterceptionLogger(CustomLogger): websearch_interception_params: enabled_providers: ["bedrock"] search_tool_name: "my-perplexity-search" + max_agentic_loops: 5 Usage: config = litellm_settings.get("websearch_interception_params", {}) @@ -406,6 +422,7 @@ class WebSearchInterceptionLogger(CustomLogger): # Extract parameters from config enabled_providers_str: Final = config.get("enabled_providers", None) search_tool_name: Final = config.get("search_tool_name", None) + max_agentic_loops: Final = config.get("max_agentic_loops", None) # Convert string provider names to LlmProviders enum values enabled_providers: list[LlmProviders | str] | None = None @@ -423,6 +440,7 @@ class WebSearchInterceptionLogger(CustomLogger): return cls( enabled_providers=enabled_providers, search_tool_name=search_tool_name, + max_agentic_loops=max_agentic_loops, ) @staticmethod @@ -493,6 +511,10 @@ class WebSearchInterceptionLogger(CustomLogger): verbose_logger.debug("WebSearchInterception: Pre-request hook triggered for provider=%s", custom_llm_provider) + deployment_max_agentic_loops: Final = kwargs.get("max_agentic_loops") + if self.max_agentic_loops is not None and deployment_max_agentic_loops is None: + kwargs["max_agentic_loops"] = self.max_agentic_loops # rebind-ok: this hook returns the kwargs it edits + # If the client sent an Anthropic-native web_search_* tool, mark the # request so the agentic loop emits native web_search_tool_result # blocks in the final response (for citations panels, etc.). The flag diff --git a/litellm/litellm_core_utils/agentic_loop_settings.py b/litellm/litellm_core_utils/agentic_loop_settings.py new file mode 100644 index 00000000000..3dd8d437aef --- /dev/null +++ b/litellm/litellm_core_utils/agentic_loop_settings.py @@ -0,0 +1,59 @@ +""" +Shared validation for the agentic loop ceiling. + +``max_agentic_loops`` can be set in two places, and the two disagreed about +what a bad value means. The feature-level +``litellm_settings.websearch_interception_params.max_agentic_loops`` was +checked at config load, while a per-deployment +``model_list[].litellm_params.max_agentic_loops`` was passed straight through +to ``int(... or 3)``. That let a per-deployment ``0`` read as the default 3, +turning the tightest ceiling into the loosest one, and let a per-deployment +``"three"`` boot the proxy and then fail every request to that model. + +Both settings now go through :func:`validated_max_agentic_loops`, which names +the field it rejected so the error says which line of the config to fix. + +Anything that spells a whole number is still accepted, because the old +``int(... or 3)`` accepted those and a ceiling is routinely parameterized as +``max_agentic_loops: os.environ/MAX_AGENTIC_LOOPS``, which resolves to a +string. Rejecting ``"5"`` would stop such a proxy from booting on upgrade. +""" + +from typing import Final + +DEFAULT_MAX_AGENTIC_LOOPS: Final = 3 + + +def _as_whole_number(value: object) -> int | None: + """ + Return ``value`` as an int when it spells a whole number, else ``None``. + + ``bool`` is excluded explicitly because it is an ``int`` subclass, so + ``max_agentic_loops: true`` would otherwise be read as a ceiling of 1. + """ + if isinstance(value, bool): + return None + if isinstance(value, int): + return value + if isinstance(value, float): + return int(value) if value.is_integer() else None + if isinstance(value, str): + try: + return int(value.strip()) + except ValueError: + return None + return None + + +def validated_max_agentic_loops(max_agentic_loops: object, field: str) -> int | None: + """ + Return ``max_agentic_loops`` as an int, or raise naming ``field``. + """ + if max_agentic_loops is None: + return None + ceiling: Final = _as_whole_number(max_agentic_loops) + if ceiling is None: + raise TypeError(f"{field} must be an integer, got {max_agentic_loops!r}") + if ceiling < 1: + raise ValueError(f"{field} must be at least 1, got {ceiling}") + return ceiling diff --git a/litellm/litellm_core_utils/chat_completion_agentic_loop.py b/litellm/litellm_core_utils/chat_completion_agentic_loop.py index b91c1785a54..07bed1f88ad 100644 --- a/litellm/litellm_core_utils/chat_completion_agentic_loop.py +++ b/litellm/litellm_core_utils/chat_completion_agentic_loop.py @@ -5,6 +5,10 @@ from typing import Final, cast from litellm._logging import verbose_logger from litellm.integrations.custom_logger import CustomLogger +from litellm.litellm_core_utils.agentic_loop_settings import ( + DEFAULT_MAX_AGENTIC_LOOPS, + validated_max_agentic_loops, +) from litellm.types.integrations.custom_logger import ( CHAT_COMPLETION_AGENTIC_SURFACE, NON_CODE_INTERPRETER_INTERCEPTION_INTERNAL_PREFIXES, @@ -52,7 +56,10 @@ def _coerce_int(value: object, default: int) -> int: def _agentic_loop_settings(kwargs: dict[str, object]) -> tuple[int, int, list[str]]: depth: Final = _coerce_int(kwargs.get("_agentic_loop_depth"), 0) - max_loops: Final = max(_coerce_int(kwargs.get("max_agentic_loops"), 3), 1) + configured: Final = validated_max_agentic_loops( + kwargs.get("max_agentic_loops"), field="litellm_params.max_agentic_loops" + ) + max_loops: Final = DEFAULT_MAX_AGENTIC_LOOPS if configured is None else configured raw_fingerprints: Final = kwargs.get("_agentic_loop_fingerprints") fingerprints: Final = [str(fp) for fp in raw_fingerprints] if isinstance(raw_fingerprints, list) else [] return depth, max_loops, fingerprints diff --git a/litellm/litellm_core_utils/get_provider_specific_headers.py b/litellm/litellm_core_utils/get_provider_specific_headers.py index ab07a6af1b3..2618aee9afa 100644 --- a/litellm/litellm_core_utils/get_provider_specific_headers.py +++ b/litellm/litellm_core_utils/get_provider_specific_headers.py @@ -1,3 +1,4 @@ +from collections.abc import Sequence from typing import Final from litellm.types.utils import ProviderSpecificHeader @@ -6,13 +7,17 @@ from litellm.types.utils import ProviderSpecificHeader class ProviderSpecificHeaderUtils: @staticmethod def get_provider_specific_headers( - provider_specific_header: ProviderSpecificHeader | None, + provider_specific_header: ProviderSpecificHeader | Sequence[ProviderSpecificHeader] | None, custom_llm_provider: str | None, ) -> dict: """ Get the provider specific headers for the given custom llm provider. - Supports comma-separated provider lists for headers that work across multiple providers. + Accepts either a single ProviderSpecificHeader or a sequence of them. Each entry + carries its own comma-separated provider list, so headers that are safe for several + providers and headers that are safe for exactly one can travel on the same request + without sharing a scope. Entries whose provider list does not contain + `custom_llm_provider` contribute nothing. Returns: Dict: The provider specific headers for the given custom llm provider @@ -20,10 +25,15 @@ class ProviderSpecificHeaderUtils: if provider_specific_header is None or custom_llm_provider is None: return {} - stored_providers: Final = provider_specific_header.get("custom_llm_provider", "") - provider_list: Final = [p.strip() for p in stored_providers.split(",")] + scoped_headers: Final = ( + (provider_specific_header,) if isinstance(provider_specific_header, dict) else provider_specific_header + ) - if custom_llm_provider in provider_list: - return provider_specific_header.get("extra_headers", {}) + matched_headers: Final = {} + for scoped_header in scoped_headers: + stored_providers = scoped_header.get("custom_llm_provider", "") + provider_list = [p.strip() for p in stored_providers.split(",")] + if custom_llm_provider in provider_list: + matched_headers.update(scoped_header.get("extra_headers", {})) - return {} + return matched_headers diff --git a/litellm/litellm_core_utils/logging_utils.py b/litellm/litellm_core_utils/logging_utils.py index a17415f3ab8..91c8ba36b26 100644 --- a/litellm/litellm_core_utils/logging_utils.py +++ b/litellm/litellm_core_utils/logging_utils.py @@ -3,6 +3,7 @@ import functools import inspect import re import time +from collections.abc import Mapping from datetime import datetime from typing import TYPE_CHECKING, Any, Final @@ -268,6 +269,16 @@ def _set_duration_in_model_call_details( verbose_logger.warning("Error setting `llm_api_duration_ms`: %s", e) +def speech_request_body(model: str, voice: str, optional_params: Mapping[str, object]) -> Mapping[str, object]: + """Speech request body for telemetry, without the caller headers the provider SDKs + take as request kwargs rather than body fields.""" + return { # mutable-ok: loggers isinstance-check the request body as a dict + "model": model, + "voice": voice, + **{key: value for key, value in optional_params.items() if key != "extra_headers"}, + } + + def track_llm_api_timing(): """ Decorator to track LLM API call timing for both sync and async functions. diff --git a/litellm/litellm_core_utils/ptu_pricing.py b/litellm/litellm_core_utils/ptu_pricing.py index 2e73719cf52..021210d9175 100644 --- a/litellm/litellm_core_utils/ptu_pricing.py +++ b/litellm/litellm_core_utils/ptu_pricing.py @@ -124,6 +124,14 @@ def ptu_identity_error( return None +PTU_MODEL_INFO_FIELDS: Final = ("ptu_count", "cost_per_ptu_per_hour", "ptu_effective_from", "ptu_effective_to") + + +def declares_ptu(model_info: Mapping[str, object]) -> bool: + """Whether any PTU field is set here, including one too malformed to charge.""" + return any(model_info.get(field) is not None for field in PTU_MODEL_INFO_FIELDS) + + def ptu_config_error(model_info: Mapping[str, object], *, model_name: str | None = None) -> str | None: """Why this PTU configuration cannot be honoured, else None. diff --git a/litellm/llms/anthropic/experimental_pass_through/messages/fake_stream_iterator.py b/litellm/llms/anthropic/experimental_pass_through/messages/fake_stream_iterator.py index 215d4a5b42b..14f1b7697cf 100644 --- a/litellm/llms/anthropic/experimental_pass_through/messages/fake_stream_iterator.py +++ b/litellm/llms/anthropic/experimental_pass_through/messages/fake_stream_iterator.py @@ -113,6 +113,14 @@ class FakeAnthropicMessagesStreamIterator: } chunks.append(f"event: content_block_delta\ndata: {json.dumps(content_block_delta)}\n\n".encode()) + else: + passthrough_start: Final = { + "type": "content_block_start", + "index": index, + "content_block": block_dict, + } + chunks.append(f"event: content_block_start\ndata: {json.dumps(passthrough_start)}\n\n".encode()) + content_block_stop: Final = {"type": "content_block_stop", "index": index} chunks.append(f"event: content_block_stop\ndata: {json.dumps(content_block_stop)}\n\n".encode()) return chunks diff --git a/litellm/llms/azure/azure.py b/litellm/llms/azure/azure.py index c8f94b575ad..980b27cda55 100644 --- a/litellm/llms/azure/azure.py +++ b/litellm/llms/azure/azure.py @@ -17,7 +17,7 @@ from openai import ( import litellm from litellm.constants import AZURE_OPERATION_POLLING_TIMEOUT, DEFAULT_MAX_RETRIES from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj -from litellm.litellm_core_utils.logging_utils import track_llm_api_timing +from litellm.litellm_core_utils.logging_utils import speech_request_body, track_llm_api_timing from litellm.litellm_core_utils.url_utils import SSRFError, assert_same_origin from litellm.llms.custom_httpx.http_handler import ( AsyncHTTPHandler, @@ -1352,6 +1352,7 @@ class AzureChatCompletion(BaseAzureLLM, BaseLLM): organization: str | None, max_retries: int, timeout: float | httpx.Timeout, + logging_obj: LiteLLMLoggingObj, azure_ad_token: str | None = None, azure_ad_token_provider: Callable | None = None, aspeech: bool | None = None, @@ -1373,6 +1374,7 @@ class AzureChatCompletion(BaseAzureLLM, BaseLLM): azure_ad_token_provider=azure_ad_token_provider, max_retries=max_retries, timeout=timeout, + logging_obj=logging_obj, client=client, litellm_params=litellm_params, ) @@ -1387,6 +1389,15 @@ class AzureChatCompletion(BaseAzureLLM, BaseLLM): litellm_params=litellm_params, ) + logging_obj.pre_call( + input=input, + api_key=api_key, + additional_args={ # mutable-ok: loggers isinstance-check this payload as a dict + "complete_input_dict": speech_request_body(model, voice, optional_params), + "api_base": str(azure_client.base_url), + }, + ) + response: Final = azure_client.audio.speech.create( model=model, voice=voice, @@ -1408,6 +1419,7 @@ class AzureChatCompletion(BaseAzureLLM, BaseLLM): azure_ad_token_provider: Callable | None, max_retries: int, timeout: float | httpx.Timeout, + logging_obj: LiteLLMLoggingObj, client=None, litellm_params: dict | None = None, ) -> HttpxBinaryResponseContent: @@ -1421,6 +1433,15 @@ class AzureChatCompletion(BaseAzureLLM, BaseLLM): litellm_params=litellm_params, ) + logging_obj.pre_call( + input=input, + api_key=api_key, + additional_args={ # mutable-ok: loggers isinstance-check this payload as a dict + "complete_input_dict": speech_request_body(model, voice, optional_params), + "api_base": str(azure_client.base_url), + }, + ) + azure_response: Final = await azure_client.audio.speech.create( model=model, voice=voice, diff --git a/litellm/llms/base_llm/files/transformation.py b/litellm/llms/base_llm/files/transformation.py index 174be93448b..b20fe0f1560 100644 --- a/litellm/llms/base_llm/files/transformation.py +++ b/litellm/llms/base_llm/files/transformation.py @@ -11,9 +11,9 @@ from litellm.types.llms.openai import ( AllMessageValues, CreateFileRequest, FileContentRequest, + FileListPage, OpenAICreateFileRequestOptionalParams, OpenAIFileObject, - OpenAIFilesPurpose, ) from litellm.types.utils import LlmProviders, ModelResponse @@ -240,10 +240,13 @@ class BaseFileEndpoints(ABC): @abstractmethod async def afile_list( self, - purpose: OpenAIFilesPurpose | None, + purpose: str | None, litellm_parent_otel_span: Span | None, + user_api_key_dict: UserAPIKeyAuth, + limit: int | None = None, + after: str | None = None, **data: dict, - ) -> list[OpenAIFileObject]: + ) -> FileListPage: pass @abstractmethod diff --git a/litellm/llms/custom_httpx/llm_http_handler.py b/litellm/llms/custom_httpx/llm_http_handler.py index 8c98c526da1..ed079197513 100644 --- a/litellm/llms/custom_httpx/llm_http_handler.py +++ b/litellm/llms/custom_httpx/llm_http_handler.py @@ -19,6 +19,10 @@ import litellm.types.utils from litellm._logging import _redact_string, verbose_logger from litellm.anthropic_beta_headers_manager import update_headers_with_filtered_beta from litellm.constants import REALTIME_WEBSOCKET_MAX_MESSAGE_SIZE_BYTES +from litellm.litellm_core_utils.agentic_loop_settings import ( + DEFAULT_MAX_AGENTIC_LOOPS, + validated_max_agentic_loops, +) from litellm.litellm_core_utils.asyncify import run_async_function from litellm.litellm_core_utils.realtime_errors import realtime_error_event, websocket_close_reason from litellm.litellm_core_utils.realtime_streaming import RealTimeStreaming @@ -89,6 +93,7 @@ from litellm.types.files import StreamingMediaUploadConfig, TwoStepFileUploadCon from litellm.types.integrations.custom_logger import ( AgenticLoopPlan, AgenticLoopRequestPatch, + AgenticLoopSafetyError, ) from litellm.types.llms.anthropic_messages.anthropic_response import ( AnthropicMessagesResponse, @@ -2056,7 +2061,7 @@ class BaseLLMHTTPHandler: # Prepare headers kwargs = kwargs or {} provider_specific_header: Final = cast( - litellm.types.utils.ProviderSpecificHeader | None, + litellm.types.utils.ProviderSpecificHeader | Sequence[litellm.types.utils.ProviderSpecificHeader] | None, kwargs.get("provider_specific_header", None), ) provider_specific_headers: Final = ProviderSpecificHeaderUtils.get_provider_specific_headers( @@ -5077,9 +5082,12 @@ class BaseLLMHTTPHandler: @staticmethod def _get_agentic_loop_settings(kwargs: dict) -> tuple[int, int, list[str]]: depth: Final = int(kwargs.get("_agentic_loop_depth", 0) or 0) - max_loops: Final = int(kwargs.get("max_agentic_loops", 3) or 3) + configured: Final = validated_max_agentic_loops( + kwargs.get("max_agentic_loops"), field="litellm_params.max_agentic_loops" + ) + max_loops: Final = DEFAULT_MAX_AGENTIC_LOOPS if configured is None else configured fingerprints: Final = list(kwargs.get("_agentic_loop_fingerprints", []) or []) - return depth, max(max_loops, 1), fingerprints + return depth, max_loops, fingerprints @staticmethod def _has_agentic_completion_hook(logging_obj: LiteLLMLoggingObj) -> bool: @@ -5122,7 +5130,8 @@ class BaseLLMHTTPHandler: """ Evaluate agentic-loop safety guards (fingerprint cycle / max depth). - Raises ValueError on abort. Returns the current fingerprint on success. + Raises AgenticLoopSafetyError on abort. Returns the current fingerprint + on success. These checks must not be swallowed by the per-callback ``except Exception`` block that wraps callback dispatch — they are bounded-loop / cycle-break @@ -5130,9 +5139,9 @@ class BaseLLMHTTPHandler: """ fingerprint: Final = BaseLLMHTTPHandler._fingerprint_agentic_tools(tool_calls) if fingerprint in fingerprints: - raise ValueError("Agentic loop detected repeated tool-call fingerprint; aborting rerun") + raise AgenticLoopSafetyError("Agentic loop detected repeated tool-call fingerprint; aborting rerun") if depth >= max_loops: - raise ValueError(f"Exceeded max_agentic_loops={max_loops} for model={model}") + raise AgenticLoopSafetyError(f"Exceeded max_agentic_loops={max_loops} for model={model}") return fingerprint @staticmethod @@ -5142,6 +5151,97 @@ class BaseLLMHTTPHandler: except Exception: return str(tools) + @staticmethod + def _refused_agentic_tool_identifiers(tool_calls: object) -> tuple[frozenset[str], frozenset[str]]: + """ + Collect the ids and names of the tool calls a safety rail just refused. + + Callbacks hand back either a bare list of tool calls or a dict wrapping + that list under ``tool_calls``, and both the anthropic and responses + shapes carry an ``id`` (or ``call_id``) plus a ``name``. + """ + calls: Final = tool_calls.get("tool_calls") if isinstance(tool_calls, dict) else tool_calls + if not isinstance(calls, list): + return frozenset(), frozenset() + dict_calls: Final = (call for call in calls if isinstance(call, dict)) + fields: Final = tuple((call.get("id"), call.get("call_id"), call.get("name")) for call in dict_calls) + ids: Final = frozenset( + value for call_id, caller_id, _ in fields for value in (call_id, caller_id) if isinstance(value, str) + ) + names: Final = frozenset(name for _, _, name in fields if isinstance(name, str)) + return ids, names + + @staticmethod + def _is_refused_tool_use_block(block: object, refused_ids: frozenset[str], refused_names: frozenset[str]) -> bool: + """ + Whether this response block belongs to a tool call the rail refused. + + An id settles it on its own, so a block carrying one is matched on the id + alone and a client's own tool call survives even where it happens to + share a name with a refused one. The name is only consulted for tool call + shapes that arrive without an id. + """ + if not isinstance(block, dict) or block.get("type") != "tool_use": + return False + block_id: Final = block.get("id") + if isinstance(block_id, str) and refused_ids: + return block_id in refused_ids + return block.get("name") in refused_names + + @staticmethod + def _can_replace_turn_with_terminal_response(stream: bool, api_surface: str) -> bool: + """ + Whether a refused rerun can still be answered with a finalized turn. + + Only the anthropic messages surface can. The responses surface carries a + pydantic model the finalizer does not rewrite, so it keeps raising, which + is what every surface did before this path learned to end the turn. + + The messages and responses call sites pass ``stream=False``, because + interception converts an intercepted stream to non-streaming before the + loop runs and rebuilds the SSE stream from the finalized turn + afterwards. ``AgenticStreamingIterator`` passes ``stream=True``, and + that path keeps raising: its events are already on the wire, so a + finalized turn would reach the client as a second message rather than + as a replacement. + """ + return not stream and api_surface == "anthropic_messages" + + @staticmethod + def _finalize_refused_agentic_response(response: object, tool_calls: object) -> object: + """ + Turn the response into a terminal turn after a safety rail refused the rerun. + + The refused tool calls target tools LiteLLM injected on the client's + behalf, so a client that never declared them cannot send back a matching + ``tool_result``. Their blocks are dropped and a ``tool_use`` stop reason + is closed out as ``end_turn``, which is what a provider-native web search + turn returns once it stops calling tools. + + A ``tool_use`` block the client itself declared is left alone, and while + one is still in the response the stop reason stays ``tool_use`` so the + client knows to answer it. + """ + if not isinstance(response, dict): + return response + + refused_ids, refused_names = BaseLLMHTTPHandler._refused_agentic_tool_identifiers(tool_calls) + finalized: Final = dict(response) + content: Final = finalized.get("content") + if isinstance(content, list): + kept_blocks: Final = [ + block + for block in content + if not BaseLLMHTTPHandler._is_refused_tool_use_block(block, refused_ids, refused_names) + ] + finalized["content"] = kept_blocks + client_tool_use_remains: Final = any( + isinstance(block, dict) and block.get("type") == "tool_use" for block in kept_blocks + ) + if not client_tool_use_remains and finalized.get("stop_reason") == "tool_use": + finalized["stop_reason"] = "end_turn" + return finalized + async def _execute_anthropic_agentic_plan( self, plan: AgenticLoopPlan, @@ -5507,14 +5607,30 @@ class BaseLLMHTTPHandler: continue # Safety guards must run OUTSIDE the callback try/except — they are - # bounded-loop / cycle-break rails that must propagate to the caller. - fingerprint = self._check_agentic_loop_safety( - tool_calls=tool_calls, - fingerprints=fingerprints, - depth=depth, - max_loops=max_loops, - model=model, - ) + # bounded-loop / cycle-break rails, not callback bugs. + try: + fingerprint = self._check_agentic_loop_safety( + tool_calls=tool_calls, + fingerprints=fingerprints, + depth=depth, + max_loops=max_loops, + model=model, + ) + except AgenticLoopSafetyError as e: + if not self._can_replace_turn_with_terminal_response(stream, api_surface): + raise + _call_id = getattr(logging_obj, "litellm_call_id", "unknown") + verbose_logger.warning( + "LiteLLM.AgenticLoopRefused: ending turn [call_id=%s model=%s]: %s", + _call_id, + model, + str(e), + ) + return self._maybe_wrap_in_fake_stream( + self._finalize_refused_agentic_response(response=response, tool_calls=tool_calls), + logging_obj, + api_surface, + ) try: kwargs_with_provider = hook_kwargs.copy() diff --git a/litellm/llms/openai/openai.py b/litellm/llms/openai/openai.py index 4fc6655ca54..ee0efb88a38 100644 --- a/litellm/llms/openai/openai.py +++ b/litellm/llms/openai/openai.py @@ -22,7 +22,7 @@ from litellm._logging import verbose_logger from litellm.constants import DEFAULT_MAX_RETRIES from litellm.files.types import FileContentStreamingResult from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj -from litellm.litellm_core_utils.logging_utils import track_llm_api_timing +from litellm.litellm_core_utils.logging_utils import speech_request_body, track_llm_api_timing from litellm.llms.base_llm.base_model_iterator import BaseModelResponseIterator from litellm.llms.base_llm.chat.transformation import BaseConfig, BaseLLMException from litellm.llms.bedrock.chat.invoke_handler import MockResponseIterator @@ -1365,9 +1365,21 @@ class OpenAIChatCompletion(BaseLLM, BaseOpenAILLM): client=client, ) - if headers: - data["extra_headers"] = headers - response = await openai_aclient.images.generate(**data, timeout=timeout) + logging_obj.pre_call( + input=prompt, + api_key=openai_aclient.api_key, + additional_args={ # mutable-ok: loggers isinstance-check this payload as a dict + "headers": {"Authorization": f"Bearer {openai_aclient.api_key}"}, # mutable-ok: logged header map + "api_base": str(openai_aclient.base_url), + "acompletion": True, + "complete_input_dict": data, + }, + ) + + request_data: Final = ( # mutable-ok: the OpenAI SDK takes the request body as a dict + {**data, "extra_headers": headers} if headers else data + ) + response = await openai_aclient.images.generate(**request_data, timeout=timeout) stringified_response: Final = response.model_dump() ## LOGGING logging_obj.post_call( @@ -1450,9 +1462,10 @@ class OpenAIChatCompletion(BaseLLM, BaseOpenAILLM): ) ## COMPLETION CALL - if headers: - data["extra_headers"] = headers - _response: Final = openai_client.images.generate(**data, timeout=timeout) + request_data: Final = ( # mutable-ok: the OpenAI SDK takes the request body as a dict + {**data, "extra_headers": headers} if headers else data + ) + _response: Final = openai_client.images.generate(**request_data, timeout=timeout) response: Final = _response.model_dump() ## LOGGING @@ -1501,6 +1514,7 @@ class OpenAIChatCompletion(BaseLLM, BaseOpenAILLM): project: str | None, max_retries: int, timeout: float | httpx.Timeout, + logging_obj: LiteLLMLoggingObj, aspeech: bool | None = None, client=None, shared_session: Optional["ClientSession"] = None, @@ -1517,6 +1531,7 @@ class OpenAIChatCompletion(BaseLLM, BaseOpenAILLM): project=project, max_retries=max_retries, timeout=timeout, + logging_obj=logging_obj, client=client, shared_session=shared_session, ) @@ -1531,7 +1546,17 @@ class OpenAIChatCompletion(BaseLLM, BaseOpenAILLM): shared_session=shared_session, ) - response: Final = cast(OpenAI, openai_client).audio.speech.create( + sync_client: Final = cast(OpenAI, openai_client) + logging_obj.pre_call( + input=input, + api_key=api_key, + additional_args={ # mutable-ok: loggers isinstance-check this payload as a dict + "complete_input_dict": speech_request_body(model, voice, optional_params), + "api_base": str(sync_client.base_url), + }, + ) + + response: Final = sync_client.audio.speech.create( model=model, voice=voice, input=input, @@ -1551,6 +1576,7 @@ class OpenAIChatCompletion(BaseLLM, BaseOpenAILLM): project: str | None, max_retries: int, timeout: float | httpx.Timeout, + logging_obj: LiteLLMLoggingObj, client=None, shared_session: Optional["ClientSession"] = None, ) -> HttpxBinaryResponseContent: @@ -1567,6 +1593,15 @@ class OpenAIChatCompletion(BaseLLM, BaseOpenAILLM): ), ) + logging_obj.pre_call( + input=input, + api_key=api_key, + additional_args={ # mutable-ok: loggers isinstance-check this payload as a dict + "complete_input_dict": speech_request_body(model, voice, optional_params), + "api_base": str(openai_client.base_url), + }, + ) + response: Final = await openai_client.audio.speech.create( model=model, voice=voice, diff --git a/litellm/main.py b/litellm/main.py index 7cfd322f3d0..2cf53833c5a 100644 --- a/litellm/main.py +++ b/litellm/main.py @@ -5091,14 +5091,16 @@ def completion( model_info: Final = kwargs.get("model_info", None) proxy_server_request: Final = kwargs.get("proxy_server_request", None) fallbacks = kwargs.get("fallbacks", None) - provider_specific_header: Final = cast(ProviderSpecificHeader | None, kwargs.get("provider_specific_header", None)) + provider_specific_header: Final = cast( + ProviderSpecificHeader | Sequence[ProviderSpecificHeader] | None, + kwargs.get("provider_specific_header", None), + ) headers = kwargs.get("headers", None) or extra_headers ensure_alternating_roles: Final[bool | None] = kwargs.get("ensure_alternating_roles", None) user_continue_message: Final[ChatCompletionUserMessage | None] = kwargs.get("user_continue_message", None) assistant_continue_message: ChatCompletionAssistantMessage | None = kwargs.get("assistant_continue_message", None) - if headers is None: - headers = {} + headers = {} if headers is None else dict(headers) if extra_headers is not None: headers.update(extra_headers) # Inject proxy auth headers if configured @@ -7535,6 +7537,15 @@ async def amoderation( }, custom_llm_provider=custom_llm_provider, ) + moderation_request: Final = {"input": input, "model": model} # mutable-ok: logged as the raw request body + litellm_logging_obj.pre_call( + input=input, + api_key=api_key, + additional_args={ # mutable-ok: loggers isinstance-check this payload as a dict + "complete_input_dict": moderation_request, + "api_base": str(_openai_client.base_url), + }, + ) if model is not None: response = await _openai_client.moderations.create(input=input, model=model) @@ -8040,6 +8051,7 @@ def speech( project=project, max_retries=max_retries, timeout=timeout, + logging_obj=logging_obj, client=client, # pass AsyncOpenAI, OpenAI client aspeech=aspeech, shared_session=shared_session, @@ -8118,6 +8130,7 @@ def speech( organization=organization, max_retries=max_retries, timeout=timeout, + logging_obj=logging_obj, client=client, # pass AsyncOpenAI, OpenAI client aspeech=aspeech, litellm_params=litellm_params_dict, diff --git a/litellm/proxy/litellm_pre_call_utils.py b/litellm/proxy/litellm_pre_call_utils.py index 903974363e8..c1099081867 100644 --- a/litellm/proxy/litellm_pre_call_utils.py +++ b/litellm/proxy/litellm_pre_call_utils.py @@ -3044,36 +3044,36 @@ async def add_guardrails_from_policy_engine( ) +_ANTHROPIC_API_HEADER_PROVIDERS: Final = ",".join( + (LlmProviders.ANTHROPIC.value, LlmProviders.BEDROCK.value, LlmProviders.VERTEX_AI.value) +) +_ANTHROPIC_OAUTH_CREDENTIAL_PROVIDERS: Final = LlmProviders.ANTHROPIC.value + + def add_provider_specific_headers_to_request( data: dict, headers: dict, ): from litellm.llms.anthropic.common_utils import is_anthropic_oauth_key - anthropic_headers: Final = {} - # boolean to indicate if a header was added - added_header = False - for header in ANTHROPIC_API_HEADERS: - if header in headers: - header_value = headers[header] - anthropic_headers[header] = header_value - added_header = True + anthropic_api_headers: Final = {header: headers[header] for header in ANTHROPIC_API_HEADERS if header in headers} + anthropic_oauth_credential_headers: Final = { + header: value + for header, value in headers.items() + if header.lower() == "authorization" and is_anthropic_oauth_key(value) + } - # Check for Authorization header with Anthropic OAuth token (sk-ant-oat*) - # This needs to be handled via provider-specific headers to ensure it only - # goes to Anthropic-compatible providers, not all providers in the router - for header, value in headers.items(): - if header.lower() == "authorization" and is_anthropic_oauth_key(value): - anthropic_headers[header] = value - added_header = True - break - if added_header is True: - # Anthropic headers work across multiple providers - # Store as comma-separated list so retrieval can match any of them - data["provider_specific_header"] = ProviderSpecificHeader( - custom_llm_provider=f"{LlmProviders.ANTHROPIC.value},{LlmProviders.BEDROCK.value},{LlmProviders.VERTEX_AI.value}", - extra_headers=anthropic_headers, + scoped_headers: Final = [ + ProviderSpecificHeader(custom_llm_provider=providers, extra_headers=extra_headers) + for providers, extra_headers in ( + (_ANTHROPIC_API_HEADER_PROVIDERS, anthropic_api_headers), + (_ANTHROPIC_OAUTH_CREDENTIAL_PROVIDERS, anthropic_oauth_credential_headers), ) + if extra_headers + ] + + if scoped_headers: + data["provider_specific_header"] = scoped_headers[0] if len(scoped_headers) == 1 else scoped_headers def _add_otel_traceparent_to_data(data: dict, request: Request): diff --git a/litellm/proxy/management_endpoints/model_management_endpoints.py b/litellm/proxy/management_endpoints/model_management_endpoints.py index b003daa9d79..217fc61a56c 100644 --- a/litellm/proxy/management_endpoints/model_management_endpoints.py +++ b/litellm/proxy/management_endpoints/model_management_endpoints.py @@ -27,6 +27,7 @@ from litellm.constants import LITELLM_PROXY_ADMIN_NAME from litellm.litellm_core_utils.ptu_pricing import ( CUSTOM_PRICING_FIELDS, PTU_EMPTIED_PRICING_FIELDS, + PTU_MODEL_INFO_FIELDS, PTU_ZEROED_PRICING_FIELDS, PTU_ZEROED_TABLE_FIELDS, SEARCH_CONTEXT_SIZES, @@ -247,7 +248,6 @@ def _raise_on_strategy_router_write_violation( ) -_PTU_MODEL_INFO_FIELDS: Final = ("ptu_count", "cost_per_ptu_per_hour", "ptu_effective_from", "ptu_effective_to") _PTU_PRICED_PAIR: Final = frozenset({"ptu_count", "cost_per_ptu_per_hour"}) @@ -261,7 +261,7 @@ def _explicitly_cleared_ptu_fields(model_info: ModelInfo | None) -> frozenset[st return frozenset() return frozenset( field - for field in _PTU_MODEL_INFO_FIELDS + for field in PTU_MODEL_INFO_FIELDS if field in model_info.model_fields_set and getattr(model_info, field) is None ) @@ -294,7 +294,7 @@ def _raise_if_ptu_cost_attribution_disabled(incoming_model_info: Mapping[str, ob """ if is_ptu_cost_attribution_enabled(): return - supplied: Final = tuple(field for field in _PTU_MODEL_INFO_FIELDS if incoming_model_info.get(field) is not None) + supplied: Final = tuple(field for field in PTU_MODEL_INFO_FIELDS if incoming_model_info.get(field) is not None) if not supplied: return raise HTTPException( diff --git a/litellm/proxy/openai_files_endpoints/common_utils.py b/litellm/proxy/openai_files_endpoints/common_utils.py index b9af01e9aea..d4cb8fe2374 100644 --- a/litellm/proxy/openai_files_endpoints/common_utils.py +++ b/litellm/proxy/openai_files_endpoints/common_utils.py @@ -4,12 +4,14 @@ import re from collections.abc import Mapping from dataclasses import dataclass, field from types import MappingProxyType -from typing import TYPE_CHECKING, Final, Literal, Optional, Protocol, runtime_checkable +from typing import TYPE_CHECKING, Final, Literal, Optional, Protocol, get_args, runtime_checkable +from litellm.proxy._types import ProxyException from litellm.repositories.table_repositories import ( ManagedFileRepository, ManagedObjectRepository, ) +from litellm.types.llms.openai import OpenAIFilesPurpose from litellm.types.utils import SpecialEnums if TYPE_CHECKING: @@ -22,6 +24,50 @@ if TYPE_CHECKING: from litellm.types.utils import LiteLLMBatch +MAX_FILE_LIST_LIMIT: Final = 10000 + +FILE_LIST_CONTINUATION_CHUNK_SIZE: Final = 500 + + +def validate_file_list_limit(limit: int | None) -> None: + """Reject a ``limit`` outside the range OpenAI documents for GET /v1/files.""" + if limit is None or 1 <= limit <= MAX_FILE_LIST_LIMIT: + return + bound, expected, openai_code = ( + ("below minimum", ">= 1", "integer_below_min_value") + if limit < 1 + else ("above maximum", f"<= {MAX_FILE_LIST_LIMIT}", "integer_above_max_value") + ) + raise ProxyException( + message=f"Invalid 'limit': integer {bound} value. Expected a value {expected}, but got {limit} instead.", + type="invalid_request_error", + param="limit", + code=400, + openai_code=openai_code, + ) + + +def validate_file_list_purpose(purpose: str | None) -> None: + """Reject a ``purpose`` filter no upload to this proxy could have stored. + + An unknown purpose matches no file, so filtering on it would report an + empty page for what is really a bad request. Rejecting it keeps a managed + listing consistent with the upload route, which refuses the same values + against this same set. The provider-backed listings do not: they pass + ``purpose`` upstream, so a purpose OpenAI accepts before it is added here + is rejected on the managed path while still working on those. + """ + valid_purposes: Final = get_args(OpenAIFilesPurpose) + if purpose is None or purpose in valid_purposes: + return + raise ProxyException( + message=f"Invalid purpose: {purpose}. Must be one of: {valid_purposes}", + type="invalid_request_error", + param="purpose", + code=400, + ) + + @runtime_checkable class ManagedResourceAccessChecker(Protocol): async def can_user_call_unified_file_id( diff --git a/litellm/proxy/openai_files_endpoints/files_endpoints.py b/litellm/proxy/openai_files_endpoints/files_endpoints.py index 813ce9630a5..92bbd58ed90 100644 --- a/litellm/proxy/openai_files_endpoints/files_endpoints.py +++ b/litellm/proxy/openai_files_endpoints/files_endpoints.py @@ -65,6 +65,7 @@ from litellm.proxy.openai_files_endpoints.common_utils import ( get_credentials_for_model, handle_model_based_routing, prepare_data_with_credentials, + validate_file_list_limit, validate_managed_files_requirement, validate_managed_id_requirement, ) @@ -1410,6 +1411,8 @@ async def list_files( provider: str | None = None, target_model_names: str | None = None, purpose: str | None = None, + limit: int | None = None, + after: str | None = None, ): """ Returns information about a specific file. that can be used across - Assistants API, Batch API @@ -1434,6 +1437,8 @@ async def list_files( data: dict = {} try: + validate_file_list_limit(limit) + # Include original request and headers in the data base_llm_response_processor: Final = ProxyBaseLLMRequestProcessing(data=data) ( @@ -1500,24 +1505,30 @@ async def list_files( or get_custom_llm_provider_from_request_headers(request=request) or get_custom_llm_provider_from_request_query(request=request) or await get_custom_llm_provider_from_request_body(request=request) - or "openai" ) + managed_files_obj: Final = proxy_logging_obj.get_proxy_hook("managed_files") + if custom_llm_provider is None and isinstance(managed_files_obj, BaseFileEndpoints): + response = await managed_files_obj.afile_list( + purpose=purpose, + litellm_parent_otel_span=user_api_key_dict.parent_otel_span, + user_api_key_dict=user_api_key_dict, + limit=limit, + after=after, + ) + else: + resolved_custom_llm_provider: Final = custom_llm_provider or "openai" + apply_team_provider_credentials( + data=data, + llm_router=llm_router, + user_api_key_dict=user_api_key_dict, + custom_llm_provider=resolved_custom_llm_provider, + ) - # No model/target_model_names pinned: resolve upstream credentials from - # the team's deployment for this provider so the call is authenticated - # against the team's own account (e.g. the team's openai deployment). - apply_team_provider_credentials( - data=data, - llm_router=llm_router, - user_api_key_dict=user_api_key_dict, - custom_llm_provider=custom_llm_provider, - ) - - response = await litellm.afile_list( - custom_llm_provider=custom_llm_provider, - purpose=purpose, - **data, - ) + response = await litellm.afile_list( + custom_llm_provider=resolved_custom_llm_provider, + purpose=purpose, + **data, + ) if response is None: raise HTTPException( @@ -1561,6 +1572,8 @@ async def list_files( ) verbose_proxy_logger.error("litellm.proxy.proxy_server.list_files(): Exception occured - %s", e) verbose_proxy_logger.debug(traceback.format_exc()) + if isinstance(e, ProxyException): + raise if isinstance(e, HTTPException): raise ProxyException( message=getattr(e, "message", str(e.detail)), diff --git a/litellm/proxy/prisma_migration.py b/litellm/proxy/prisma_migration.py index 373c3811949..1b95d24c011 100644 --- a/litellm/proxy/prisma_migration.py +++ b/litellm/proxy/prisma_migration.py @@ -1,8 +1,9 @@ """Standalone entrypoint for applying database migrations and generating the Prisma client. -The entrypoint enforces migration failures by default. Set -ENFORCE_PRISMA_MIGRATION_CHECK=false to preserve log-only behavior for migration and -Prisma generate failures. +Migration failures fail the entrypoint by default; set ENFORCE_PRISMA_MIGRATION_CHECK=false +for log-only behavior. A failed 'prisma generate' is always log-only: every shipped image +bakes the client at build time, and refreshing it writes into site-packages, which an +arbitrary non-root uid or a read-only root filesystem cannot do. """ import os @@ -30,13 +31,13 @@ def main() -> int: verbose_proxy_logger.info("Running 'prisma generate'...") result: Final = subprocess.run(("prisma", "generate"), capture_output=True, text=True) verbose_proxy_logger.info("'prisma generate' stdout: %s", result.stdout) - exit_code: Final = result.returncode - if exit_code != 0: - verbose_proxy_logger.info("'prisma generate' failed with exit code %s.", exit_code) - verbose_proxy_logger.error("'prisma generate' stderr: %s", result.stderr) - if enforce_prisma_migration_check: - return exit_code + if result.returncode != 0: + verbose_proxy_logger.warning( + "'prisma generate' exited %s; continuing with the client baked at image build time. stderr: %s", + result.returncode, + result.stderr, + ) return 0 diff --git a/litellm/proxy/proxy_server.py b/litellm/proxy/proxy_server.py index 9f16584340d..7dced4e26b6 100644 --- a/litellm/proxy/proxy_server.py +++ b/litellm/proxy/proxy_server.py @@ -254,6 +254,9 @@ from litellm.exceptions import RejectedRequestError from litellm.integrations.custom_guardrail import ModifyResponseException from litellm.integrations.custom_logger import CustomLogger from litellm.integrations.SlackAlerting.slack_alerting import SlackAlerting +from litellm.litellm_core_utils.agentic_loop_settings import ( + validated_max_agentic_loops, +) from litellm.litellm_core_utils.asyncify import asyncify from litellm.litellm_core_utils.core_helpers import ( _get_parent_otel_span_from_kwargs, @@ -4081,6 +4084,27 @@ def resolve_complexity_router_plugins( complexity_router_config["classifier_plugin"] = resolved_classifier # rebind-ok: out-param, resolved in place +def validate_deployment_max_agentic_loops(model: Mapping[str, Any]) -> None: + """ + Reject a per-deployment `max_agentic_loops` the agentic loop cannot honor. + + Checked here rather than on `LiteLLM_Params` because the proxy builds its + router with `ignore_invalid_deployments=True`, so a validator down there + turns a bad value into a silently missing model instead of a refusal to + start. Left unchecked entirely, a `0` used to read as the default ceiling + of 3 and a non-integer failed every request to that model instead. + """ + litellm_params: Final = model.get("litellm_params") or {} + if "max_agentic_loops" not in litellm_params: + return + + model_name: Final = model.get("model_name", "") + validated_max_agentic_loops( + litellm_params["max_agentic_loops"], + field=f"litellm_params.max_agentic_loops on model {model_name!r}", + ) + + def pin_complexity_router_model_id(model: dict) -> None: # mutable-ok: out-param, model_info is stamped in place """ Stamps `model_info.id` from the raw litellm_params before plugin resolution swaps @@ -5416,6 +5440,7 @@ class ProxyConfig: for k, v in model["litellm_params"].items(): if isinstance(v, str) and v.startswith("os.environ/"): model["litellm_params"][k] = get_secret(v) + validate_deployment_max_agentic_loops(model) pin_complexity_router_model_id(model) complexity_router_config = model["litellm_params"].get("complexity_router_config") if isinstance(complexity_router_config, dict): diff --git a/litellm/router.py b/litellm/router.py index 7dedbe851d7..045fd32847c 100644 --- a/litellm/router.py +++ b/litellm/router.py @@ -66,6 +66,8 @@ from litellm.litellm_core_utils.credential_accessor import CredentialAccessor from litellm.litellm_core_utils.dd_tracing import tracer from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLogging from litellm.litellm_core_utils.ptu_pricing import ( + PTU_COST_ATTRIBUTION_ENV_VAR, + declares_ptu, is_ptu_cost_attribution_enabled, ptu_config_error, ptu_identity_error, @@ -8234,6 +8236,21 @@ class Router: ) duplicate_ids: Final = frozenset(model_id for model_id in declared_ids if declared_ids.count(model_id) > 1) + ptu_declared: Final = tuple( + str(entry.get("model_name")) + for entry in original_model_list + if isinstance(entry.get("model_info"), dict) + and entry["model_info"].get("db_model") is not True + and declares_ptu(entry["model_info"]) + ) + if ptu_declared and not is_ptu_cost_attribution_enabled(): + verbose_router_logger.warning( + "PTU fields are set on config.yaml deployment(s) %s, but PTU cost attribution is disabled, so no " + "flat cost accrues and this traffic is billed per token. Set %s=True to enable it", + ", ".join(ptu_declared), + PTU_COST_ATTRIBUTION_ENV_VAR, + ) + for model in original_model_list: _model_name = model.pop("model_name") _litellm_params = model.pop("litellm_params") diff --git a/litellm/types/integrations/custom_logger.py b/litellm/types/integrations/custom_logger.py index 89b85bc5114..2cca16351af 100644 --- a/litellm/types/integrations/custom_logger.py +++ b/litellm/types/integrations/custom_logger.py @@ -23,6 +23,21 @@ def is_interception_internal_key( return any(key.startswith(prefix) for prefix in prefixes) +class AgenticLoopSafetyError(ValueError): + """ + Raised when an agentic-loop safety rail refuses a rerun. + + Covers both rails: the bounded-loop cap (``max_agentic_loops``) and the + repeated tool-call fingerprint cycle break. Subclasses ``ValueError`` so + callers that already catch the broader type keep working. + + Only the anthropic messages loop raises this today. The chat completions + loop in ``litellm_core_utils/chat_completion_agentic_loop.py`` still raises + a plain ``ValueError`` from its own copy of the same rails, so catching + this type alone will not cover that surface until it is moved over. + """ + + class StandardCustomLoggerInitParams(BaseModel): """ Params for initializing a CustomLogger. diff --git a/litellm/types/integrations/websearch_interception.py b/litellm/types/integrations/websearch_interception.py index 90713b270be..7926b9eee0a 100644 --- a/litellm/types/integrations/websearch_interception.py +++ b/litellm/types/integrations/websearch_interception.py @@ -5,6 +5,7 @@ Type definitions for WebSearch Interception integration. from typing import Literal, TypedDict from pydantic import BaseModel +from typing_extensions import ReadOnly class AnthropicSearchQuery(BaseModel): @@ -35,6 +36,7 @@ class WebSearchInterceptionConfig(TypedDict, total=False): websearch_interception_params: enabled_providers: ["bedrock"] search_tool_name: "my-perplexity-search" + max_agentic_loops: 5 """ enabled_providers: list[str] @@ -42,3 +44,6 @@ class WebSearchInterceptionConfig(TypedDict, total=False): search_tool_name: str | None """Name of search tool configured in router's search_tools. If None, uses first available.""" + + max_agentic_loops: ReadOnly[int | None] + """How many follow-up model calls one intercepted request may chain. If None, LiteLLM's default of 3 applies.""" diff --git a/litellm/types/llms/openai.py b/litellm/types/llms/openai.py index 1588c650177..50e47071012 100644 --- a/litellm/types/llms/openai.py +++ b/litellm/types/llms/openai.py @@ -65,6 +65,7 @@ from pydantic import ( BaseModel, ConfigDict, Discriminator, + Field, PrivateAttr, field_serializer, field_validator, @@ -275,6 +276,7 @@ OpenAIFilesPurpose = Literal[ "fine-tune-results", "vision", "user_data", + "evals", "messages", ] @@ -381,6 +383,21 @@ class OpenAIFileObject(BaseModel): return self.dict() +class FileListPage(BaseModel): + """A page of files, as `GET /v1/files` returns it. + + Post-call hooks and logging callbacks are handed the listing response, and + the provider SDKs hand them a page object rather than a mapping, so this + exposes the same ``.data`` attribute while serializing to an identical body. + """ + + object: Literal["list"] = "list" + data: list[OpenAIFileObject] = Field(default_factory=list) + first_id: str | None = None + last_id: str | None = None + has_more: bool = False + + CREATE_FILE_REQUESTS_PURPOSE = Literal["assistants", "batch", "fine-tune", "messages"] diff --git a/litellm/types/utils.py b/litellm/types/utils.py index ac2ab1c8363..94526de0757 100644 --- a/litellm/types/utils.py +++ b/litellm/types/utils.py @@ -2846,7 +2846,7 @@ class StandardLoggingRoutingDecision(TypedDict, total=False): classifier_cost: float escalated: bool tier_boundaries: StandardLoggingRoutingDecisionTierBoundaries - reasoning_override_min_score: ReadOnly[float] + reasoning_override_min_score: float # writable-ok: Pydantic warns on ReadOnly TypedDict fields conversation_continuing: bool savings_baseline_model: str savings_baseline_deployment_id: str diff --git a/migrations/Dockerfile b/migrations/Dockerfile index 52795d426ec..6335e6f6bd8 100644 --- a/migrations/Dockerfile +++ b/migrations/Dockerfile @@ -1,5 +1,5 @@ -ARG LITELLM_BUILD_IMAGE=cgr.dev/chainguard/wolfi-base@sha256:42df77a9974d6ec8b17a5ee8bc23b532600a44d705acef2409e0933c1251b45f -ARG LITELLM_RUNTIME_IMAGE=cgr.dev/chainguard/wolfi-base@sha256:42df77a9974d6ec8b17a5ee8bc23b532600a44d705acef2409e0933c1251b45f +ARG LITELLM_BUILD_IMAGE=cgr.dev/chainguard/wolfi-base@sha256:a31344ab2cb8618db84f535eec56f76f6178b142cb92cb2e48676cc2dcebea72 +ARG LITELLM_RUNTIME_IMAGE=cgr.dev/chainguard/wolfi-base@sha256:a31344ab2cb8618db84f535eec56f76f6178b142cb92cb2e48676cc2dcebea72 ARG UV_IMAGE=ghcr.io/astral-sh/uv:0.11.7@sha256:240fb85ab0f263ef12f492d8476aa3a2e4e1e333f7d67fbdd923d00a506a516a FROM $UV_IMAGE AS uvbin diff --git a/pyproject.toml b/pyproject.toml index 57df956bdc9..fca5c7da1e2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -67,8 +67,8 @@ proxy = [ "azure-identity>=1.25.2,<2.0", "azure-storage-blob>=12.28.0,<13.0", "mcp>=1.28.1,<2.0", - "litellm-proxy-extras==0.4.88", - "litellm-enterprise==0.1.58", + "litellm-proxy-extras==0.4.89", + "litellm-enterprise==0.1.59", "RestrictedPython>=8.1,<9.0", "rich>=13.9.4,<14.0", "InquirerPy>=0.3.4,<1.0", diff --git a/ruff-tests.toml b/ruff-tests.toml index de0931f5e69..e52e1a96d00 100644 --- a/ruff-tests.toml +++ b/ruff-tests.toml @@ -36,6 +36,10 @@ # `re.search`, so a `.` copied out of an error message is a wildcard and the block # accepts messages the author never meant to accept. Mark a real regex raw, wrap a # literal message in `re.escape`, and the pattern says which one it is +# F823 a module-level name read inside a function that also binds it lower down. The +# later binding makes the name local for the whole body, so the read raises +# UnboundLocalError, and in an autouse fixture that takes every test in the +# directory down with it # # No target-version here on purpose: it resolves from requires-python (>=3.10), so # 3.11-only builtins like BaseExceptionGroup are correctly flagged in a tree that @@ -58,4 +62,5 @@ lint.select = [ "PLR0133", "PLW0127", "RUF043", + "F823", ] diff --git a/test-quality-budget.json b/test-quality-budget.json index 5039143eaa0..0dea4e8fe93 100644 --- a/test-quality-budget.json +++ b/test-quality-budget.json @@ -6,13 +6,13 @@ "limit": 742 }, "TQ003": { - "limit": 1068 + "limit": 62 }, "TQ004": { "limit": 469 }, "TQ005": { - "limit": 2459 + "limit": 2405 }, "TQ006": { "limit": 34 diff --git a/tests/agent_tests/local_only_agent_tests/test_a2a.py b/tests/agent_tests/local_only_agent_tests/test_a2a.py index 16ff545db14..e2e73808b95 100644 --- a/tests/agent_tests/local_only_agent_tests/test_a2a.py +++ b/tests/agent_tests/local_only_agent_tests/test_a2a.py @@ -6,8 +6,6 @@ Run with: """ import asyncio -import os -import sys import json from typing import Optional from uuid import uuid4 @@ -18,9 +16,6 @@ import litellm from litellm.integrations.custom_logger import CustomLogger from litellm.types.utils import StandardLoggingPayload -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path from a2a.types import MessageSendParams, SendMessageRequest diff --git a/tests/agent_tests/local_only_agent_tests/test_a2a_completion_bridge.py b/tests/agent_tests/local_only_agent_tests/test_a2a_completion_bridge.py index 4369bb800af..ff7e9da0368 100644 --- a/tests/agent_tests/local_only_agent_tests/test_a2a_completion_bridge.py +++ b/tests/agent_tests/local_only_agent_tests/test_a2a_completion_bridge.py @@ -10,13 +10,10 @@ Prerequisites: - LangGraph server running on localhost:2024 """ -import os -import sys from uuid import uuid4 import pytest -sys.path.insert(0, os.path.abspath("../..")) import litellm from a2a.types import MessageSendParams, SendMessageRequest, SendStreamingMessageRequest diff --git a/tests/audio_tests/conftest.py b/tests/audio_tests/conftest.py index c4ff576e5bd..21e7c868641 100644 --- a/tests/audio_tests/conftest.py +++ b/tests/audio_tests/conftest.py @@ -1,9 +1,6 @@ -import os -import sys import pytest -sys.path.insert(0, os.path.abspath("../..")) from tests._vcr_conftest_common import ( # noqa: E402,F401 VerboseReporterState, diff --git a/tests/audio_tests/test_audio_speech.py b/tests/audio_tests/test_audio_speech.py index fb9e679699a..f5a0cef6049 100644 --- a/tests/audio_tests/test_audio_speech.py +++ b/tests/audio_tests/test_audio_speech.py @@ -4,7 +4,6 @@ import asyncio import os import random -import sys import time import traceback from litellm._uuid import uuid @@ -13,9 +12,6 @@ from dotenv import load_dotenv load_dotenv() -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path from pathlib import Path from unittest.mock import AsyncMock, MagicMock, patch diff --git a/tests/audio_tests/test_whisper.py b/tests/audio_tests/test_whisper.py index 333d806fe41..ba0ec02a02f 100644 --- a/tests/audio_tests/test_whisper.py +++ b/tests/audio_tests/test_whisper.py @@ -4,7 +4,6 @@ import asyncio import logging import os -import sys import time import traceback from typing import Optional @@ -41,9 +40,6 @@ def _audio_file2(): load_dotenv() -sys.path.insert( - 0, os.path.abspath("../") -) # Adds the parent directory to the system path from litellm import Router diff --git a/tests/batches_tests/conftest.py b/tests/batches_tests/conftest.py index e1899a22b6c..b46726c0c85 100644 --- a/tests/batches_tests/conftest.py +++ b/tests/batches_tests/conftest.py @@ -1,12 +1,7 @@ import asyncio -import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm # noqa: E402,F401 from tests._vcr_conftest_common import ( # noqa: E402,F401 diff --git a/tests/batches_tests/test_batch_rate_limits.py b/tests/batches_tests/test_batch_rate_limits.py index ae02c1be12c..b44b8435cd9 100644 --- a/tests/batches_tests/test_batch_rate_limits.py +++ b/tests/batches_tests/test_batch_rate_limits.py @@ -5,14 +5,10 @@ Integration Tests for Batch Rate Limits import asyncio import json import os -import sys import pytest from fastapi import HTTPException -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm import DualCache diff --git a/tests/batches_tests/test_batches_logging_unit_tests.py b/tests/batches_tests/test_batches_logging_unit_tests.py index 62b6f5b08e4..5211b3ecb29 100644 --- a/tests/batches_tests/test_batches_logging_unit_tests.py +++ b/tests/batches_tests/test_batches_logging_unit_tests.py @@ -1,15 +1,10 @@ import asyncio import json -import os -import sys import traceback from unittest.mock import AsyncMock, MagicMock, patch from dotenv import load_dotenv load_dotenv() -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system-path import logging import time diff --git a/tests/batches_tests/test_bedrock_files_and_batches.py b/tests/batches_tests/test_bedrock_files_and_batches.py index b9045cc43d6..336fd7dd953 100644 --- a/tests/batches_tests/test_bedrock_files_and_batches.py +++ b/tests/batches_tests/test_bedrock_files_and_batches.py @@ -3,15 +3,11 @@ import asyncio import json as json_module import os -import sys import traceback import tempfile from dotenv import load_dotenv load_dotenv() -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system-path import pytest diff --git a/tests/batches_tests/test_fine_tuning_api.py b/tests/batches_tests/test_fine_tuning_api.py index bd6672a52e9..41b47c1ee68 100644 --- a/tests/batches_tests/test_fine_tuning_api.py +++ b/tests/batches_tests/test_fine_tuning_api.py @@ -1,12 +1,7 @@ -import os -import sys import traceback import json import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path from openai import APITimeoutError as Timeout import litellm diff --git a/tests/batches_tests/test_openai_batches_and_files.py b/tests/batches_tests/test_openai_batches_and_files.py index 0a49b3d77d1..ebd7fde7971 100644 --- a/tests/batches_tests/test_openai_batches_and_files.py +++ b/tests/batches_tests/test_openai_batches_and_files.py @@ -3,14 +3,10 @@ import asyncio import json import os -import sys import tempfile from dotenv import load_dotenv load_dotenv() -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system-path import logging import time @@ -103,6 +99,25 @@ def load_vertex_ai_credentials(): print("created gcs path service account=", os.environ["GCS_PATH_SERVICE_ACCOUNT"]) +async def cancel_batch_unless_already_terminal(batch_id: str, provider: str) -> None: + try: + cancel_batch_response = await litellm.acancel_batch(batch_id=batch_id, custom_llm_provider=provider) + except openai.ConflictError as e: + if "Cannot cancel a batch with status 'completed'" in str(e): + print(f"Batch already completed, cannot cancel: {e}") + return + if "Cannot cancel a batch with status 'failed'" not in str(e): + raise + failed_batch = await litellm.aretrieve_batch(batch_id=batch_id, custom_llm_provider=provider) + print(f"Batch failed before cancel, errors={failed_batch.errors}") + failure_codes = {err.code for err in (failed_batch.errors.data if failed_batch.errors else None) or []} + assert failure_codes == {"token_limit_exceeded"}, ( + f"batch failed for a reason other than the org's enqueued token limit: {failed_batch.errors}" + ) + return + print("cancel_batch_response=", cancel_batch_response) + + @pytest.mark.parametrize("provider", ["openai"]) # , "azure" @pytest.mark.asyncio @skip_if_no_openai_network @@ -176,24 +191,7 @@ async def test_create_batch(provider, tmp_path): result_file_path = tmp_path / "batch_job_results_furniture.jsonl" result_file_path.write_bytes(result) - # Cancel Batch - handle race condition where batch may already be completed - try: - cancel_batch_response = await litellm.acancel_batch( - batch_id=create_batch_response.id, - custom_llm_provider=provider, - ) - print("cancel_batch_response=", cancel_batch_response) - except openai.ConflictError as e: - # Only allow to pass if it's specifically the "batch already completed" error - if "Cannot cancel a batch with status 'completed'" in str(e): - print(f"Batch already completed, cannot cancel: {e}") - else: - # Re-raise other ConflictError types - raise - except Exception as e: - # Re-raise any other unexpected errors - print(f"Unexpected error during batch cancellation: {e}") - raise + await cancel_batch_unless_already_terminal(batch_id=create_batch_response.id, provider=provider) pass @@ -395,24 +393,7 @@ async def test_async_create_batch(provider, tmp_path): result_file_path = tmp_path / "batch_job_results_furniture.jsonl" result_file_path.write_bytes(file_content.content) - # Cancel Batch - handle race condition where batch may already be completed - try: - cancel_batch_response = await litellm.acancel_batch( - batch_id=create_batch_response.id, - custom_llm_provider=provider, - ) - print("cancel_batch_response=", cancel_batch_response) - except openai.ConflictError as e: - # Only allow to pass if it's specifically the "batch already completed" error - if "Cannot cancel a batch with status 'completed'" in str(e): - print(f"Batch already completed, cannot cancel: {e}") - else: - # Re-raise other ConflictError types - raise - except Exception as e: - # Re-raise any other unexpected errors - print(f"Unexpected error during batch cancellation: {e}") - raise + await cancel_batch_unless_already_terminal(batch_id=create_batch_response.id, provider=provider) mock_file_response = { diff --git a/tests/code_coverage_tests/bedrock_pricing.py b/tests/code_coverage_tests/bedrock_pricing.py index b2c9e78b06c..5984dd8b3a4 100644 --- a/tests/code_coverage_tests/bedrock_pricing.py +++ b/tests/code_coverage_tests/bedrock_pricing.py @@ -1,7 +1,5 @@ import os -import sys -sys.path.insert(0, os.path.abspath("../..")) import litellm import requests from bs4 import BeautifulSoup diff --git a/tests/code_coverage_tests/check_spanattributes_value_usage.py b/tests/code_coverage_tests/check_spanattributes_value_usage.py index b180c572e73..6d1daa45fc7 100644 --- a/tests/code_coverage_tests/check_spanattributes_value_usage.py +++ b/tests/code_coverage_tests/check_spanattributes_value_usage.py @@ -27,10 +27,8 @@ import ast import os import re from typing import List, Tuple -import sys # Add parent directory to path so we can import litellm -sys.path.insert(0, os.path.abspath("../..")) import litellm diff --git a/tests/code_coverage_tests/enforce_llms_folder_style.py b/tests/code_coverage_tests/enforce_llms_folder_style.py index 04a95b45196..a284cf9e1a9 100644 --- a/tests/code_coverage_tests/enforce_llms_folder_style.py +++ b/tests/code_coverage_tests/enforce_llms_folder_style.py @@ -1,8 +1,6 @@ import ast import os -import sys -sys.path.insert(0, os.path.abspath("../..")) import litellm diff --git a/tests/code_coverage_tests/test_router_strategy_async.py b/tests/code_coverage_tests/test_router_strategy_async.py index 05bdca10f45..80bfcad4453 100644 --- a/tests/code_coverage_tests/test_router_strategy_async.py +++ b/tests/code_coverage_tests/test_router_strategy_async.py @@ -4,14 +4,9 @@ Test that all cache calls in async functions in router_strategy/ are async """ import os -import sys from typing import Dict, List, Tuple import ast -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path -import os class AsyncCacheCallVisitor(ast.NodeVisitor): diff --git a/tests/documentation_tests/test_api_docs.py b/tests/documentation_tests/test_api_docs.py index 2faac371c39..d8536f13b9c 100644 --- a/tests/documentation_tests/test_api_docs.py +++ b/tests/documentation_tests/test_api_docs.py @@ -4,11 +4,7 @@ import os from dataclasses import dataclass import argparse import re -import sys -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm diff --git a/tests/documentation_tests/test_exception_types.py b/tests/documentation_tests/test_exception_types.py index 87e128605c4..f554c4b38d4 100644 --- a/tests/documentation_tests/test_exception_types.py +++ b/tests/documentation_tests/test_exception_types.py @@ -11,9 +11,6 @@ import re # Backup the original sys.path original_sys_path = sys.path.copy() -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm public_exceptions = litellm.LITELLM_EXCEPTION_TYPES diff --git a/tests/documentation_tests/test_router_settings.py b/tests/documentation_tests/test_router_settings.py index a1b6f1dac1d..75032f80dfa 100644 --- a/tests/documentation_tests/test_router_settings.py +++ b/tests/documentation_tests/test_router_settings.py @@ -2,11 +2,7 @@ import os import re import inspect from typing import Type -import sys -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm diff --git a/tests/documentation_tests/test_standard_logging_payload.py b/tests/documentation_tests/test_standard_logging_payload.py index cdb51411833..22f7b71033f 100644 --- a/tests/documentation_tests/test_standard_logging_payload.py +++ b/tests/documentation_tests/test_standard_logging_payload.py @@ -1,12 +1,7 @@ -import os import re -import sys from typing import get_type_hints -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path from litellm.types.utils import StandardLoggingPayload diff --git a/tests/enterprise/conftest.py b/tests/enterprise/conftest.py index f23a5664f83..4c95f967bc4 100644 --- a/tests/enterprise/conftest.py +++ b/tests/enterprise/conftest.py @@ -3,13 +3,9 @@ import asyncio import importlib import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm @@ -31,9 +27,6 @@ def setup_and_teardown(): This fixture reloads litellm before every function. To speed up testing by removing callbacks being chained. """ curr_dir = os.getcwd() # Get the current working directory - sys.path.insert( - 0, os.path.abspath("../..") - ) # Adds the project directory to the system path from litellm import Router @@ -41,8 +34,6 @@ def setup_and_teardown(): try: if hasattr(litellm, "proxy") and hasattr(litellm.proxy, "proxy_server"): - import litellm.proxy.proxy_server - importlib.reload(litellm.proxy.proxy_server) except Exception as e: print(f"Error reloading litellm.proxy.proxy_server: {e}") diff --git a/tests/enterprise/litellm_enterprise/enterprise_callbacks/test_prometheus_logging_callbacks.py b/tests/enterprise/litellm_enterprise/enterprise_callbacks/test_prometheus_logging_callbacks.py index b6c9cd0294b..05886e4b7f6 100644 --- a/tests/enterprise/litellm_enterprise/enterprise_callbacks/test_prometheus_logging_callbacks.py +++ b/tests/enterprise/litellm_enterprise/enterprise_callbacks/test_prometheus_logging_callbacks.py @@ -1,7 +1,4 @@ -import os -import sys -sys.path.insert(0, os.path.abspath("../..")) import asyncio import logging diff --git a/tests/enterprise/litellm_enterprise/integrations/test_custom_guardrail.py b/tests/enterprise/litellm_enterprise/integrations/test_custom_guardrail.py index 8a29e5c1ced..c6e48061698 100644 --- a/tests/enterprise/litellm_enterprise/integrations/test_custom_guardrail.py +++ b/tests/enterprise/litellm_enterprise/integrations/test_custom_guardrail.py @@ -1,9 +1,4 @@ -import os -import sys -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system-path from litellm.integrations.custom_guardrail import CustomGuardrail from litellm.types.guardrails import GuardrailEventHooks, Mode diff --git a/tests/enterprise/litellm_enterprise/integrations/test_prometheus.py b/tests/enterprise/litellm_enterprise/integrations/test_prometheus.py index 6c4a008c823..7315f2b9881 100644 --- a/tests/enterprise/litellm_enterprise/integrations/test_prometheus.py +++ b/tests/enterprise/litellm_enterprise/integrations/test_prometheus.py @@ -3,15 +3,10 @@ Mock prometheus unit tests, these don't rely on LLM API calls """ import json -import os -import sys import pytest from fastapi.testclient import TestClient -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from unittest.mock import patch diff --git a/tests/enterprise/litellm_enterprise/integrations/test_prometheus_unit_tests.py b/tests/enterprise/litellm_enterprise/integrations/test_prometheus_unit_tests.py index f5c39fb86ae..28fd03daf37 100644 --- a/tests/enterprise/litellm_enterprise/integrations/test_prometheus_unit_tests.py +++ b/tests/enterprise/litellm_enterprise/integrations/test_prometheus_unit_tests.py @@ -9,16 +9,12 @@ except Exception: PrometheusLogger = None import asyncio -import sys from dotenv import load_dotenv load_dotenv() import os -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system-path from unittest.mock import MagicMock import pytest diff --git a/tests/enterprise/litellm_enterprise/proxy/auth/test_route_checks.py b/tests/enterprise/litellm_enterprise/proxy/auth/test_route_checks.py index f90ac9abb7d..265abbe95cf 100644 --- a/tests/enterprise/litellm_enterprise/proxy/auth/test_route_checks.py +++ b/tests/enterprise/litellm_enterprise/proxy/auth/test_route_checks.py @@ -1,10 +1,6 @@ import os -import sys from unittest.mock import MagicMock, patch -sys.path.insert( - 0, os.path.abspath("../../../..") -) # Adds the parent directory to the system path import pytest from fastapi import HTTPException diff --git a/tests/enterprise/litellm_enterprise/proxy/guardrails/test_apply_guardrail_endpoint.py b/tests/enterprise/litellm_enterprise/proxy/guardrails/test_apply_guardrail_endpoint.py index e5074c44210..4f44a4adeed 100644 --- a/tests/enterprise/litellm_enterprise/proxy/guardrails/test_apply_guardrail_endpoint.py +++ b/tests/enterprise/litellm_enterprise/proxy/guardrails/test_apply_guardrail_endpoint.py @@ -2,13 +2,10 @@ Test the /guardrails/apply_guardrail endpoint """ -import os -import sys from unittest.mock import AsyncMock, Mock, patch import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) from fastapi import HTTPException diff --git a/tests/enterprise/litellm_enterprise/proxy/guardrails/test_bedrock_apply_guardrail.py b/tests/enterprise/litellm_enterprise/proxy/guardrails/test_bedrock_apply_guardrail.py index 6b6b5d768dd..463076229e9 100644 --- a/tests/enterprise/litellm_enterprise/proxy/guardrails/test_bedrock_apply_guardrail.py +++ b/tests/enterprise/litellm_enterprise/proxy/guardrails/test_bedrock_apply_guardrail.py @@ -2,13 +2,10 @@ Test the Bedrock guardrail apply_guardrail functionality """ -import os -import sys from unittest.mock import AsyncMock, Mock, patch import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm.proxy._types import UserAPIKeyAuth diff --git a/tests/enterprise/litellm_enterprise/proxy/management_endpoints/test_project_endpoints_prisma.py b/tests/enterprise/litellm_enterprise/proxy/management_endpoints/test_project_endpoints_prisma.py index ed6735a7126..34a0d1c9f7a 100644 --- a/tests/enterprise/litellm_enterprise/proxy/management_endpoints/test_project_endpoints_prisma.py +++ b/tests/enterprise/litellm_enterprise/proxy/management_endpoints/test_project_endpoints_prisma.py @@ -1,5 +1,4 @@ import os -import sys import traceback from litellm._uuid import uuid from unittest import mock @@ -10,7 +9,6 @@ from fastapi import Request load_dotenv() import time -sys.path.insert(0, os.path.abspath("../..")) import logging import pytest diff --git a/tests/guardrails_tests/conftest.py b/tests/guardrails_tests/conftest.py index f2f65645c3d..6eeb0924341 100644 --- a/tests/guardrails_tests/conftest.py +++ b/tests/guardrails_tests/conftest.py @@ -7,13 +7,9 @@ import importlib import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from tests._vcr_conftest_common import ( # noqa: E402,F401 @@ -122,7 +118,6 @@ def setup_and_teardown(): Module-scoped setup. Reloads litellm only in single-process mode (skipped under xdist to avoid cross-worker interference). """ - sys.path.insert(0, os.path.abspath("../..")) import litellm diff --git a/tests/guardrails_tests/test_bedrock_guardrails.py b/tests/guardrails_tests/test_bedrock_guardrails.py index 8b22cc0eb73..43d088268eb 100644 --- a/tests/guardrails_tests/test_bedrock_guardrails.py +++ b/tests/guardrails_tests/test_bedrock_guardrails.py @@ -1,9 +1,6 @@ -import sys -import os import io, asyncio import pytest -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm.proxy.guardrails.guardrail_hooks.bedrock_guardrails import ( BedrockGuardrail, diff --git a/tests/guardrails_tests/test_custom_guardrail.py b/tests/guardrails_tests/test_custom_guardrail.py index 9d7efeecdca..3c88ed53cd3 100644 --- a/tests/guardrails_tests/test_custom_guardrail.py +++ b/tests/guardrails_tests/test_custom_guardrail.py @@ -3,11 +3,8 @@ Test custom guardrail + unit tests for guardrails """ import io -import os -import sys -sys.path.insert(0, os.path.abspath("../..")) import asyncio import gzip diff --git a/tests/guardrails_tests/test_deepkeep_guardrails.py b/tests/guardrails_tests/test_deepkeep_guardrails.py index d06610f3f4c..74bdea2e0b9 100644 --- a/tests/guardrails_tests/test_deepkeep_guardrails.py +++ b/tests/guardrails_tests/test_deepkeep_guardrails.py @@ -1,5 +1,4 @@ import os -import sys from unittest.mock import patch, AsyncMock from httpx import Response, Request @@ -13,9 +12,6 @@ from litellm.proxy.guardrails.guardrail_hooks.deepkeep.deepkeep import ( ) from litellm.exceptions import GuardrailRaisedException -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm.proxy.guardrails.init_guardrails import init_guardrails_v2 diff --git a/tests/guardrails_tests/test_dynamoai_guardrails.py b/tests/guardrails_tests/test_dynamoai_guardrails.py index 6f0ea00165b..4f56f7cd444 100644 --- a/tests/guardrails_tests/test_dynamoai_guardrails.py +++ b/tests/guardrails_tests/test_dynamoai_guardrails.py @@ -2,11 +2,8 @@ Test DynamoAI Guardrails integration """ -import sys -import os import pytest -sys.path.insert(0, os.path.abspath("../..")) from litellm.proxy.guardrails.guardrail_hooks.dynamoai import DynamoAIGuardrails from litellm.proxy._types import UserAPIKeyAuth diff --git a/tests/guardrails_tests/test_eu_ai_act_article5.py b/tests/guardrails_tests/test_eu_ai_act_article5.py index f7384667481..d17e56c7450 100644 --- a/tests/guardrails_tests/test_eu_ai_act_article5.py +++ b/tests/guardrails_tests/test_eu_ai_act_article5.py @@ -8,11 +8,9 @@ Tests 40 different sentences to validate the conditional matching logic: - identifier or block word alone should ALLOW """ -import sys import os import pytest -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm.proxy.guardrails.guardrail_hooks.litellm_content_filter.content_filter import ( ContentFilterGuardrail, @@ -162,7 +160,6 @@ def content_filter_guardrail(): """Initialize content filter guardrail with EU AI Act Article 5 template.""" # Get absolute path to the policy template - import os content_filter_dir = os.path.join( os.path.dirname(__file__), diff --git a/tests/guardrails_tests/test_eu_ai_act_french_3_scenarios.py b/tests/guardrails_tests/test_eu_ai_act_french_3_scenarios.py index 221ca5aa6e6..cfc59030076 100644 --- a/tests/guardrails_tests/test_eu_ai_act_french_3_scenarios.py +++ b/tests/guardrails_tests/test_eu_ai_act_french_3_scenarios.py @@ -7,11 +7,9 @@ Tests the exact 3 scenarios requested: 3. Request 3: Safe query in French that should pass (allowed) """ -import sys import os import pytest -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm.proxy.guardrails.guardrail_hooks.litellm_content_filter.content_filter import ( ContentFilterGuardrail, diff --git a/tests/guardrails_tests/test_guardrail_load_balancing.py b/tests/guardrails_tests/test_guardrail_load_balancing.py index 4f71f83c433..2e71d2c99a3 100644 --- a/tests/guardrails_tests/test_guardrail_load_balancing.py +++ b/tests/guardrails_tests/test_guardrail_load_balancing.py @@ -2,11 +2,8 @@ Test guardrail load balancing through the Router and ProxyLogging. """ -import os -import sys from unittest.mock import MagicMock, patch, AsyncMock -sys.path.insert(0, os.path.abspath("../..")) import litellm import pytest diff --git a/tests/guardrails_tests/test_guardrails_config.py b/tests/guardrails_tests/test_guardrails_config.py index aaacb607261..5160954b0eb 100644 --- a/tests/guardrails_tests/test_guardrails_config.py +++ b/tests/guardrails_tests/test_guardrails_config.py @@ -2,8 +2,6 @@ ## Unit Tests for guardrails config import asyncio import inspect -import os -import sys import time import traceback from litellm._uuid import uuid @@ -15,7 +13,6 @@ from pydantic import BaseModel import litellm.litellm_core_utils import litellm.litellm_core_utils.litellm_logging -sys.path.insert(0, os.path.abspath("../..")) from typing import Any, List, Literal, Optional, Tuple, Union from unittest.mock import AsyncMock, MagicMock, patch diff --git a/tests/guardrails_tests/test_javelin_guardrails.py b/tests/guardrails_tests/test_javelin_guardrails.py index 62655a3c077..a2e7747d657 100644 --- a/tests/guardrails_tests/test_javelin_guardrails.py +++ b/tests/guardrails_tests/test_javelin_guardrails.py @@ -1,10 +1,7 @@ -import sys -import os import pytest from unittest.mock import AsyncMock, patch from fastapi import HTTPException -sys.path.insert(0, os.path.abspath("../..")) from litellm.proxy.guardrails.guardrail_hooks.javelin import JavelinGuardrail import litellm from litellm.proxy._types import UserAPIKeyAuth diff --git a/tests/guardrails_tests/test_lakera_v2.py b/tests/guardrails_tests/test_lakera_v2.py index 74e19350192..a71759862b2 100644 --- a/tests/guardrails_tests/test_lakera_v2.py +++ b/tests/guardrails_tests/test_lakera_v2.py @@ -1,12 +1,9 @@ -import sys -import os import io, asyncio import pytest import time from litellm import mock_completion from unittest.mock import MagicMock, AsyncMock, patch -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm.proxy.guardrails.guardrail_hooks.lakera_ai_v2 import LakeraAIGuardrail from litellm.types.guardrails import PiiEntityType, PiiAction diff --git a/tests/guardrails_tests/test_lasso_guardrails.py b/tests/guardrails_tests/test_lasso_guardrails.py index 75b571e236b..fd585623744 100644 --- a/tests/guardrails_tests/test_lasso_guardrails.py +++ b/tests/guardrails_tests/test_lasso_guardrails.py @@ -1,5 +1,4 @@ import os -import sys from fastapi.exceptions import HTTPException from unittest.mock import patch from httpx import Response, Request @@ -14,9 +13,6 @@ from litellm.proxy.guardrails.guardrail_hooks.lasso.lasso import ( LassoGuardrailAPIError, ) -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm.proxy.guardrails.init_guardrails import init_guardrails_v2 diff --git a/tests/guardrails_tests/test_presidio_pii.py b/tests/guardrails_tests/test_presidio_pii.py index edc63bd9419..b3b2a790ba8 100644 --- a/tests/guardrails_tests/test_presidio_pii.py +++ b/tests/guardrails_tests/test_presidio_pii.py @@ -1,10 +1,8 @@ -import sys import os import pytest from litellm import mock_completion from unittest.mock import patch -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm.proxy.guardrails.guardrail_hooks.presidio import ( _OPTIONAL_PresidioPIIMasking, diff --git a/tests/guardrails_tests/test_semantic_guard.py b/tests/guardrails_tests/test_semantic_guard.py index c9f4a902895..92c55507568 100644 --- a/tests/guardrails_tests/test_semantic_guard.py +++ b/tests/guardrails_tests/test_semantic_guard.py @@ -3,9 +3,7 @@ Tests for the Semantic Guard guardrail — embedding-based prompt injection dete """ import os -import sys -sys.path.insert(0, os.path.abspath("../..")) from unittest.mock import MagicMock diff --git a/tests/guardrails_tests/test_sg_mas_ai_guardrails.py b/tests/guardrails_tests/test_sg_mas_ai_guardrails.py index e587d666a79..385fee93ab4 100644 --- a/tests/guardrails_tests/test_sg_mas_ai_guardrails.py +++ b/tests/guardrails_tests/test_sg_mas_ai_guardrails.py @@ -10,11 +10,9 @@ for Singapore financial institutions: 5. sg_mas_model_security — Adversarial attacks on financial AI """ -import sys import os import pytest -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm.proxy.guardrails.guardrail_hooks.litellm_content_filter.content_filter import ( ContentFilterGuardrail, diff --git a/tests/guardrails_tests/test_sg_pdpa_guardrails.py b/tests/guardrails_tests/test_sg_pdpa_guardrails.py index 42c3a15f9f6..1e8b8a48b85 100644 --- a/tests/guardrails_tests/test_sg_pdpa_guardrails.py +++ b/tests/guardrails_tests/test_sg_pdpa_guardrails.py @@ -15,11 +15,9 @@ Each sub-guardrail validates: - identifier or block word alone → ALLOW (no match) """ -import sys import os import pytest -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm.proxy.guardrails.guardrail_hooks.litellm_content_filter.content_filter import ( ContentFilterGuardrail, diff --git a/tests/guardrails_tests/test_tracing_guardrails.py b/tests/guardrails_tests/test_tracing_guardrails.py index 46f4f3e6e9b..bd8b7bad33f 100644 --- a/tests/guardrails_tests/test_tracing_guardrails.py +++ b/tests/guardrails_tests/test_tracing_guardrails.py @@ -1,4 +1,3 @@ -import sys import os import io, asyncio import json @@ -7,7 +6,6 @@ import time from litellm import mock_completion from unittest.mock import MagicMock, AsyncMock, patch -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm.proxy.guardrails.guardrail_hooks.presidio import ( _OPTIONAL_PresidioPIIMasking, diff --git a/tests/image_gen_tests/base_image_generation_test.py b/tests/image_gen_tests/base_image_generation_test.py index ab46bd36feb..c50b09d329c 100644 --- a/tests/image_gen_tests/base_image_generation_test.py +++ b/tests/image_gen_tests/base_image_generation_test.py @@ -2,14 +2,9 @@ import asyncio import httpx import json import pytest -import sys from typing import Any, Dict, List, Optional from unittest.mock import MagicMock, Mock, patch -import os -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm.exceptions import BadRequestError from litellm.llms.custom_httpx.http_handler import AsyncHTTPHandler, HTTPHandler diff --git a/tests/image_gen_tests/conftest.py b/tests/image_gen_tests/conftest.py index 9f808c11161..7e9a5c0d629 100644 --- a/tests/image_gen_tests/conftest.py +++ b/tests/image_gen_tests/conftest.py @@ -1,12 +1,7 @@ import asyncio -import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm # noqa: E402,F401 from tests._vcr_conftest_common import ( # noqa: E402,F401 diff --git a/tests/image_gen_tests/test_bedrock_image_gen_unit_tests.py b/tests/image_gen_tests/test_bedrock_image_gen_unit_tests.py index c4d0f5fc773..1be3ca0745d 100644 --- a/tests/image_gen_tests/test_bedrock_image_gen_unit_tests.py +++ b/tests/image_gen_tests/test_bedrock_image_gen_unit_tests.py @@ -1,14 +1,9 @@ import logging -import os -import sys import traceback from dotenv import load_dotenv from openai.types.image import Image -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path from litellm.llms.bedrock.image_generation.amazon_nova_canvas_transformation import ( AmazonNovaCanvasConfig, @@ -18,13 +13,9 @@ logging.basicConfig(level=logging.DEBUG) load_dotenv() import asyncio -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import pytest from litellm.llms.bedrock.image_generation.cost_calculator import cost_calculator from litellm.types.utils import ImageResponse, ImageObject -import os import litellm from litellm.llms.bedrock.image_generation.amazon_stability3_transformation import ( diff --git a/tests/image_gen_tests/test_fal_ai_image_generation.py b/tests/image_gen_tests/test_fal_ai_image_generation.py index 23032e44ded..d33f2c4262e 100644 --- a/tests/image_gen_tests/test_fal_ai_image_generation.py +++ b/tests/image_gen_tests/test_fal_ai_image_generation.py @@ -1,11 +1,8 @@ import asyncio -import os -import sys from unittest.mock import MagicMock, patch import pytest -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm import aimage_generation diff --git a/tests/image_gen_tests/test_image_edits.py b/tests/image_gen_tests/test_image_edits.py index ca8ec3bbe32..0c2f57066e8 100644 --- a/tests/image_gen_tests/test_image_edits.py +++ b/tests/image_gen_tests/test_image_edits.py @@ -1,6 +1,5 @@ import logging import os -import sys import traceback import asyncio from typing import Optional @@ -11,9 +10,6 @@ from unittest.mock import patch, AsyncMock import json from abc import ABC, abstractmethod -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm.utils import ImageResponse diff --git a/tests/image_gen_tests/test_image_generation.py b/tests/image_gen_tests/test_image_generation.py index 9047557c493..02cee2e8a00 100644 --- a/tests/image_gen_tests/test_image_generation.py +++ b/tests/image_gen_tests/test_image_generation.py @@ -3,14 +3,10 @@ import logging import os -import sys import traceback from unittest.mock import AsyncMock, MagicMock, patch -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path from dotenv import load_dotenv from openai.types.image import Image @@ -19,7 +15,6 @@ from litellm.caching import InMemoryCache logging.basicConfig(level=logging.DEBUG) load_dotenv() import asyncio -import os import pytest import litellm diff --git a/tests/image_gen_tests/test_image_variation.py b/tests/image_gen_tests/test_image_variation.py index 301835057a7..b566385bb8a 100644 --- a/tests/image_gen_tests/test_image_variation.py +++ b/tests/image_gen_tests/test_image_variation.py @@ -2,14 +2,9 @@ ## This tests the litellm support for the openai /generations endpoint import logging -import os -import sys import traceback -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path from dotenv import load_dotenv from openai.types.image import Image @@ -18,7 +13,6 @@ from litellm.caching import InMemoryCache logging.basicConfig(level=logging.DEBUG) load_dotenv() import asyncio -import os import pytest import litellm diff --git a/tests/image_gen_tests/test_xinference.py b/tests/image_gen_tests/test_xinference.py index 6dd56daf193..3dc4fee85da 100644 --- a/tests/image_gen_tests/test_xinference.py +++ b/tests/image_gen_tests/test_xinference.py @@ -1,14 +1,9 @@ import logging -import os -import sys import traceback import pytest import json from unittest.mock import Mock, patch, AsyncMock -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm.types.utils import ImageObject diff --git a/tests/integration/test_oci_integration.py b/tests/integration/test_oci_integration.py index 94b8930bce8..231a3bd8445 100644 --- a/tests/integration/test_oci_integration.py +++ b/tests/integration/test_oci_integration.py @@ -20,12 +20,10 @@ Run only these tests: import math import os -import sys from typing import NamedTuple, Optional import pytest -sys.path.insert(0, os.path.abspath("../..")) # --------------------------------------------------------------------------- # Fixtures / helpers diff --git a/tests/litellm_utils_tests/base_token_counter_test.py b/tests/litellm_utils_tests/base_token_counter_test.py index 9af14dc9f47..ddce27522c2 100644 --- a/tests/litellm_utils_tests/base_token_counter_test.py +++ b/tests/litellm_utils_tests/base_token_counter_test.py @@ -10,16 +10,11 @@ Usage: the abstract methods to provide provider-specific configuration. """ -import os -import sys from abc import ABC, abstractmethod from typing import Any, Dict, List, Optional import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path from litellm.llms.base_llm.base_utils import BaseTokenCounter from litellm.types.utils import TokenCountResponse diff --git a/tests/litellm_utils_tests/conftest.py b/tests/litellm_utils_tests/conftest.py index 39ea4299f35..002ed594d3f 100644 --- a/tests/litellm_utils_tests/conftest.py +++ b/tests/litellm_utils_tests/conftest.py @@ -2,14 +2,9 @@ import asyncio import importlib -import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm # noqa: E402,F401 from tests._vcr_conftest_common import ( # noqa: E402,F401 @@ -38,9 +33,6 @@ def setup_and_teardown(): """ This fixture reloads litellm before every function. To speed up testing by removing callbacks being chained. """ - sys.path.insert( - 0, os.path.abspath("../..") - ) # Adds the project directory to the system path importlib.reload(litellm) diff --git a/tests/litellm_utils_tests/test_aiohttp_handler.py b/tests/litellm_utils_tests/test_aiohttp_handler.py index 14c80d0e0bd..9fdac5ca23d 100644 --- a/tests/litellm_utils_tests/test_aiohttp_handler.py +++ b/tests/litellm_utils_tests/test_aiohttp_handler.py @@ -1,6 +1,5 @@ import asyncio import copy -import sys import time from datetime import datetime from unittest import mock @@ -10,11 +9,7 @@ from dotenv import load_dotenv from litellm.types.utils import StandardCallbackDynamicParams load_dotenv() -import os -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system-path import pytest import litellm diff --git a/tests/litellm_utils_tests/test_anthropic_token_counter.py b/tests/litellm_utils_tests/test_anthropic_token_counter.py index 028586203a5..df3d198b6cf 100644 --- a/tests/litellm_utils_tests/test_anthropic_token_counter.py +++ b/tests/litellm_utils_tests/test_anthropic_token_counter.py @@ -5,14 +5,10 @@ Tests for the Anthropic token counter implementation using the base test suite. """ import os -import sys from typing import Any, Dict, List import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path from litellm.llms.anthropic.count_tokens import AnthropicTokenCounter from litellm.llms.base_llm.base_utils import BaseTokenCounter diff --git a/tests/litellm_utils_tests/test_azure_ai_anthropic_token_counter.py b/tests/litellm_utils_tests/test_azure_ai_anthropic_token_counter.py index 2686c28cb1c..50631eb9341 100644 --- a/tests/litellm_utils_tests/test_azure_ai_anthropic_token_counter.py +++ b/tests/litellm_utils_tests/test_azure_ai_anthropic_token_counter.py @@ -5,14 +5,10 @@ Tests for the Azure AI Anthropic token counter implementation using the base tes """ import os -import sys from typing import Any, Dict, List import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path from litellm.llms.azure_ai.anthropic.count_tokens import AzureAIAnthropicTokenCounter from litellm.llms.base_llm.base_utils import BaseTokenCounter diff --git a/tests/litellm_utils_tests/test_bedrock_token_counter.py b/tests/litellm_utils_tests/test_bedrock_token_counter.py index 9fb2463e8b5..683949fc5c7 100644 --- a/tests/litellm_utils_tests/test_bedrock_token_counter.py +++ b/tests/litellm_utils_tests/test_bedrock_token_counter.py @@ -9,15 +9,11 @@ counting, the test will be skipped. """ import os -import sys from typing import Any, Dict, List from unittest.mock import patch import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path from litellm.llms.base_llm.base_utils import BaseTokenCounter from litellm.llms.bedrock.count_tokens.bedrock_token_counter import BedrockTokenCounter diff --git a/tests/litellm_utils_tests/test_cyberark.py b/tests/litellm_utils_tests/test_cyberark.py index 71daf35a265..9172e33af10 100644 --- a/tests/litellm_utils_tests/test_cyberark.py +++ b/tests/litellm_utils_tests/test_cyberark.py @@ -3,14 +3,12 @@ Integration test for CyberArk Conjur Secret Manager. """ import os -import sys import pytest import yaml from dotenv import load_dotenv load_dotenv() -sys.path.insert(0, os.path.abspath("../..")) from unittest.mock import AsyncMock, MagicMock, patch from litellm._uuid import uuid diff --git a/tests/litellm_utils_tests/test_get_secret.py b/tests/litellm_utils_tests/test_get_secret.py index eec67b5d765..048e668467c 100644 --- a/tests/litellm_utils_tests/test_get_secret.py +++ b/tests/litellm_utils_tests/test_get_secret.py @@ -1,12 +1,7 @@ import json -import os -import sys from datetime import datetime from unittest.mock import AsyncMock, Mock, patch -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import pytest import litellm diff --git a/tests/litellm_utils_tests/test_hashicorp.py b/tests/litellm_utils_tests/test_hashicorp.py index 1d98debef2c..ac9d4af3f53 100644 --- a/tests/litellm_utils_tests/test_hashicorp.py +++ b/tests/litellm_utils_tests/test_hashicorp.py @@ -1,14 +1,10 @@ import os -import sys import pytest from dotenv import load_dotenv load_dotenv() import httpx -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path from unittest.mock import patch, MagicMock import logging from litellm._logging import verbose_logger diff --git a/tests/litellm_utils_tests/test_health_check.py b/tests/litellm_utils_tests/test_health_check.py index 9a17aaeea87..cfdddd20263 100644 --- a/tests/litellm_utils_tests/test_health_check.py +++ b/tests/litellm_utils_tests/test_health_check.py @@ -2,14 +2,10 @@ # This tests if ahealth_check() actually works import os -import sys import pytest from unittest.mock import AsyncMock, patch -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import asyncio import litellm diff --git a/tests/litellm_utils_tests/test_logging_callback_manager.py b/tests/litellm_utils_tests/test_logging_callback_manager.py index 517ba6befd7..ebd5b473ebb 100644 --- a/tests/litellm_utils_tests/test_logging_callback_manager.py +++ b/tests/litellm_utils_tests/test_logging_callback_manager.py @@ -1,14 +1,10 @@ import json import os -import sys import time from datetime import datetime from unittest.mock import AsyncMock, patch, MagicMock import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm.integrations.custom_logger import CustomLogger from litellm.litellm_core_utils.logging_callback_manager import LoggingCallbackManager diff --git a/tests/litellm_utils_tests/test_proxy_budget_reset.py b/tests/litellm_utils_tests/test_proxy_budget_reset.py index 83891b55fb5..9f6e1f4c3f7 100644 --- a/tests/litellm_utils_tests/test_proxy_budget_reset.py +++ b/tests/litellm_utils_tests/test_proxy_budget_reset.py @@ -1,6 +1,4 @@ import asyncio -import os -import sys from datetime import datetime, timedelta, timezone from unittest.mock import AsyncMock, MagicMock, patch @@ -11,9 +9,6 @@ load_dotenv() from litellm.proxy._types import LiteLLM_BudgetTableFull -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path from litellm.proxy.common_utils.reset_budget_job import ResetBudgetJob diff --git a/tests/litellm_utils_tests/test_secret_manager.py b/tests/litellm_utils_tests/test_secret_manager.py index 012889ee00c..4ba928dacd7 100644 --- a/tests/litellm_utils_tests/test_secret_manager.py +++ b/tests/litellm_utils_tests/test_secret_manager.py @@ -1,6 +1,5 @@ import base64 import os -import sys import time import traceback from litellm._uuid import uuid @@ -12,9 +11,6 @@ load_dotenv() import tempfile from uuid import uuid4 -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import pytest import litellm from litellm.llms.azure.azure import get_azure_ad_token_from_oidc diff --git a/tests/litellm_utils_tests/test_utils.py b/tests/litellm_utils_tests/test_utils.py index 0a5327d2662..67f2e1ce06d 100644 --- a/tests/litellm_utils_tests/test_utils.py +++ b/tests/litellm_utils_tests/test_utils.py @@ -1,6 +1,5 @@ import copy import logging -import sys import time from datetime import datetime from unittest import mock @@ -12,9 +11,6 @@ from litellm.types.utils import StandardCallbackDynamicParams load_dotenv() import os -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system-path import pytest import litellm diff --git a/tests/litellm_utils_tests/test_validate_tool_choice.py b/tests/litellm_utils_tests/test_validate_tool_choice.py index 07f8c9ed8f4..b8246fe0deb 100644 --- a/tests/litellm_utils_tests/test_validate_tool_choice.py +++ b/tests/litellm_utils_tests/test_validate_tool_choice.py @@ -1,8 +1,5 @@ import pytest -import sys -import os -sys.path.insert(0, os.path.abspath("../..")) from litellm.utils import validate_chat_completion_tool_choice diff --git a/tests/llm_responses_api_testing/base_responses_api.py b/tests/llm_responses_api_testing/base_responses_api.py index 99ca9fb17b5..74c0478b08b 100644 --- a/tests/llm_responses_api_testing/base_responses_api.py +++ b/tests/llm_responses_api_testing/base_responses_api.py @@ -1,17 +1,12 @@ import httpx import json import pytest -import sys from typing import Any, Dict, List, Optional from unittest.mock import MagicMock, Mock, patch -import os from litellm._uuid import uuid import time import base64 -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from abc import ABC, abstractmethod diff --git a/tests/llm_responses_api_testing/conftest.py b/tests/llm_responses_api_testing/conftest.py index b5884f51275..5501d99cb22 100644 --- a/tests/llm_responses_api_testing/conftest.py +++ b/tests/llm_responses_api_testing/conftest.py @@ -2,14 +2,9 @@ import asyncio import importlib -import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm # noqa: E402 @@ -77,17 +72,12 @@ def setup_and_teardown(): """ This fixture reloads litellm before every function. To speed up testing by removing callbacks being chained. """ - sys.path.insert( - 0, os.path.abspath("../..") - ) # Adds the project directory to the system path importlib.reload(litellm) try: if hasattr(litellm, "proxy") and hasattr(litellm.proxy, "proxy_server"): - import litellm.proxy.proxy_server - importlib.reload(litellm.proxy.proxy_server) except Exception as e: print(f"Error reloading litellm.proxy.proxy_server: {e}") diff --git a/tests/llm_responses_api_testing/test_anthropic_responses_api.py b/tests/llm_responses_api_testing/test_anthropic_responses_api.py index 0ca159219df..8ed85aaa209 100644 --- a/tests/llm_responses_api_testing/test_anthropic_responses_api.py +++ b/tests/llm_responses_api_testing/test_anthropic_responses_api.py @@ -1,5 +1,3 @@ -import os -import sys import pytest import asyncio from typing import Optional @@ -13,7 +11,6 @@ from litellm.responses.litellm_completion_transformation.transformation import ( from litellm.types.utils import ModelResponse -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm.integrations.custom_logger import CustomLogger import json diff --git a/tests/llm_responses_api_testing/test_anthropic_tool_result_empty_call_id.py b/tests/llm_responses_api_testing/test_anthropic_tool_result_empty_call_id.py index 08b1c1784e7..28621c6531f 100644 --- a/tests/llm_responses_api_testing/test_anthropic_tool_result_empty_call_id.py +++ b/tests/llm_responses_api_testing/test_anthropic_tool_result_empty_call_id.py @@ -11,12 +11,9 @@ The issue occurs when: 3. The message is sent to Anthropic without a corresponding tool_use block """ -import os -import sys import pytest from unittest.mock import patch, MagicMock -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm.responses.litellm_completion_transformation.transformation import ( LiteLLMCompletionResponsesConfig, diff --git a/tests/llm_responses_api_testing/test_anthropic_tool_result_fix.py b/tests/llm_responses_api_testing/test_anthropic_tool_result_fix.py index d7c15c7609f..d203b0f6917 100644 --- a/tests/llm_responses_api_testing/test_anthropic_tool_result_fix.py +++ b/tests/llm_responses_api_testing/test_anthropic_tool_result_fix.py @@ -5,13 +5,10 @@ This test verifies that when using previous_response_id with tool_result, the fix ensures tool_calls are added to the previous assistant message. """ -import os -import sys import pytest import json from unittest.mock import patch, AsyncMock -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm.responses.litellm_completion_transformation.transformation import ( LiteLLMCompletionResponsesConfig, diff --git a/tests/llm_responses_api_testing/test_azure_responses_api.py b/tests/llm_responses_api_testing/test_azure_responses_api.py index 79990a88496..6f1bb440341 100644 --- a/tests/llm_responses_api_testing/test_azure_responses_api.py +++ b/tests/llm_responses_api_testing/test_azure_responses_api.py @@ -1,10 +1,8 @@ import os -import sys import pytest import asyncio from unittest.mock import patch, AsyncMock -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm.integrations.custom_logger import CustomLogger import json diff --git a/tests/llm_responses_api_testing/test_base_responses_api_streaming_iterator.py b/tests/llm_responses_api_testing/test_base_responses_api_streaming_iterator.py index 5388c5aef83..bd617587cf3 100644 --- a/tests/llm_responses_api_testing/test_base_responses_api_streaming_iterator.py +++ b/tests/llm_responses_api_testing/test_base_responses_api_streaming_iterator.py @@ -13,15 +13,12 @@ response tracking and logging. """ import json -import os -import sys from datetime import datetime from typing import Any, Dict, Optional from unittest.mock import Mock, patch import pytest -sys.path.insert(0, os.path.abspath("../..")) from litellm.constants import STREAM_SSE_DONE_STRING from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj diff --git a/tests/llm_responses_api_testing/test_google_ai_studio_responses_api.py b/tests/llm_responses_api_testing/test_google_ai_studio_responses_api.py index 3ed92bd760d..d84e9cc66e3 100644 --- a/tests/llm_responses_api_testing/test_google_ai_studio_responses_api.py +++ b/tests/llm_responses_api_testing/test_google_ai_studio_responses_api.py @@ -1,9 +1,7 @@ import os -import sys import pytest from unittest.mock import patch, AsyncMock -sys.path.insert(0, os.path.abspath("../..")) import litellm import json from base_responses_api import BaseResponsesAPITest diff --git a/tests/llm_responses_api_testing/test_openai_responses_api.py b/tests/llm_responses_api_testing/test_openai_responses_api.py index d614c40f5d0..5f77d5a5477 100644 --- a/tests/llm_responses_api_testing/test_openai_responses_api.py +++ b/tests/llm_responses_api_testing/test_openai_responses_api.py @@ -1,5 +1,4 @@ import os -import sys import pytest import asyncio from typing import Optional, cast @@ -10,7 +9,6 @@ from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLogging import time import json -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm.integrations.custom_logger import CustomLogger from litellm.types.utils import StandardLoggingPayload diff --git a/tests/llm_translation/base_audio_transcription_unit_tests.py b/tests/llm_translation/base_audio_transcription_unit_tests.py index 71f2aa79ce5..76401b456fa 100644 --- a/tests/llm_translation/base_audio_transcription_unit_tests.py +++ b/tests/llm_translation/base_audio_transcription_unit_tests.py @@ -1,15 +1,11 @@ import httpx import json import pytest -import sys from typing import Any, Dict, List from unittest.mock import MagicMock, Mock, patch import os from litellm._uuid import uuid -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm import transcription from litellm.litellm_core_utils.get_supported_openai_params import ( diff --git a/tests/llm_translation/base_embedding_unit_tests.py b/tests/llm_translation/base_embedding_unit_tests.py index 30a9dcc0da3..1a88f0e9d6b 100644 --- a/tests/llm_translation/base_embedding_unit_tests.py +++ b/tests/llm_translation/base_embedding_unit_tests.py @@ -2,14 +2,10 @@ import asyncio import httpx import json import pytest -import sys from typing import Any, Dict, List from unittest.mock import MagicMock, Mock, patch import os -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm import embedding from litellm.exceptions import BadRequestError diff --git a/tests/llm_translation/base_llm_unit_tests.py b/tests/llm_translation/base_llm_unit_tests.py index 6d845f4b2f1..1a33422a31c 100644 --- a/tests/llm_translation/base_llm_unit_tests.py +++ b/tests/llm_translation/base_llm_unit_tests.py @@ -10,9 +10,6 @@ import time import base64 import inspect -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm.exceptions import BadRequestError from litellm.llms.custom_httpx.http_handler import AsyncHTTPHandler, HTTPHandler diff --git a/tests/llm_translation/base_rerank_unit_tests.py b/tests/llm_translation/base_rerank_unit_tests.py index 57878c8f171..df7dd33d7b0 100644 --- a/tests/llm_translation/base_rerank_unit_tests.py +++ b/tests/llm_translation/base_rerank_unit_tests.py @@ -2,14 +2,10 @@ import asyncio import httpx import json import pytest -import sys from typing import Any, Dict, List from unittest.mock import MagicMock, Mock, patch import os -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm.exceptions import BadRequestError from litellm.llms.custom_httpx.http_handler import AsyncHTTPHandler, HTTPHandler diff --git a/tests/llm_translation/conftest.py b/tests/llm_translation/conftest.py index f5b71236e92..8532af2851c 100644 --- a/tests/llm_translation/conftest.py +++ b/tests/llm_translation/conftest.py @@ -7,14 +7,9 @@ import asyncio import importlib -import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm # noqa: E402 @@ -123,7 +118,6 @@ def event_loop(): @pytest.fixture(scope="function", autouse=True) def setup_and_teardown(event_loop): # Add event_loop as a dependency - sys.path.insert(0, os.path.abspath("../..")) import litellm diff --git a/tests/llm_translation/realtime/base_realtime_tests.py b/tests/llm_translation/realtime/base_realtime_tests.py index 1a2c6ff6a9c..964e1d0ac59 100644 --- a/tests/llm_translation/realtime/base_realtime_tests.py +++ b/tests/llm_translation/realtime/base_realtime_tests.py @@ -8,14 +8,12 @@ across different providers (OpenAI, xAI, etc.) import asyncio import json import os -import sys from abc import ABC, abstractmethod from typing import Optional, Tuple, Union import pytest import websockets -sys.path.insert(0, os.path.abspath("../../..")) import litellm diff --git a/tests/llm_translation/realtime/test_openai_realtime.py b/tests/llm_translation/realtime/test_openai_realtime.py index 0e50e2792d6..add22117590 100644 --- a/tests/llm_translation/realtime/test_openai_realtime.py +++ b/tests/llm_translation/realtime/test_openai_realtime.py @@ -1,13 +1,9 @@ import os -import sys from unittest.mock import AsyncMock, MagicMock import pytest from websockets.exceptions import ConnectionClosedError, ConnectionClosedOK -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm.types.realtime import RealtimeQueryParams diff --git a/tests/llm_translation/realtime/test_openai_realtime_simple.py b/tests/llm_translation/realtime/test_openai_realtime_simple.py index 073c1ce11af..93451a6617e 100644 --- a/tests/llm_translation/realtime/test_openai_realtime_simple.py +++ b/tests/llm_translation/realtime/test_openai_realtime_simple.py @@ -5,12 +5,9 @@ Tests OpenAI's Realtime API through LiteLLM's realtime interface. Uses the base test class to ensure consistent behavior across providers. """ -import os -import sys import pytest -sys.path.insert(0, os.path.abspath("../../..")) from tests.llm_translation.realtime.base_realtime_tests import BaseRealtimeTest diff --git a/tests/llm_translation/realtime/test_xai_realtime.py b/tests/llm_translation/realtime/test_xai_realtime.py index 8ffcb3db30d..19cf8624c48 100644 --- a/tests/llm_translation/realtime/test_xai_realtime.py +++ b/tests/llm_translation/realtime/test_xai_realtime.py @@ -5,13 +5,10 @@ Tests xAI's Grok Voice Agent API through LiteLLM's realtime interface. Uses the base test class to ensure consistent behavior across providers. """ -import os -import sys from typing import Tuple import pytest -sys.path.insert(0, os.path.abspath("../../..")) from tests.llm_translation.realtime.base_realtime_tests import BaseRealtimeTest diff --git a/tests/llm_translation/test_a2a.py b/tests/llm_translation/test_a2a.py index ec260acd1ae..1f647092abf 100644 --- a/tests/llm_translation/test_a2a.py +++ b/tests/llm_translation/test_a2a.py @@ -6,11 +6,9 @@ streaming and non-streaming requests. """ import os -import sys import pytest -sys.path.insert(0, os.path.abspath("../..")) import litellm diff --git a/tests/llm_translation/test_anthropic_completion.py b/tests/llm_translation/test_anthropic_completion.py index ab1c67dffbf..8c55014955f 100644 --- a/tests/llm_translation/test_anthropic_completion.py +++ b/tests/llm_translation/test_anthropic_completion.py @@ -3,7 +3,6 @@ import asyncio import os -import sys import traceback from dotenv import load_dotenv @@ -15,9 +14,6 @@ from litellm.llms.anthropic.chat import ModelResponseIterator load_dotenv() import io -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path from typing import Optional from unittest.mock import MagicMock, patch diff --git a/tests/llm_translation/test_azure_agents.py b/tests/llm_translation/test_azure_agents.py index 6a737cc102b..e0741471582 100644 --- a/tests/llm_translation/test_azure_agents.py +++ b/tests/llm_translation/test_azure_agents.py @@ -25,9 +25,7 @@ See: https://learn.microsoft.com/en-us/azure/ai-foundry/agents/quickstart import json import os -import sys -sys.path.insert(0, os.path.abspath("../..")) import pytest from unittest.mock import MagicMock diff --git a/tests/llm_translation/test_azure_ai.py b/tests/llm_translation/test_azure_ai.py index 553f9102246..5be6ade80ab 100644 --- a/tests/llm_translation/test_azure_ai.py +++ b/tests/llm_translation/test_azure_ai.py @@ -3,7 +3,6 @@ import asyncio import os -import sys import traceback from dotenv import load_dotenv @@ -20,9 +19,6 @@ from litellm.llms.custom_httpx.http_handler import HTTPHandler load_dotenv() import io -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path from typing import Optional from unittest.mock import MagicMock, patch diff --git a/tests/llm_translation/test_azure_o_series.py b/tests/llm_translation/test_azure_o_series.py index ab122d3ff6a..1a2d672af71 100644 --- a/tests/llm_translation/test_azure_o_series.py +++ b/tests/llm_translation/test_azure_o_series.py @@ -1,12 +1,8 @@ import json import os -import sys from datetime import datetime from unittest.mock import AsyncMock, patch, MagicMock -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import httpx diff --git a/tests/llm_translation/test_azure_openai.py b/tests/llm_translation/test_azure_openai.py index 0deb20900a7..0fa72b45ed8 100644 --- a/tests/llm_translation/test_azure_openai.py +++ b/tests/llm_translation/test_azure_openai.py @@ -1,9 +1,5 @@ -import sys import os -sys.path.insert( - 0, os.path.abspath("../../") -) # Adds the parent directory to the system path import httpx import pytest @@ -103,7 +99,6 @@ from unittest.mock import MagicMock, patch from openai import AzureOpenAI import litellm from litellm import completion -import os @pytest.mark.parametrize( diff --git a/tests/llm_translation/test_bedrock_agentcore.py b/tests/llm_translation/test_bedrock_agentcore.py index 40774cf3d60..0087eb5b326 100644 --- a/tests/llm_translation/test_bedrock_agentcore.py +++ b/tests/llm_translation/test_bedrock_agentcore.py @@ -2,13 +2,10 @@ Test Bedrock AgentCore integration """ -import os -import sys from dotenv import load_dotenv load_dotenv() -sys.path.insert(0, os.path.abspath("../..")) import litellm from unittest.mock import MagicMock, Mock, patch diff --git a/tests/llm_translation/test_bedrock_agents.py b/tests/llm_translation/test_bedrock_agents.py index 6371224def9..1685dd220d2 100644 --- a/tests/llm_translation/test_bedrock_agents.py +++ b/tests/llm_translation/test_bedrock_agents.py @@ -1,5 +1,3 @@ -import os -import sys import traceback from dotenv import load_dotenv @@ -10,9 +8,6 @@ load_dotenv() import io import json -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path from unittest.mock import AsyncMock, Mock, patch import pytest diff --git a/tests/llm_translation/test_bedrock_anthropic_regression.py b/tests/llm_translation/test_bedrock_anthropic_regression.py index 8b8ce0a6cc8..8f2974f531c 100644 --- a/tests/llm_translation/test_bedrock_anthropic_regression.py +++ b/tests/llm_translation/test_bedrock_anthropic_regression.py @@ -11,13 +11,10 @@ feature parity and prevent regression of previously fixed issues. """ import json -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import pytest -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm import completion diff --git a/tests/llm_translation/test_bedrock_completion.py b/tests/llm_translation/test_bedrock_completion.py index 6ee6e5d1493..550e82fb5bb 100644 --- a/tests/llm_translation/test_bedrock_completion.py +++ b/tests/llm_translation/test_bedrock_completion.py @@ -4,7 +4,6 @@ Tests Bedrock Completion + Rerank endpoints # @pytest.mark.skip(reason="AWS Suspended Account") import os -import sys import traceback from dotenv import load_dotenv @@ -15,9 +14,6 @@ load_dotenv() import io import json -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path from unittest.mock import AsyncMock, Mock, patch import pytest diff --git a/tests/llm_translation/test_bedrock_dynamic_auth_params_unit_tests.py b/tests/llm_translation/test_bedrock_dynamic_auth_params_unit_tests.py index 5d2fab15a8f..dad2fdbf065 100644 --- a/tests/llm_translation/test_bedrock_dynamic_auth_params_unit_tests.py +++ b/tests/llm_translation/test_bedrock_dynamic_auth_params_unit_tests.py @@ -1,14 +1,9 @@ # tests/llm_translation/test_base_aws_llm.py -import os import json import pytest from unittest.mock import patch from botocore.credentials import Credentials -import sys -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm.llms.custom_httpx.http_handler import HTTPHandler diff --git a/tests/llm_translation/test_bedrock_embedding.py b/tests/llm_translation/test_bedrock_embedding.py index e343b8856a7..56baed141da 100644 --- a/tests/llm_translation/test_bedrock_embedding.py +++ b/tests/llm_translation/test_bedrock_embedding.py @@ -1,15 +1,11 @@ import json import os -import sys from datetime import datetime from unittest.mock import AsyncMock, Mock, patch import pytest import base64 import httpx -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm.llms.custom_httpx.http_handler import HTTPHandler, AsyncHTTPHandler diff --git a/tests/llm_translation/test_bedrock_gpt_oss.py b/tests/llm_translation/test_bedrock_gpt_oss.py index 0a595ad7114..4af81ee81f7 100644 --- a/tests/llm_translation/test_bedrock_gpt_oss.py +++ b/tests/llm_translation/test_bedrock_gpt_oss.py @@ -1,13 +1,8 @@ from base_llm_unit_tests import BaseLLMChatTest import json import pytest -import sys -import os from unittest.mock import patch, Mock, MagicMock -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm.llms.bedrock.chat.converse_transformation import AmazonConverseConfig from litellm.llms.custom_httpx.http_handler import HTTPHandler diff --git a/tests/llm_translation/test_bedrock_invoke_tests.py b/tests/llm_translation/test_bedrock_invoke_tests.py index 901b43542f7..cf53899ecf6 100644 --- a/tests/llm_translation/test_bedrock_invoke_tests.py +++ b/tests/llm_translation/test_bedrock_invoke_tests.py @@ -1,11 +1,7 @@ from base_llm_unit_tests import BaseLLMChatTest import pytest -import sys import os -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm.types.llms.bedrock import BedrockInvokeNovaRequest diff --git a/tests/llm_translation/test_bedrock_llama.py b/tests/llm_translation/test_bedrock_llama.py index b18928747eb..6c1a7073c13 100644 --- a/tests/llm_translation/test_bedrock_llama.py +++ b/tests/llm_translation/test_bedrock_llama.py @@ -1,11 +1,6 @@ from base_llm_unit_tests import BaseLLMChatTest import pytest -import sys -import os -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm diff --git a/tests/llm_translation/test_bedrock_mantle.py b/tests/llm_translation/test_bedrock_mantle.py index 46a0c653005..70919a07bb9 100644 --- a/tests/llm_translation/test_bedrock_mantle.py +++ b/tests/llm_translation/test_bedrock_mantle.py @@ -9,14 +9,11 @@ Tests use a fake/mocked HTTP layer to verify the full request pipeline: """ import json -import os -import sys from unittest.mock import MagicMock, patch import httpx import pytest -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm.llms.custom_httpx.http_handler import HTTPHandler diff --git a/tests/llm_translation/test_bedrock_moonshot.py b/tests/llm_translation/test_bedrock_moonshot.py index a82d1c6f029..3bf047c51a5 100644 --- a/tests/llm_translation/test_bedrock_moonshot.py +++ b/tests/llm_translation/test_bedrock_moonshot.py @@ -14,13 +14,11 @@ This test suite verifies: from base_llm_unit_tests import BaseLLMChatTest import httpx import pytest -import sys import os import json from typing import Optional from unittest.mock import AsyncMock, Mock, patch -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm.llms.bedrock.common_utils import get_bedrock_chat_config from litellm.llms.custom_httpx.http_handler import AsyncHTTPHandler, HTTPHandler diff --git a/tests/llm_translation/test_bedrock_nova_embedding.py b/tests/llm_translation/test_bedrock_nova_embedding.py index 9795dc3d8d5..c4fd0724884 100644 --- a/tests/llm_translation/test_bedrock_nova_embedding.py +++ b/tests/llm_translation/test_bedrock_nova_embedding.py @@ -11,15 +11,10 @@ Tests cover: """ import json -import os -import sys from unittest.mock import MagicMock, Mock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm.llms.bedrock.embed.amazon_nova_transformation import ( diff --git a/tests/llm_translation/test_bedrock_nova_json.py b/tests/llm_translation/test_bedrock_nova_json.py index 7531891c4ef..754ef4e3525 100644 --- a/tests/llm_translation/test_bedrock_nova_json.py +++ b/tests/llm_translation/test_bedrock_nova_json.py @@ -1,11 +1,6 @@ from base_llm_unit_tests import BaseLLMChatTest import pytest -import sys -import os -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm diff --git a/tests/llm_translation/test_cohere.py b/tests/llm_translation/test_cohere.py index 0eb0b1b33fe..729f42f8984 100644 --- a/tests/llm_translation/test_cohere.py +++ b/tests/llm_translation/test_cohere.py @@ -1,5 +1,3 @@ -import os -import sys import traceback from dotenv import load_dotenv @@ -7,9 +5,6 @@ from dotenv import load_dotenv load_dotenv() import io -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import json import pytest diff --git a/tests/llm_translation/test_containers_api.py b/tests/llm_translation/test_containers_api.py index 7fb0c6d21d6..c5248516a1c 100644 --- a/tests/llm_translation/test_containers_api.py +++ b/tests/llm_translation/test_containers_api.py @@ -5,12 +5,10 @@ Tests the container files endpoints using LiteLLM SDK methods. """ import os -import sys import time import pytest -sys.path.insert(0, os.path.abspath("../..")) from litellm.containers import ( create_container, diff --git a/tests/llm_translation/test_convert_dict_to_image.py b/tests/llm_translation/test_convert_dict_to_image.py index 62a7eec8cbb..df6e2bcb4a3 100644 --- a/tests/llm_translation/test_convert_dict_to_image.py +++ b/tests/llm_translation/test_convert_dict_to_image.py @@ -1,11 +1,6 @@ import json -import os -import sys from datetime import datetime -sys.path.insert( - 0, os.path.abspath("../../") -) # Adds the parent directory to the system path import litellm import pytest diff --git a/tests/llm_translation/test_databricks.py b/tests/llm_translation/test_databricks.py index 3a224231667..46caae0e7bd 100644 --- a/tests/llm_translation/test_databricks.py +++ b/tests/llm_translation/test_databricks.py @@ -6,11 +6,7 @@ import sys from typing import Any, Dict, List from unittest.mock import MagicMock, Mock, patch, ANY -import os -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm.exceptions import BadRequestError from litellm.llms.custom_httpx.http_handler import AsyncHTTPHandler, HTTPHandler diff --git a/tests/llm_translation/test_deepgram.py b/tests/llm_translation/test_deepgram.py index 204d6c01cf8..855d570488b 100644 --- a/tests/llm_translation/test_deepgram.py +++ b/tests/llm_translation/test_deepgram.py @@ -1,11 +1,6 @@ -import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from base_audio_transcription_unit_tests import BaseLLMAudioTranscriptionTest diff --git a/tests/llm_translation/test_elevenlabs.py b/tests/llm_translation/test_elevenlabs.py index b6c838d2300..9dc4a1d09ed 100644 --- a/tests/llm_translation/test_elevenlabs.py +++ b/tests/llm_translation/test_elevenlabs.py @@ -1,5 +1,4 @@ import os -import sys from typing import Any, Dict @@ -7,9 +6,6 @@ import pytest from unittest.mock import patch, MagicMock import httpx -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from base_audio_transcription_unit_tests import BaseLLMAudioTranscriptionTest diff --git a/tests/llm_translation/test_evals_api.py b/tests/llm_translation/test_evals_api.py index 4a55663e669..ba6b5edf3cd 100644 --- a/tests/llm_translation/test_evals_api.py +++ b/tests/llm_translation/test_evals_api.py @@ -4,13 +4,11 @@ Tests for Evals API operations across providers import hashlib import os -import sys from abc import ABC, abstractmethod from typing import Optional import pytest -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm.types.llms.openai_evals import ( diff --git a/tests/llm_translation/test_fireworks_ai_translation.py b/tests/llm_translation/test_fireworks_ai_translation.py index 27059581e4d..e20134fc1bf 100644 --- a/tests/llm_translation/test_fireworks_ai_translation.py +++ b/tests/llm_translation/test_fireworks_ai_translation.py @@ -1,11 +1,6 @@ -import os -import sys import json import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm.litellm_core_utils.get_supported_openai_params import ( get_supported_openai_params, diff --git a/tests/llm_translation/test_gemini.py b/tests/llm_translation/test_gemini.py index 310a2e2c20c..0c3eca52dde 100644 --- a/tests/llm_translation/test_gemini.py +++ b/tests/llm_translation/test_gemini.py @@ -1,11 +1,7 @@ import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system paths from base_llm_unit_tests import BaseLLMChatTest from litellm.llms.vertex_ai.context_caching.transformation import ( diff --git a/tests/llm_translation/test_gpt4o_audio.py b/tests/llm_translation/test_gpt4o_audio.py index a50d07406d4..0f20119e4ef 100644 --- a/tests/llm_translation/test_gpt4o_audio.py +++ b/tests/llm_translation/test_gpt4o_audio.py @@ -1,12 +1,7 @@ import json -import os -import sys from datetime import datetime from unittest.mock import AsyncMock -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import httpx diff --git a/tests/llm_translation/test_hosted_vllm_embedding_e2e.py b/tests/llm_translation/test_hosted_vllm_embedding_e2e.py index 4b887013357..23ad63ab6da 100644 --- a/tests/llm_translation/test_hosted_vllm_embedding_e2e.py +++ b/tests/llm_translation/test_hosted_vllm_embedding_e2e.py @@ -5,13 +5,9 @@ This test verifies that the hosted_vllm provider works correctly with real API e """ import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm diff --git a/tests/llm_translation/test_huggingface_chat_completion.py b/tests/llm_translation/test_huggingface_chat_completion.py index cdf3f9ef76f..90e6c2adb8d 100644 --- a/tests/llm_translation/test_huggingface_chat_completion.py +++ b/tests/llm_translation/test_huggingface_chat_completion.py @@ -3,15 +3,10 @@ Test HuggingFace LLM """ import json -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch from base_llm_unit_tests import BaseLLMChatTest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import pytest diff --git a/tests/llm_translation/test_hyperbolic.py b/tests/llm_translation/test_hyperbolic.py index 006d31c88e6..78817fbd902 100644 --- a/tests/llm_translation/test_hyperbolic.py +++ b/tests/llm_translation/test_hyperbolic.py @@ -1,13 +1,9 @@ import os -import sys from datetime import datetime from unittest.mock import MagicMock import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm import get_llm_provider @@ -76,7 +72,6 @@ def test_hyperbolic_in_provider_lists(): def test_hyperbolic_models_configuration(): """Test that Hyperbolic models are properly configured""" import json - import os # Load model configuration directly from the JSON file json_path = os.path.join( diff --git a/tests/llm_translation/test_infinity.py b/tests/llm_translation/test_infinity.py index 5ca3d377fd7..1829113e045 100644 --- a/tests/llm_translation/test_infinity.py +++ b/tests/llm_translation/test_infinity.py @@ -1,25 +1,15 @@ import json -import os -import sys from datetime import datetime from unittest.mock import AsyncMock -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system-path import litellm -import os -import sys from unittest.mock import patch, MagicMock import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system-path from test_rerank import assert_response_shape from base_embedding_unit_tests import BaseLLMEmbeddingTest diff --git a/tests/llm_translation/test_jina_ai.py b/tests/llm_translation/test_jina_ai.py index 00810369ed7..81527293a00 100644 --- a/tests/llm_translation/test_jina_ai.py +++ b/tests/llm_translation/test_jina_ai.py @@ -1,12 +1,7 @@ import json -import os -import sys from datetime import datetime from unittest.mock import AsyncMock -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path from base_rerank_unit_tests import BaseLLMRerankTest diff --git a/tests/llm_translation/test_langgraph.py b/tests/llm_translation/test_langgraph.py index fa3a7f91b6b..3d0de508e7c 100644 --- a/tests/llm_translation/test_langgraph.py +++ b/tests/llm_translation/test_langgraph.py @@ -19,9 +19,7 @@ Non-streaming: """ import os -import sys -sys.path.insert(0, os.path.abspath("../..")) import pytest diff --git a/tests/llm_translation/test_litellm_proxy_provider.py b/tests/llm_translation/test_litellm_proxy_provider.py index 7a917c226df..1cb805bf9ba 100644 --- a/tests/llm_translation/test_litellm_proxy_provider.py +++ b/tests/llm_translation/test_litellm_proxy_provider.py @@ -1,14 +1,9 @@ import json -import os import re -import sys from datetime import datetime from io import BytesIO from unittest.mock import AsyncMock -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system-path import litellm from litellm import completion, embedding diff --git a/tests/llm_translation/test_llm_response_utils/test_convert_dict_to_chat_completion.py b/tests/llm_translation/test_llm_response_utils/test_convert_dict_to_chat_completion.py index 8c7390d3d04..b6e30ddc711 100644 --- a/tests/llm_translation/test_llm_response_utils/test_convert_dict_to_chat_completion.py +++ b/tests/llm_translation/test_llm_response_utils/test_convert_dict_to_chat_completion.py @@ -1,11 +1,6 @@ import json -import os -import sys from datetime import datetime -sys.path.insert( - 0, os.path.abspath("../../../") -) # Adds the parent directory to the system path import litellm import pytest diff --git a/tests/llm_translation/test_llm_response_utils/test_get_headers.py b/tests/llm_translation/test_llm_response_utils/test_get_headers.py index f0cc7ca61f1..380f89bbdd4 100644 --- a/tests/llm_translation/test_llm_response_utils/test_get_headers.py +++ b/tests/llm_translation/test_llm_response_utils/test_get_headers.py @@ -1,11 +1,6 @@ import json -import os -import sys from datetime import datetime -sys.path.insert( - 0, os.path.abspath("../../") -) # Adds the parent directory to the system path import litellm import pytest diff --git a/tests/llm_translation/test_minimax_tts.py b/tests/llm_translation/test_minimax_tts.py index e10b32fb39b..660e49b664f 100644 --- a/tests/llm_translation/test_minimax_tts.py +++ b/tests/llm_translation/test_minimax_tts.py @@ -3,15 +3,11 @@ Tests for MiniMax Text-to-Speech integration """ import os -import sys from pathlib import Path from unittest.mock import MagicMock, Mock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm import speech diff --git a/tests/llm_translation/test_mistral_api.py b/tests/llm_translation/test_mistral_api.py index 62f69e616ab..9e2f726a020 100644 --- a/tests/llm_translation/test_mistral_api.py +++ b/tests/llm_translation/test_mistral_api.py @@ -1,6 +1,4 @@ import asyncio -import os -import sys import traceback from dotenv import load_dotenv @@ -12,9 +10,6 @@ from litellm.llms.anthropic.chat import ModelResponseIterator load_dotenv() import io -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path from typing import Optional from unittest.mock import MagicMock, patch diff --git a/tests/llm_translation/test_morph.py b/tests/llm_translation/test_morph.py index a24ace5ca6d..b91d1810d38 100644 --- a/tests/llm_translation/test_morph.py +++ b/tests/llm_translation/test_morph.py @@ -1,12 +1,8 @@ """Unit tests for Morph provider integration.""" import os -import sys from unittest.mock import patch -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm import MorphChatConfig, get_llm_provider diff --git a/tests/llm_translation/test_nvidia_nim.py b/tests/llm_translation/test_nvidia_nim.py index 79c792d1644..7ee4f347f72 100644 --- a/tests/llm_translation/test_nvidia_nim.py +++ b/tests/llm_translation/test_nvidia_nim.py @@ -1,12 +1,7 @@ import json -import os -import sys from datetime import datetime from unittest.mock import AsyncMock -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import httpx diff --git a/tests/llm_translation/test_openai.py b/tests/llm_translation/test_openai.py index 405dbb0e6ec..2b9abdec5d0 100644 --- a/tests/llm_translation/test_openai.py +++ b/tests/llm_translation/test_openai.py @@ -1,13 +1,8 @@ import json -import os -import sys from datetime import datetime from unittest.mock import AsyncMock, patch from typing import Optional -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import httpx diff --git a/tests/llm_translation/test_openai_o1.py b/tests/llm_translation/test_openai_o1.py index dbaf20717a0..e188a3af647 100644 --- a/tests/llm_translation/test_openai_o1.py +++ b/tests/llm_translation/test_openai_o1.py @@ -1,12 +1,8 @@ import json import os -import sys from datetime import datetime from unittest.mock import AsyncMock, patch, MagicMock -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import httpx diff --git a/tests/llm_translation/test_openrouter.py b/tests/llm_translation/test_openrouter.py index 8fbb8803d11..8ecf9b4a8a2 100644 --- a/tests/llm_translation/test_openrouter.py +++ b/tests/llm_translation/test_openrouter.py @@ -1,10 +1,5 @@ -import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system paths import litellm diff --git a/tests/llm_translation/test_optional_params.py b/tests/llm_translation/test_optional_params.py index 814f5a235e1..997f5b3b73f 100644 --- a/tests/llm_translation/test_optional_params.py +++ b/tests/llm_translation/test_optional_params.py @@ -2,14 +2,11 @@ # This tests if get_optional_params works as expected import asyncio import inspect -import os -import sys import time import traceback import pytest -sys.path.insert(0, os.path.abspath("../..")) from unittest.mock import MagicMock, patch import litellm diff --git a/tests/llm_translation/test_perplexity_reasoning.py b/tests/llm_translation/test_perplexity_reasoning.py index 2ea28b76696..61fbc9d7824 100644 --- a/tests/llm_translation/test_perplexity_reasoning.py +++ b/tests/llm_translation/test_perplexity_reasoning.py @@ -1,13 +1,9 @@ import json import os -import sys from unittest.mock import patch, MagicMock import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm import completion diff --git a/tests/llm_translation/test_prompt_caching.py b/tests/llm_translation/test_prompt_caching.py index eb4703fd677..341973168e8 100644 --- a/tests/llm_translation/test_prompt_caching.py +++ b/tests/llm_translation/test_prompt_caching.py @@ -1,12 +1,7 @@ import json -import os -import sys from datetime import datetime from unittest.mock import AsyncMock -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import httpx diff --git a/tests/llm_translation/test_prompt_factory.py b/tests/llm_translation/test_prompt_factory.py index 1b4c8a82cf4..a90a3df584e 100644 --- a/tests/llm_translation/test_prompt_factory.py +++ b/tests/llm_translation/test_prompt_factory.py @@ -1,11 +1,8 @@ #### What this tests #### # This tests if prompts are being correctly formatted -import os -import sys import pytest -sys.path.insert(0, os.path.abspath("../..")) from typing import List diff --git a/tests/llm_translation/test_replicate.py b/tests/llm_translation/test_replicate.py index 8972d115882..eb8987f5444 100644 --- a/tests/llm_translation/test_replicate.py +++ b/tests/llm_translation/test_replicate.py @@ -4,13 +4,10 @@ Unit tests for Replicate provider, particularly testing DeepSeek models import asyncio import json -import os -import sys from unittest.mock import AsyncMock, MagicMock, Mock, patch import pytest -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm import completion diff --git a/tests/llm_translation/test_rerank.py b/tests/llm_translation/test_rerank.py index cb254542009..3009928c9bc 100644 --- a/tests/llm_translation/test_rerank.py +++ b/tests/llm_translation/test_rerank.py @@ -1,7 +1,6 @@ import asyncio import json import os -import sys import traceback from dotenv import load_dotenv @@ -10,11 +9,7 @@ load_dotenv() import io from typing import Optional, Dict -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path -import os from unittest.mock import AsyncMock, MagicMock, patch import pytest diff --git a/tests/llm_translation/test_router_llm_translation_tests.py b/tests/llm_translation/test_router_llm_translation_tests.py index 26456ab0a35..10807adf356 100644 --- a/tests/llm_translation/test_router_llm_translation_tests.py +++ b/tests/llm_translation/test_router_llm_translation_tests.py @@ -4,13 +4,9 @@ Uses litellm.Router, ensures router.completion and router.acompletion pass BaseL import asyncio import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from base_llm_unit_tests import BaseLLMChatTest diff --git a/tests/llm_translation/test_skills_api.py b/tests/llm_translation/test_skills_api.py index e1830e50ef9..aeab5f0da3e 100644 --- a/tests/llm_translation/test_skills_api.py +++ b/tests/llm_translation/test_skills_api.py @@ -3,7 +3,6 @@ Tests for Skills API operations across providers """ import os -import sys import zipfile from abc import ABC, abstractmethod from contextlib import contextmanager @@ -12,7 +11,6 @@ from typing import Optional import pytest -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm.types.llms.anthropic_skills import ( @@ -143,7 +141,6 @@ class BaseSkillsAPITest(ABC): """ Test listing skills. """ - import os custom_llm_provider = self.get_custom_llm_provider() api_key = self.get_api_key() diff --git a/tests/llm_translation/test_text_completion.py b/tests/llm_translation/test_text_completion.py index 38d2dd95de7..7f81a6a3449 100644 --- a/tests/llm_translation/test_text_completion.py +++ b/tests/llm_translation/test_text_completion.py @@ -1,11 +1,6 @@ import json -import os -import sys from datetime import datetime -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm import pytest diff --git a/tests/llm_translation/test_text_completion_unit_tests.py b/tests/llm_translation/test_text_completion_unit_tests.py index 55026ba0542..d741786ad44 100644 --- a/tests/llm_translation/test_text_completion_unit_tests.py +++ b/tests/llm_translation/test_text_completion_unit_tests.py @@ -1,6 +1,4 @@ import json -import os -import sys from datetime import datetime from unittest.mock import AsyncMock import pytest @@ -8,9 +6,6 @@ import httpx from respx import MockRouter from unittest.mock import patch, MagicMock -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm.types.utils import TextCompletionResponse diff --git a/tests/llm_translation/test_together_ai.py b/tests/llm_translation/test_together_ai.py index 387e61656ea..c371caefa5e 100644 --- a/tests/llm_translation/test_together_ai.py +++ b/tests/llm_translation/test_together_ai.py @@ -5,13 +5,9 @@ Test TogetherAI LLM from base_llm_unit_tests import BaseLLMChatTest import json import os -import sys from datetime import datetime from unittest.mock import AsyncMock -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm import pytest diff --git a/tests/llm_translation/test_triton.py b/tests/llm_translation/test_triton.py index f9ab3bfaff7..a5d66809421 100644 --- a/tests/llm_translation/test_triton.py +++ b/tests/llm_translation/test_triton.py @@ -1,6 +1,4 @@ import json -import os -import sys import traceback from dotenv import load_dotenv @@ -9,9 +7,6 @@ load_dotenv() import io from unittest.mock import AsyncMock, MagicMock, patch -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import pytest import litellm diff --git a/tests/llm_translation/test_unit_test_bedrock_invoke.py b/tests/llm_translation/test_unit_test_bedrock_invoke.py index 586b04384d5..e6cf4695089 100644 --- a/tests/llm_translation/test_unit_test_bedrock_invoke.py +++ b/tests/llm_translation/test_unit_test_bedrock_invoke.py @@ -1,5 +1,3 @@ -import os -import sys import traceback from dotenv import load_dotenv import litellm.types @@ -10,7 +8,6 @@ import json load_dotenv() import io -sys.path.insert(0, os.path.abspath("../..")) from unittest.mock import AsyncMock, Mock, patch diff --git a/tests/llm_translation/test_voyage_ai.py b/tests/llm_translation/test_voyage_ai.py index 30f2844fbfa..208e01110da 100644 --- a/tests/llm_translation/test_voyage_ai.py +++ b/tests/llm_translation/test_voyage_ai.py @@ -1,12 +1,8 @@ import json import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path from unittest.mock import MagicMock, patch diff --git a/tests/llm_translation/test_watsonx.py b/tests/llm_translation/test_watsonx.py index 5857394d0ff..0ccc2ba85f3 100644 --- a/tests/llm_translation/test_watsonx.py +++ b/tests/llm_translation/test_watsonx.py @@ -1,10 +1,5 @@ import json -import os -import sys -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm import completion, embedding from litellm.llms.custom_httpx.http_handler import HTTPHandler diff --git a/tests/llm_translation/test_xai.py b/tests/llm_translation/test_xai.py index f0945e6e165..7a121afc3fa 100644 --- a/tests/llm_translation/test_xai.py +++ b/tests/llm_translation/test_xai.py @@ -1,12 +1,8 @@ import json import os -import sys from datetime import datetime from unittest.mock import AsyncMock -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import httpx diff --git a/tests/load_tests/test_datadog_load_test.py b/tests/load_tests/test_datadog_load_test.py index f4328b71b1b..3dfc3fc6da4 100644 --- a/tests/load_tests/test_datadog_load_test.py +++ b/tests/load_tests/test_datadog_load_test.py @@ -1,7 +1,5 @@ -import sys import os -sys.path.insert(0, os.path.abspath("../..")) import asyncio import litellm diff --git a/tests/load_tests/test_langsmith_load_test.py b/tests/load_tests/test_langsmith_load_test.py index cf9fe526b74..84400d6974b 100644 --- a/tests/load_tests/test_langsmith_load_test.py +++ b/tests/load_tests/test_langsmith_load_test.py @@ -1,8 +1,6 @@ -import sys import os -sys.path.insert(0, os.path.abspath("../..")) import asyncio import litellm diff --git a/tests/load_tests/test_memory_usage.py b/tests/load_tests/test_memory_usage.py index 347dbf2bb44..c5b5134a3d7 100644 --- a/tests/load_tests/test_memory_usage.py +++ b/tests/load_tests/test_memory_usage.py @@ -9,9 +9,6 @@ from dotenv import load_dotenv load_dotenv() import io -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm.types @@ -21,7 +18,6 @@ from typing import Optional from unittest.mock import MagicMock, patch import pytest -import os import litellm from typing import Callable, Any diff --git a/tests/load_tests/test_otel_load_test.py b/tests/load_tests/test_otel_load_test.py index f5754c0c402..57dcc53a50b 100644 --- a/tests/load_tests/test_otel_load_test.py +++ b/tests/load_tests/test_otel_load_test.py @@ -1,8 +1,6 @@ -import sys import os -sys.path.insert(0, os.path.abspath("../..")) import asyncio import litellm diff --git a/tests/load_tests/test_vertex_embeddings_load_test.py b/tests/load_tests/test_vertex_embeddings_load_test.py index 9beee710553..c5b9a80ec6b 100644 --- a/tests/load_tests/test_vertex_embeddings_load_test.py +++ b/tests/load_tests/test_vertex_embeddings_load_test.py @@ -3,10 +3,8 @@ Load test on vertex AI embeddings to ensure vertex median response time is less """ -import sys import os -sys.path.insert(0, os.path.abspath("../..")) import asyncio import litellm diff --git a/tests/load_tests/test_vertex_load_tests.py b/tests/load_tests/test_vertex_load_tests.py index 9130873b970..93e1ed24f72 100644 --- a/tests/load_tests/test_vertex_load_tests.py +++ b/tests/load_tests/test_vertex_load_tests.py @@ -1,7 +1,5 @@ -import sys import os -sys.path.insert(0, os.path.abspath("../..")) import asyncio import litellm diff --git a/tests/local_testing/cache_unit_tests.py b/tests/local_testing/cache_unit_tests.py index 27eefb79fae..a1973d477b2 100644 --- a/tests/local_testing/cache_unit_tests.py +++ b/tests/local_testing/cache_unit_tests.py @@ -1,7 +1,5 @@ from abc import ABC, abstractmethod from litellm.caching import LiteLLMCacheType -import os -import sys import time import traceback from litellm._uuid import uuid @@ -10,9 +8,6 @@ from dotenv import load_dotenv load_dotenv() -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import asyncio import hashlib import random diff --git a/tests/local_testing/conftest.py b/tests/local_testing/conftest.py index d134a7439a8..4f142664827 100644 --- a/tests/local_testing/conftest.py +++ b/tests/local_testing/conftest.py @@ -13,13 +13,9 @@ import importlib import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm # ``litellm.model_cost`` is loaded at import time from the URL pinned to ``main`` @@ -238,7 +234,6 @@ def setup_and_teardown(): Module-scoped setup. Reloads litellm only in single-process mode (skipped under xdist to avoid cross-worker interference). """ - sys.path.insert(0, os.path.abspath("../..")) import litellm diff --git a/tests/local_testing/create_mock_standard_logging_payload.py b/tests/local_testing/create_mock_standard_logging_payload.py index 106328e95e2..096c8ff8c60 100644 --- a/tests/local_testing/create_mock_standard_logging_payload.py +++ b/tests/local_testing/create_mock_standard_logging_payload.py @@ -1,9 +1,6 @@ import io -import os -import sys -sys.path.insert(0, os.path.abspath("../..")) import asyncio import gzip diff --git a/tests/local_testing/test_acompletion_fallbacks.py b/tests/local_testing/test_acompletion_fallbacks.py index 7cf97eb9b5e..f9ee5a93c32 100644 --- a/tests/local_testing/test_acompletion_fallbacks.py +++ b/tests/local_testing/test_acompletion_fallbacks.py @@ -1,14 +1,10 @@ import asyncio import os -import sys import time import traceback import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import concurrent from dotenv import load_dotenv diff --git a/tests/local_testing/test_acooldowns_router.py b/tests/local_testing/test_acooldowns_router.py index 18dc26bda9a..18c58a5cfac 100644 --- a/tests/local_testing/test_acooldowns_router.py +++ b/tests/local_testing/test_acooldowns_router.py @@ -3,15 +3,11 @@ import asyncio import os -import sys import time import traceback import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import concurrent from dotenv import load_dotenv diff --git a/tests/local_testing/test_add_function_to_prompt.py b/tests/local_testing/test_add_function_to_prompt.py index 43ee3dd41af..507fd99ec59 100644 --- a/tests/local_testing/test_add_function_to_prompt.py +++ b/tests/local_testing/test_add_function_to_prompt.py @@ -4,9 +4,6 @@ import sys, os, pytest import traceback -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm diff --git a/tests/local_testing/test_aim_guardrails.py b/tests/local_testing/test_aim_guardrails.py index a6a4a0ad781..2a179ddcf32 100644 --- a/tests/local_testing/test_aim_guardrails.py +++ b/tests/local_testing/test_aim_guardrails.py @@ -1,8 +1,6 @@ import asyncio import contextlib import json -import os -import sys from unittest.mock import AsyncMock, patch, call import pytest @@ -17,9 +15,6 @@ from litellm.proxy.guardrails.guardrail_hooks.aim.aim import ( from litellm.proxy.proxy_server import StreamingCallbackError, UserAPIKeyAuth from litellm.types.utils import ModelResponseStream, ModelResponse -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm.proxy.guardrails.init_guardrails import init_guardrails_v2 diff --git a/tests/local_testing/test_alangfuse.py b/tests/local_testing/test_alangfuse.py index 7c2ec7e9f64..7b1f7f203e3 100644 --- a/tests/local_testing/test_alangfuse.py +++ b/tests/local_testing/test_alangfuse.py @@ -3,12 +3,10 @@ import copy import json import logging import os -import sys from typing import Any, Optional from unittest.mock import MagicMock, patch logging.basicConfig(level=logging.DEBUG) -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm import completion diff --git a/tests/local_testing/test_amazing_vertex_completion.py b/tests/local_testing/test_amazing_vertex_completion.py index a52b5975f6e..76ff23a9a1b 100644 --- a/tests/local_testing/test_amazing_vertex_completion.py +++ b/tests/local_testing/test_amazing_vertex_completion.py @@ -1,5 +1,4 @@ import os -import sys import traceback from dotenv import load_dotenv @@ -9,12 +8,8 @@ import io from test_streaming import streaming_format_tests -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import asyncio import json -import os import tempfile from unittest.mock import AsyncMock, MagicMock, patch, ANY from respx import MockRouter diff --git a/tests/local_testing/test_anthropic_prompt_caching.py b/tests/local_testing/test_anthropic_prompt_caching.py index 3105c0b9eeb..904b3ead92d 100644 --- a/tests/local_testing/test_anthropic_prompt_caching.py +++ b/tests/local_testing/test_anthropic_prompt_caching.py @@ -1,6 +1,5 @@ import json import os -import sys import traceback from dotenv import load_dotenv @@ -10,11 +9,7 @@ import io from test_streaming import streaming_format_tests -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path -import os from unittest.mock import AsyncMock, MagicMock, patch import pytest diff --git a/tests/local_testing/test_assistants.py b/tests/local_testing/test_assistants.py index 8dc4f9e48e1..af40e2f62b0 100644 --- a/tests/local_testing/test_assistants.py +++ b/tests/local_testing/test_assistants.py @@ -1,5 +1,3 @@ -import os -import sys import pytest from dotenv import load_dotenv @@ -7,7 +5,6 @@ from openai.types.beta.assistant import Assistant from openai.types.beta.assistant_deleted import AssistantDeleted load_dotenv() -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm import create_thread, get_thread diff --git a/tests/local_testing/test_async_fn.py b/tests/local_testing/test_async_fn.py index 40a757a4874..e2b3a62bd28 100644 --- a/tests/local_testing/test_async_fn.py +++ b/tests/local_testing/test_async_fn.py @@ -3,15 +3,10 @@ import asyncio import logging -import os -import sys import traceback import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm import acompletion, acreate, completion diff --git a/tests/local_testing/test_auth_utils.py b/tests/local_testing/test_auth_utils.py index e1444ed562e..0cc52716ce1 100644 --- a/tests/local_testing/test_auth_utils.py +++ b/tests/local_testing/test_auth_utils.py @@ -7,9 +7,6 @@ from dotenv import load_dotenv load_dotenv() -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import pytest import litellm from litellm.proxy.auth.auth_utils import ( diff --git a/tests/local_testing/test_azure_openai.py b/tests/local_testing/test_azure_openai.py index 2a2b1e7fc35..d6e08552697 100644 --- a/tests/local_testing/test_azure_openai.py +++ b/tests/local_testing/test_azure_openai.py @@ -1,6 +1,5 @@ import json import os -import sys import traceback from dotenv import load_dotenv @@ -8,11 +7,7 @@ from dotenv import load_dotenv load_dotenv() import io -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path -import os from datetime import datetime from unittest.mock import AsyncMock, MagicMock, patch diff --git a/tests/local_testing/test_basic_python_version.py b/tests/local_testing/test_basic_python_version.py index a710b5e0ff7..fb06ed6b69d 100644 --- a/tests/local_testing/test_basic_python_version.py +++ b/tests/local_testing/test_basic_python_version.py @@ -1,7 +1,6 @@ import asyncio import os import subprocess -import sys import time import traceback @@ -9,9 +8,6 @@ import pytest PROJECT_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")) -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path def _run_uv(*args: str, **kwargs) -> subprocess.CompletedProcess: diff --git a/tests/local_testing/test_batch_completions.py b/tests/local_testing/test_batch_completions.py index 95bfe5e6e2b..d3296988e8c 100644 --- a/tests/local_testing/test_batch_completions.py +++ b/tests/local_testing/test_batch_completions.py @@ -5,9 +5,6 @@ import sys, os import traceback import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path from openai import APITimeoutError as Timeout import litellm diff --git a/tests/local_testing/test_blocked_user_list.py b/tests/local_testing/test_blocked_user_list.py index 9b29d3fcfa5..9bbe3fedf46 100644 --- a/tests/local_testing/test_blocked_user_list.py +++ b/tests/local_testing/test_blocked_user_list.py @@ -5,7 +5,6 @@ import asyncio import os import random -import sys import time import traceback from datetime import datetime @@ -15,9 +14,6 @@ from fastapi import Request load_dotenv() -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import logging import pytest diff --git a/tests/local_testing/test_braintrust.py b/tests/local_testing/test_braintrust.py index 18c210b6d33..4c1a2d990b1 100644 --- a/tests/local_testing/test_braintrust.py +++ b/tests/local_testing/test_braintrust.py @@ -2,9 +2,7 @@ ## This tests the braintrust integration import asyncio -import os import random -import sys import time import traceback from datetime import datetime @@ -14,9 +12,6 @@ from fastapi import Request load_dotenv() -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import logging from unittest.mock import AsyncMock, MagicMock, patch diff --git a/tests/local_testing/test_caching.py b/tests/local_testing/test_caching.py index 90be551ff46..f9deb9c100b 100644 --- a/tests/local_testing/test_caching.py +++ b/tests/local_testing/test_caching.py @@ -1,5 +1,4 @@ import os -import sys import time import traceback from litellm._uuid import uuid @@ -9,9 +8,6 @@ from dotenv import load_dotenv load_dotenv() import json -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import asyncio import hashlib import random diff --git a/tests/local_testing/test_caching_handler.py b/tests/local_testing/test_caching_handler.py index b26334e9ee0..f17a058b3fe 100644 --- a/tests/local_testing/test_caching_handler.py +++ b/tests/local_testing/test_caching_handler.py @@ -1,5 +1,3 @@ -import os -import sys import time import traceback from litellm._uuid import uuid @@ -7,9 +5,6 @@ from litellm._uuid import uuid from dotenv import load_dotenv load_dotenv() -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import asyncio import hashlib import random diff --git a/tests/local_testing/test_caching_ssl.py b/tests/local_testing/test_caching_ssl.py index 863f227aef1..a8fe45b2d7b 100644 --- a/tests/local_testing/test_caching_ssl.py +++ b/tests/local_testing/test_caching_ssl.py @@ -8,9 +8,6 @@ from dotenv import load_dotenv load_dotenv() -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import pytest import litellm from litellm import embedding, completion, Router diff --git a/tests/local_testing/test_completion.py b/tests/local_testing/test_completion.py index 3b890273ce7..ef8d6c55148 100644 --- a/tests/local_testing/test_completion.py +++ b/tests/local_testing/test_completion.py @@ -1,6 +1,5 @@ import json import os -import sys import traceback from dotenv import load_dotenv @@ -8,12 +7,8 @@ from dotenv import load_dotenv load_dotenv() import io -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path -import os from unittest.mock import AsyncMock, MagicMock, patch import pytest diff --git a/tests/local_testing/test_completion_cost.py b/tests/local_testing/test_completion_cost.py index 7dfcb55e29a..f47b40f2ef1 100644 --- a/tests/local_testing/test_completion_cost.py +++ b/tests/local_testing/test_completion_cost.py @@ -1,14 +1,9 @@ import os -import sys import traceback import litellm.cost_calculator -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import asyncio -import os import time from typing import Optional from unittest.mock import AsyncMock, MagicMock, patch diff --git a/tests/local_testing/test_completion_with_retries.py b/tests/local_testing/test_completion_with_retries.py index c9b519b2af8..ede07a15225 100644 --- a/tests/local_testing/test_completion_with_retries.py +++ b/tests/local_testing/test_completion_with_retries.py @@ -4,9 +4,6 @@ from dotenv import load_dotenv load_dotenv() -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import pytest import openai import litellm diff --git a/tests/local_testing/test_config.py b/tests/local_testing/test_config.py index 2a5dc3376ee..6c3c0a093a7 100644 --- a/tests/local_testing/test_config.py +++ b/tests/local_testing/test_config.py @@ -3,7 +3,6 @@ import os -import sys import traceback from dotenv import load_dotenv @@ -11,9 +10,6 @@ from dotenv import load_dotenv load_dotenv() import io -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path from typing import Literal import pytest diff --git a/tests/local_testing/test_cost_calc.py b/tests/local_testing/test_cost_calc.py index 233b67a6072..0b2e8e39701 100644 --- a/tests/local_testing/test_cost_calc.py +++ b/tests/local_testing/test_cost_calc.py @@ -1,5 +1,3 @@ -import os -import sys import traceback from dotenv import load_dotenv @@ -7,9 +5,6 @@ from dotenv import load_dotenv load_dotenv() import io -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system-path from typing import Literal import pytest diff --git a/tests/local_testing/test_custom_callback_input.py b/tests/local_testing/test_custom_callback_input.py index cedb5ea1a97..745bfe94e1a 100644 --- a/tests/local_testing/test_custom_callback_input.py +++ b/tests/local_testing/test_custom_callback_input.py @@ -3,7 +3,6 @@ import asyncio import inspect import os -import sys import traceback from litellm._uuid import uuid from datetime import datetime @@ -11,7 +10,6 @@ from datetime import datetime import pytest from pydantic import BaseModel -sys.path.insert(0, os.path.abspath("../..")) from typing import List, Literal, Optional, Union from unittest.mock import AsyncMock, MagicMock, patch diff --git a/tests/local_testing/test_custom_llm.py b/tests/local_testing/test_custom_llm.py index 64a6c8b2587..160d771004c 100644 --- a/tests/local_testing/test_custom_llm.py +++ b/tests/local_testing/test_custom_llm.py @@ -3,18 +3,12 @@ import asyncio -import os -import sys import time import traceback import openai import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path -import os from collections import defaultdict from concurrent.futures import ThreadPoolExecutor from typing import ( diff --git a/tests/local_testing/test_custom_logger.py b/tests/local_testing/test_custom_logger.py index 02a9eaaa9e6..1b627d56717 100644 --- a/tests/local_testing/test_custom_logger.py +++ b/tests/local_testing/test_custom_logger.py @@ -2,13 +2,11 @@ import asyncio import inspect import os -import sys import time import traceback import pytest -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm import completion, embedding diff --git a/tests/local_testing/test_dual_cache.py b/tests/local_testing/test_dual_cache.py index cdfa8146420..e60fa5f3746 100644 --- a/tests/local_testing/test_dual_cache.py +++ b/tests/local_testing/test_dual_cache.py @@ -1,5 +1,4 @@ import os -import sys import time import traceback from litellm._uuid import uuid @@ -8,9 +7,6 @@ from dotenv import load_dotenv load_dotenv() -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import asyncio import hashlib import random diff --git a/tests/local_testing/test_dynamic_rate_limit_handler.py b/tests/local_testing/test_dynamic_rate_limit_handler.py index fe3c8ca260e..7c178113e35 100644 --- a/tests/local_testing/test_dynamic_rate_limit_handler.py +++ b/tests/local_testing/test_dynamic_rate_limit_handler.py @@ -1,9 +1,7 @@ # What is this? ## Unit tests for 'dynamic_rate_limiter.py` import asyncio -import os import random -import sys import time import traceback from litellm._uuid import uuid @@ -14,9 +12,6 @@ from dotenv import load_dotenv load_dotenv() -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import pytest import litellm diff --git a/tests/local_testing/test_embedding.py b/tests/local_testing/test_embedding.py index fbbe83ada30..aed2849f056 100644 --- a/tests/local_testing/test_embedding.py +++ b/tests/local_testing/test_embedding.py @@ -1,7 +1,6 @@ import json import os import re -import sys import traceback import openai @@ -10,9 +9,6 @@ from dotenv import load_dotenv load_dotenv() -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path from unittest.mock import AsyncMock, MagicMock, patch import litellm diff --git a/tests/local_testing/test_exceptions.py b/tests/local_testing/test_exceptions.py index cf89e7bea1d..8370046446d 100644 --- a/tests/local_testing/test_exceptions.py +++ b/tests/local_testing/test_exceptions.py @@ -1,17 +1,14 @@ import asyncio import os import subprocess -import sys import traceback from typing import Any -from openai import AuthenticationError, BadRequestError, OpenAIError, RateLimitError +import httpx +from openai import AsyncOpenAI, AuthenticationError, BadRequestError, OpenAIError, RateLimitError from litellm.llms.custom_httpx.http_handler import AsyncHTTPHandler, HTTPHandler -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path from concurrent.futures import ThreadPoolExecutor from unittest.mock import MagicMock, patch @@ -63,23 +60,38 @@ async def test_content_policy_exception_azure(): @pytest.mark.asyncio async def test_content_policy_exception_openai(): - # this is ony a test - we needed some way to invoke the exception :( - litellm.set_verbose = True + def reject_as_safety_system(request: httpx.Request) -> httpx.Response: + return httpx.Response( + status_code=400, + json={ + "error": { + "message": "Your request was rejected as a result of our safety system.", + "type": "invalid_request_error", + "param": None, + "code": "content_policy_violation", + } + }, + request=request, + ) - async def stream_response(): + async def stream_response(rejecting_client: AsyncOpenAI): response = await litellm.acompletion( model="gpt-3.5-turbo", stream=True, - messages=[ - {"role": "user", "content": "Gimme the lyrics to Don't Stop Me Now"} - ], + messages=[{"role": "user", "content": "Gimme the lyrics to Don't Stop Me Now"}], + client=rejecting_client, ) async for chunk in response: print(chunk) - with pytest.raises(litellm.ContentPolicyViolationError) as exc_info: - await stream_response() + async with AsyncOpenAI( + api_key="sk-test", + http_client=httpx.AsyncClient(transport=httpx.MockTransport(reject_as_safety_system)), + ) as rejecting_client: + with pytest.raises(litellm.ContentPolicyViolationError) as exc_info: + await stream_response(rejecting_client) assert exc_info.value.llm_provider == "openai" + assert exc_info.value.status_code == 400 # Test 1: Context Window Errors @@ -871,7 +883,7 @@ def test_anthropic_tool_calling_exception(): from typing import Optional, Union -from openai import AsyncOpenAI, OpenAI +from openai import OpenAI def _pre_call_utils( diff --git a/tests/local_testing/test_function_call_parsing.py b/tests/local_testing/test_function_call_parsing.py index 57027c670bb..c98f170a98f 100644 --- a/tests/local_testing/test_function_call_parsing.py +++ b/tests/local_testing/test_function_call_parsing.py @@ -1,7 +1,5 @@ # What is this? ## Test to make sure function call response always works with json.loads() -> no extra parsing required. Relevant issue - https://github.com/BerriAI/litellm/issues/2654 -import os -import sys import traceback from dotenv import load_dotenv @@ -9,9 +7,6 @@ from dotenv import load_dotenv load_dotenv() import io -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import json import warnings from typing import List diff --git a/tests/local_testing/test_function_calling.py b/tests/local_testing/test_function_calling.py index b5f72264549..5752f29daef 100644 --- a/tests/local_testing/test_function_calling.py +++ b/tests/local_testing/test_function_calling.py @@ -1,5 +1,3 @@ -import os -import sys import traceback from dotenv import load_dotenv @@ -7,9 +5,6 @@ from dotenv import load_dotenv load_dotenv() import io -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import pytest from unittest.mock import patch, MagicMock, AsyncMock import litellm diff --git a/tests/local_testing/test_function_setup.py b/tests/local_testing/test_function_setup.py index 92f49589ca2..757aaefc8c6 100644 --- a/tests/local_testing/test_function_setup.py +++ b/tests/local_testing/test_function_setup.py @@ -7,9 +7,6 @@ from dotenv import load_dotenv load_dotenv() import io -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import pytest, uuid from litellm.utils import function_setup, Rules from litellm.litellm_core_utils.prompt_templates.factory import ( diff --git a/tests/local_testing/test_gcs_bucket.py b/tests/local_testing/test_gcs_bucket.py index ffd466aa809..437a8b8f13b 100644 --- a/tests/local_testing/test_gcs_bucket.py +++ b/tests/local_testing/test_gcs_bucket.py @@ -1,8 +1,6 @@ import io import os -import sys -sys.path.insert(0, os.path.abspath("../..")) import asyncio import json diff --git a/tests/local_testing/test_get_llm_provider.py b/tests/local_testing/test_get_llm_provider.py index 0e667b82a66..cc6209f2bf9 100644 --- a/tests/local_testing/test_get_llm_provider.py +++ b/tests/local_testing/test_get_llm_provider.py @@ -1,5 +1,4 @@ import os -import sys import traceback from dotenv import load_dotenv @@ -9,9 +8,6 @@ import io from unittest.mock import patch -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import pytest import litellm from litellm.types.router import LiteLLM_Params diff --git a/tests/local_testing/test_get_model_file.py b/tests/local_testing/test_get_model_file.py index 17bd2d7ceff..3742dca9dda 100644 --- a/tests/local_testing/test_get_model_file.py +++ b/tests/local_testing/test_get_model_file.py @@ -2,9 +2,6 @@ import os, sys, traceback import importlib.resources import json -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm import pytest diff --git a/tests/local_testing/test_get_model_info.py b/tests/local_testing/test_get_model_info.py index cef05050ac9..2de83778f1c 100644 --- a/tests/local_testing/test_get_model_info.py +++ b/tests/local_testing/test_get_model_info.py @@ -1,16 +1,12 @@ # What is this? ## Unit testing for the 'get_model_info()' function import os -import sys import traceback import json from typing import List, Dict, Any -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system-path import pytest import litellm diff --git a/tests/local_testing/test_get_optional_params_embeddings.py b/tests/local_testing/test_get_optional_params_embeddings.py index ddf9e877477..60ccfbfaebe 100644 --- a/tests/local_testing/test_get_optional_params_embeddings.py +++ b/tests/local_testing/test_get_optional_params_embeddings.py @@ -7,9 +7,6 @@ from dotenv import load_dotenv load_dotenv() import io -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import pytest import litellm from litellm import embedding diff --git a/tests/local_testing/test_google_ai_studio_gemini.py b/tests/local_testing/test_google_ai_studio_gemini.py index 5012717d383..43b64ded1ab 100644 --- a/tests/local_testing/test_google_ai_studio_gemini.py +++ b/tests/local_testing/test_google_ai_studio_gemini.py @@ -1,8 +1,5 @@ import os, sys, traceback -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from dotenv import load_dotenv diff --git a/tests/local_testing/test_guardrails_ai.py b/tests/local_testing/test_guardrails_ai.py index 004ffa0b9e3..bc2db026ecc 100644 --- a/tests/local_testing/test_guardrails_ai.py +++ b/tests/local_testing/test_guardrails_ai.py @@ -1,10 +1,5 @@ -import os -import sys import traceback -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm.proxy.guardrails.init_guardrails import init_guardrails_v2 diff --git a/tests/local_testing/test_helicone_integration.py b/tests/local_testing/test_helicone_integration.py index 9bfa29551e3..f34ad33aa9b 100644 --- a/tests/local_testing/test_helicone_integration.py +++ b/tests/local_testing/test_helicone_integration.py @@ -2,13 +2,11 @@ import asyncio import copy import logging import os -import sys import time from typing import Any from unittest.mock import MagicMock, patch logging.basicConfig(level=logging.DEBUG) -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm import completion diff --git a/tests/local_testing/test_http_parsing_utils.py b/tests/local_testing/test_http_parsing_utils.py index 813460c7e27..db282d6d4be 100644 --- a/tests/local_testing/test_http_parsing_utils.py +++ b/tests/local_testing/test_http_parsing_utils.py @@ -3,12 +3,7 @@ from fastapi import Request from fastapi.testclient import TestClient from starlette.datastructures import Headers from starlette.requests import HTTPConnection -import os -import sys -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system-path from litellm.proxy.common_utils.http_parsing_utils import _read_request_body from litellm.proxy._types import ProxyException diff --git a/tests/local_testing/test_least_busy_routing.py b/tests/local_testing/test_least_busy_routing.py index 0a3b5490131..18ab8bf779d 100644 --- a/tests/local_testing/test_least_busy_routing.py +++ b/tests/local_testing/test_least_busy_routing.py @@ -2,9 +2,7 @@ # This tests the router's ability to identify the least busy deployment import asyncio -import os import random -import sys import time import traceback @@ -12,9 +10,6 @@ from dotenv import load_dotenv load_dotenv() -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import pytest import litellm diff --git a/tests/local_testing/test_llm_guard.py b/tests/local_testing/test_llm_guard.py index 60fe9c0e020..9e70d48dbda 100644 --- a/tests/local_testing/test_llm_guard.py +++ b/tests/local_testing/test_llm_guard.py @@ -10,9 +10,6 @@ from dotenv import load_dotenv load_dotenv() -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import pytest from fastapi import HTTPException diff --git a/tests/local_testing/test_longer_context_fallback.py b/tests/local_testing/test_longer_context_fallback.py index 07e9e8cad74..adb087079c5 100644 --- a/tests/local_testing/test_longer_context_fallback.py +++ b/tests/local_testing/test_longer_context_fallback.py @@ -5,9 +5,6 @@ import sys, os import traceback import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm import longer_context_model_fallback_dict diff --git a/tests/local_testing/test_lowest_cost_routing.py b/tests/local_testing/test_lowest_cost_routing.py index 6ed1731572a..5bf3a3ee98b 100644 --- a/tests/local_testing/test_lowest_cost_routing.py +++ b/tests/local_testing/test_lowest_cost_routing.py @@ -9,9 +9,6 @@ from dotenv import load_dotenv load_dotenv() import copy -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import pytest from litellm import Router from litellm.router_strategy.lowest_cost import LowestCostLoggingHandler diff --git a/tests/local_testing/test_lowest_latency_routing.py b/tests/local_testing/test_lowest_latency_routing.py index 0a202e0dfb9..598b1dbcaf9 100644 --- a/tests/local_testing/test_lowest_latency_routing.py +++ b/tests/local_testing/test_lowest_latency_routing.py @@ -2,7 +2,6 @@ # This tests the router's ability to pick deployment with lowest latency import asyncio -import os import random import sys import time @@ -14,9 +13,6 @@ from dotenv import load_dotenv load_dotenv() import copy -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import pytest import litellm diff --git a/tests/local_testing/test_lunary.py b/tests/local_testing/test_lunary.py index 0dbae1b817f..a2e137ed355 100644 --- a/tests/local_testing/test_lunary.py +++ b/tests/local_testing/test_lunary.py @@ -1,8 +1,5 @@ import io -import os -import sys -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm import completion diff --git a/tests/local_testing/test_mock_request.py b/tests/local_testing/test_mock_request.py index c9cd14633ba..9cbcafb003b 100644 --- a/tests/local_testing/test_mock_request.py +++ b/tests/local_testing/test_mock_request.py @@ -2,14 +2,10 @@ # This tests mock request calls to litellm import os -import sys import traceback import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm import time diff --git a/tests/local_testing/test_model_alias_map.py b/tests/local_testing/test_model_alias_map.py index 9ef0448e7c6..675f2345747 100644 --- a/tests/local_testing/test_model_alias_map.py +++ b/tests/local_testing/test_model_alias_map.py @@ -1,13 +1,8 @@ #### What this tests #### # This tests the model alias mapping - if user passes in an alias, and has set an alias, set it to the actual value -import os -import sys import traceback -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import pytest import litellm diff --git a/tests/local_testing/test_multiple_deployments.py b/tests/local_testing/test_multiple_deployments.py index 72bfd5012c1..1c39bd56a95 100644 --- a/tests/local_testing/test_multiple_deployments.py +++ b/tests/local_testing/test_multiple_deployments.py @@ -4,9 +4,6 @@ import sys, os import traceback -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import pytest import litellm from litellm import completion diff --git a/tests/local_testing/test_ollama.py b/tests/local_testing/test_ollama.py index 7ca8e806529..ad5d7d86501 100644 --- a/tests/local_testing/test_ollama.py +++ b/tests/local_testing/test_ollama.py @@ -1,7 +1,5 @@ import asyncio import json -import os -import sys import traceback from dotenv import load_dotenv @@ -9,9 +7,6 @@ from dotenv import load_dotenv load_dotenv() import io -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path from unittest import mock import pytest diff --git a/tests/local_testing/test_openai_moderations_hook.py b/tests/local_testing/test_openai_moderations_hook.py index 944ac047e55..530ab714eae 100644 --- a/tests/local_testing/test_openai_moderations_hook.py +++ b/tests/local_testing/test_openai_moderations_hook.py @@ -10,9 +10,6 @@ from dotenv import load_dotenv load_dotenv() -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import pytest import litellm from litellm.proxy.enterprise.enterprise_hooks.openai_moderation import ( @@ -62,7 +59,9 @@ async def test_openai_moderation_error_raising(monkeypatch): llm_router.amoderation = mock_amoderation - setattr(litellm.proxy.proxy_server, "llm_router", llm_router) + import litellm.proxy.proxy_server as proxy_server + + monkeypatch.setattr(proxy_server, "llm_router", llm_router) with pytest.raises(Exception, match="Violated content safety policy") as exc_info: await openai_mod.async_moderation_hook( diff --git a/tests/local_testing/test_opik.py b/tests/local_testing/test_opik.py index 4047a5fefe3..8be4b796360 100644 --- a/tests/local_testing/test_opik.py +++ b/tests/local_testing/test_opik.py @@ -1,8 +1,6 @@ import io import os -import sys -sys.path.insert(0, os.path.abspath("../..")) import asyncio import logging diff --git a/tests/local_testing/test_pass_through_endpoints.py b/tests/local_testing/test_pass_through_endpoints.py index 793a60efc3f..618354ca31e 100644 --- a/tests/local_testing/test_pass_through_endpoints.py +++ b/tests/local_testing/test_pass_through_endpoints.py @@ -1,5 +1,4 @@ import os -import sys from litellm._uuid import uuid from functools import partial from typing import Optional @@ -9,9 +8,6 @@ import pytest from fastapi import FastAPI from fastapi.testclient import TestClient -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds-the parent directory to the system path import asyncio from unittest.mock import Mock diff --git a/tests/local_testing/test_prometheus_service.py b/tests/local_testing/test_prometheus_service.py index b97fcd096b3..c8acca83d93 100644 --- a/tests/local_testing/test_prometheus_service.py +++ b/tests/local_testing/test_prometheus_service.py @@ -2,11 +2,9 @@ ## Unit Tests for prometheus service monitoring import json -import sys import os import io, asyncio -sys.path.insert(0, os.path.abspath("../..")) import pytest from litellm import acompletion, Cache from litellm._service_logger import ServiceLogging diff --git a/tests/local_testing/test_prompt_caching.py b/tests/local_testing/test_prompt_caching.py index 58b8f560045..f6b3fb89e9e 100644 --- a/tests/local_testing/test_prompt_caching.py +++ b/tests/local_testing/test_prompt_caching.py @@ -1,10 +1,7 @@ """Asserts that prompt caching information is correctly returned for Anthropic, OpenAI, and Deepseek""" import io -import os -import sys -sys.path.insert(0, os.path.abspath("../..")) import litellm import pytest diff --git a/tests/local_testing/test_prompt_injection_detection.py b/tests/local_testing/test_prompt_injection_detection.py index 9f5137630ea..fa35dc5b060 100644 --- a/tests/local_testing/test_prompt_injection_detection.py +++ b/tests/local_testing/test_prompt_injection_detection.py @@ -8,9 +8,6 @@ from dotenv import load_dotenv load_dotenv() -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import pytest import litellm from litellm.proxy.hooks.prompt_injection_detection import ( diff --git a/tests/local_testing/test_provider_specific_config.py b/tests/local_testing/test_provider_specific_config.py index 5587087e40b..a6bad688201 100644 --- a/tests/local_testing/test_provider_specific_config.py +++ b/tests/local_testing/test_provider_specific_config.py @@ -3,14 +3,10 @@ # There are 2 types of tests - changing config dynamically or by setting class variables import os -import sys import traceback import json import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path from unittest.mock import AsyncMock, MagicMock, patch import litellm diff --git a/tests/local_testing/test_pydantic.py b/tests/local_testing/test_pydantic.py index 436b9d3dd48..155b0345186 100644 --- a/tests/local_testing/test_pydantic.py +++ b/tests/local_testing/test_pydantic.py @@ -1,5 +1,3 @@ -import os -import sys import traceback from dotenv import load_dotenv @@ -7,12 +5,8 @@ from dotenv import load_dotenv load_dotenv() import io -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import asyncio import json -import os import tempfile from unittest.mock import MagicMock, patch diff --git a/tests/local_testing/test_redis_batch_optimizations.py b/tests/local_testing/test_redis_batch_optimizations.py index 4997157bac8..d49939cff1a 100644 --- a/tests/local_testing/test_redis_batch_optimizations.py +++ b/tests/local_testing/test_redis_batch_optimizations.py @@ -8,7 +8,6 @@ Verifies: """ import os -import sys import time from unittest.mock import AsyncMock, patch @@ -16,7 +15,6 @@ import pytest from dotenv import load_dotenv load_dotenv() -sys.path.insert(0, os.path.abspath("../..")) import uuid from litellm.caching.dual_cache import DualCache diff --git a/tests/local_testing/test_register_model.py b/tests/local_testing/test_register_model.py index 44fb440bbbd..eddd697974c 100644 --- a/tests/local_testing/test_register_model.py +++ b/tests/local_testing/test_register_model.py @@ -8,9 +8,6 @@ from pathlib import Path import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm diff --git a/tests/local_testing/test_router.py b/tests/local_testing/test_router.py index f648b31901a..370c43f8f44 100644 --- a/tests/local_testing/test_router.py +++ b/tests/local_testing/test_router.py @@ -3,7 +3,6 @@ import asyncio import os -import sys import time import traceback @@ -13,10 +12,6 @@ import pytest import litellm.types import litellm.types.router -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path -import os from collections import defaultdict from concurrent.futures import ThreadPoolExecutor from unittest.mock import AsyncMock, MagicMock, patch diff --git a/tests/local_testing/test_router_batch_completion.py b/tests/local_testing/test_router_batch_completion.py index bb9e1851c61..6fd89065c1d 100644 --- a/tests/local_testing/test_router_batch_completion.py +++ b/tests/local_testing/test_router_batch_completion.py @@ -2,18 +2,12 @@ # This tests litellm router with batch completion import asyncio -import os -import sys import time import traceback import openai import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path -import os from collections import defaultdict from concurrent.futures import ThreadPoolExecutor diff --git a/tests/local_testing/test_router_budget_limiter.py b/tests/local_testing/test_router_budget_limiter.py index 3bdb3116670..bda1f648076 100644 --- a/tests/local_testing/test_router_budget_limiter.py +++ b/tests/local_testing/test_router_budget_limiter.py @@ -6,9 +6,6 @@ from dotenv import load_dotenv load_dotenv() import copy -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system-path import pytest from litellm import Router from litellm.router_strategy.budget_limiter import RouterBudgetLimiting diff --git a/tests/local_testing/test_router_caching.py b/tests/local_testing/test_router_caching.py index cb223b661b4..9675a1299d1 100644 --- a/tests/local_testing/test_router_caching.py +++ b/tests/local_testing/test_router_caching.py @@ -2,16 +2,12 @@ # This tests caching on the router import asyncio import os -import sys import time import traceback from unittest.mock import patch from typing import Union import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm import Router from litellm.caching import RedisCache, RedisClusterCache diff --git a/tests/local_testing/test_router_client_init.py b/tests/local_testing/test_router_client_init.py index f2b82b651dd..f27b3848beb 100644 --- a/tests/local_testing/test_router_client_init.py +++ b/tests/local_testing/test_router_client_init.py @@ -6,7 +6,6 @@ import os #### What this tests #### # This tests caching on the router -import sys import time import traceback from typing import Dict @@ -15,9 +14,6 @@ from unittest.mock import MagicMock, PropertyMock, patch import pytest from openai.lib.azure import OpenAIError -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm import APIConnectionError, Router from unittest.mock import ANY diff --git a/tests/local_testing/test_router_cooldown_handlers.py b/tests/local_testing/test_router_cooldown_handlers.py index 55510df5b9e..e1e3df1e4a5 100644 --- a/tests/local_testing/test_router_cooldown_handlers.py +++ b/tests/local_testing/test_router_cooldown_handlers.py @@ -4,15 +4,11 @@ import asyncio import os import random -import sys import time import traceback import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system-path from unittest.mock import AsyncMock, MagicMock, patch diff --git a/tests/local_testing/test_router_custom_routing.py b/tests/local_testing/test_router_custom_routing.py index 3ebd79a7b2a..bd624f7a19f 100644 --- a/tests/local_testing/test_router_custom_routing.py +++ b/tests/local_testing/test_router_custom_routing.py @@ -1,15 +1,10 @@ import asyncio -import os -import sys import time from dotenv import load_dotenv load_dotenv() -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path from typing import Dict, List, Optional, Union import pytest diff --git a/tests/local_testing/test_router_debug_logs.py b/tests/local_testing/test_router_debug_logs.py index 04e8dc6c77c..0fce5c824c7 100644 --- a/tests/local_testing/test_router_debug_logs.py +++ b/tests/local_testing/test_router_debug_logs.py @@ -1,14 +1,10 @@ import asyncio import os -import sys import time import traceback import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import logging diff --git a/tests/local_testing/test_router_fallback_handlers.py b/tests/local_testing/test_router_fallback_handlers.py index 0bd455463b7..65994f0a4cf 100644 --- a/tests/local_testing/test_router_fallback_handlers.py +++ b/tests/local_testing/test_router_fallback_handlers.py @@ -1,14 +1,10 @@ import asyncio import os -import sys import time import traceback import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path from unittest.mock import AsyncMock, MagicMock, patch import litellm diff --git a/tests/local_testing/test_router_fallbacks.py b/tests/local_testing/test_router_fallbacks.py index 1cafd2c709d..82b832f89fd 100644 --- a/tests/local_testing/test_router_fallbacks.py +++ b/tests/local_testing/test_router_fallbacks.py @@ -3,15 +3,11 @@ import asyncio import os -import sys import time import traceback import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path from unittest.mock import AsyncMock, MagicMock, patch import litellm diff --git a/tests/local_testing/test_router_get_deployments.py b/tests/local_testing/test_router_get_deployments.py index 78503b36c74..a4d4359a3e9 100644 --- a/tests/local_testing/test_router_get_deployments.py +++ b/tests/local_testing/test_router_get_deployments.py @@ -3,15 +3,11 @@ # These are fast Tests, and make no API calls import asyncio import os -import sys import time import traceback import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path from collections import defaultdict from concurrent.futures import ThreadPoolExecutor diff --git a/tests/local_testing/test_router_max_parallel_requests.py b/tests/local_testing/test_router_max_parallel_requests.py index 7bb40dd7a2f..65602c968bc 100644 --- a/tests/local_testing/test_router_max_parallel_requests.py +++ b/tests/local_testing/test_router_max_parallel_requests.py @@ -2,15 +2,12 @@ ## Unit tests for the max_parallel_requests feature on Router import asyncio import inspect -import os -import sys import time import traceback from datetime import datetime import pytest -sys.path.insert(0, os.path.abspath("../..")) from typing import Optional import litellm diff --git a/tests/local_testing/test_router_pattern_matching.py b/tests/local_testing/test_router_pattern_matching.py index d02582a2a99..6ffc5316f2e 100644 --- a/tests/local_testing/test_router_pattern_matching.py +++ b/tests/local_testing/test_router_pattern_matching.py @@ -9,9 +9,6 @@ import json import traceback, asyncio import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm import Router from litellm.router import Deployment, LiteLLM_Params diff --git a/tests/local_testing/test_router_retries.py b/tests/local_testing/test_router_retries.py index 7d1ad012745..d5374a3da0f 100644 --- a/tests/local_testing/test_router_retries.py +++ b/tests/local_testing/test_router_retries.py @@ -3,15 +3,11 @@ import asyncio import os -import sys import time import traceback import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import httpx import openai diff --git a/tests/local_testing/test_router_timeout.py b/tests/local_testing/test_router_timeout.py index 9971e540024..9992fa03bcd 100644 --- a/tests/local_testing/test_router_timeout.py +++ b/tests/local_testing/test_router_timeout.py @@ -3,18 +3,13 @@ import asyncio import os -import sys import time import traceback import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path from unittest.mock import patch, MagicMock, AsyncMock -import os from dotenv import load_dotenv diff --git a/tests/local_testing/test_router_utils.py b/tests/local_testing/test_router_utils.py index f2fd2fdf559..45fe42f4cd3 100644 --- a/tests/local_testing/test_router_utils.py +++ b/tests/local_testing/test_router_utils.py @@ -5,9 +5,6 @@ import sys, os, time import traceback, asyncio import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm import Router from litellm.router import Deployment, LiteLLM_Params diff --git a/tests/local_testing/test_rules.py b/tests/local_testing/test_rules.py index 7ffab789d64..2e9472c8678 100644 --- a/tests/local_testing/test_rules.py +++ b/tests/local_testing/test_rules.py @@ -1,17 +1,12 @@ #### What this tests #### # This tests setting rules before / after making llm api calls import asyncio -import os import re -import sys import time import traceback import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm import acompletion, completion diff --git a/tests/local_testing/test_sagemaker.py b/tests/local_testing/test_sagemaker.py index bf17d9dce21..a01c8c217c6 100644 --- a/tests/local_testing/test_sagemaker.py +++ b/tests/local_testing/test_sagemaker.py @@ -1,6 +1,4 @@ import json -import os -import sys import traceback from dotenv import load_dotenv @@ -10,11 +8,7 @@ import io import litellm from test_streaming import streaming_format_tests -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path -import os from unittest.mock import AsyncMock, MagicMock, patch import pytest diff --git a/tests/local_testing/test_scheduler.py b/tests/local_testing/test_scheduler.py index 178983f02d6..027a400dfc9 100644 --- a/tests/local_testing/test_scheduler.py +++ b/tests/local_testing/test_scheduler.py @@ -6,9 +6,6 @@ import traceback, asyncio import pytest from typing import List -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path from litellm import Router from litellm.scheduler import FlowItem, Scheduler, SchedulerCacheKeys from litellm import ModelResponse diff --git a/tests/local_testing/test_secret_detect_hook.py b/tests/local_testing/test_secret_detect_hook.py index 8a93b72dce2..0ee0f596177 100644 --- a/tests/local_testing/test_secret_detect_hook.py +++ b/tests/local_testing/test_secret_detect_hook.py @@ -2,12 +2,10 @@ ## This tests the llm guard integration import asyncio -import os import random # What is this? ## Unit test for presidio pii masking -import sys import time import traceback from datetime import datetime @@ -16,9 +14,6 @@ from dotenv import load_dotenv load_dotenv() -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import pytest from fastapi import Request, Response from starlette.datastructures import URL diff --git a/tests/local_testing/test_spend_calculate_endpoint.py b/tests/local_testing/test_spend_calculate_endpoint.py index 8f7434e40b9..3bedab794e2 100644 --- a/tests/local_testing/test_spend_calculate_endpoint.py +++ b/tests/local_testing/test_spend_calculate_endpoint.py @@ -1,5 +1,3 @@ -import os -import sys import pytest from dotenv import load_dotenv @@ -13,9 +11,6 @@ from litellm.router import Router # this file is to test litellm/proxy -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path @pytest.mark.asyncio diff --git a/tests/local_testing/test_stream_chunk_builder.py b/tests/local_testing/test_stream_chunk_builder.py index 9dab6e60c35..6d62dd52b89 100644 --- a/tests/local_testing/test_stream_chunk_builder.py +++ b/tests/local_testing/test_stream_chunk_builder.py @@ -1,6 +1,5 @@ import asyncio import os -import sys import time import traceback @@ -15,13 +14,9 @@ def check_non_streaming_response(response): assert isinstance( response.choices[0].message.audio, ChatCompletionAudioResponse ), "Invalid audio response type" - assert len(completion.choices[0].message.audio.data) > 0, "Audio data is empty" + assert len(response.choices[0].message.audio.data) > 0, "Audio data is empty" -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path -import os import dotenv from openai import OpenAI diff --git a/tests/local_testing/test_streaming.py b/tests/local_testing/test_streaming.py index ba1f4e7d51c..07d693af447 100644 --- a/tests/local_testing/test_streaming.py +++ b/tests/local_testing/test_streaming.py @@ -4,7 +4,6 @@ import asyncio import json import os -import sys import time import traceback from litellm._uuid import uuid @@ -19,9 +18,6 @@ import litellm.litellm_core_utils.litellm_logging from litellm.utils import ModelResponseListIterator from litellm.types.utils import ModelResponseStream -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path from dotenv import load_dotenv load_dotenv() diff --git a/tests/local_testing/test_supabase_integration.py b/tests/local_testing/test_supabase_integration.py index 96d2889a795..5331de86303 100644 --- a/tests/local_testing/test_supabase_integration.py +++ b/tests/local_testing/test_supabase_integration.py @@ -4,9 +4,6 @@ import sys, os import traceback import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm import embedding, completion diff --git a/tests/local_testing/test_text_completion.py b/tests/local_testing/test_text_completion.py index 227d8e5096a..a814ce6d303 100644 --- a/tests/local_testing/test_text_completion.py +++ b/tests/local_testing/test_text_completion.py @@ -1,7 +1,5 @@ import asyncio import json -import os -import sys import traceback from dotenv import load_dotenv @@ -9,9 +7,6 @@ from dotenv import load_dotenv load_dotenv() import io -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path from unittest.mock import MagicMock, patch import pytest diff --git a/tests/local_testing/test_timeout.py b/tests/local_testing/test_timeout.py index 6b490f1cef2..66054a0930a 100644 --- a/tests/local_testing/test_timeout.py +++ b/tests/local_testing/test_timeout.py @@ -2,12 +2,8 @@ # This tests the timeout decorator import os -import sys import traceback -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import time from litellm._uuid import uuid diff --git a/tests/local_testing/test_tpm_rpm_routing_v2.py b/tests/local_testing/test_tpm_rpm_routing_v2.py index c6917775d4b..7478bd253b6 100644 --- a/tests/local_testing/test_tpm_rpm_routing_v2.py +++ b/tests/local_testing/test_tpm_rpm_routing_v2.py @@ -4,7 +4,6 @@ import asyncio import os import random -import sys import time import traceback from datetime import datetime @@ -13,9 +12,6 @@ from dotenv import load_dotenv load_dotenv() -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path from unittest.mock import AsyncMock, MagicMock, patch from litellm.types.utils import StandardLoggingPayload import pytest diff --git a/tests/local_testing/test_ui_sso_helper_utils.py b/tests/local_testing/test_ui_sso_helper_utils.py index c7206363278..bb446c54738 100644 --- a/tests/local_testing/test_ui_sso_helper_utils.py +++ b/tests/local_testing/test_ui_sso_helper_utils.py @@ -3,9 +3,7 @@ import asyncio -import os import random -import sys import time import traceback from datetime import datetime @@ -15,9 +13,6 @@ from fastapi import Request load_dotenv() -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import logging from litellm.proxy.management_endpoints.sso_helper_utils import ( diff --git a/tests/local_testing/test_unit_test_caching.py b/tests/local_testing/test_unit_test_caching.py index e25b75e658f..fd9f4bb9e89 100644 --- a/tests/local_testing/test_unit_test_caching.py +++ b/tests/local_testing/test_unit_test_caching.py @@ -1,5 +1,3 @@ -import os -import sys import time import traceback from litellm._uuid import uuid @@ -7,9 +5,6 @@ from litellm._uuid import uuid from dotenv import load_dotenv load_dotenv() -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import asyncio import hashlib import random diff --git a/tests/local_testing/test_update_spend.py b/tests/local_testing/test_update_spend.py index 7894f330796..b492a752c2c 100644 --- a/tests/local_testing/test_update_spend.py +++ b/tests/local_testing/test_update_spend.py @@ -5,7 +5,6 @@ import asyncio import os import random -import sys import time import traceback from datetime import datetime @@ -15,9 +14,6 @@ from fastapi import Request load_dotenv() -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import logging import pytest diff --git a/tests/local_testing/test_validate_environment.py b/tests/local_testing/test_validate_environment.py index dce61b3abbb..289c2bb7c99 100644 --- a/tests/local_testing/test_validate_environment.py +++ b/tests/local_testing/test_validate_environment.py @@ -4,9 +4,6 @@ import sys, os import traceback -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import time import litellm diff --git a/tests/local_testing/test_wandb.py b/tests/local_testing/test_wandb.py index 58a9c9f5ddf..02ab2787cf3 100644 --- a/tests/local_testing/test_wandb.py +++ b/tests/local_testing/test_wandb.py @@ -1,10 +1,8 @@ -import sys import os import io, asyncio # import logging # logging.basicConfig(level=logging.DEBUG) -sys.path.insert(0, os.path.abspath("../..")) from litellm import completion import litellm diff --git a/tests/logging_callback_tests/base_test.py b/tests/logging_callback_tests/base_test.py index 0d1e7dfcf77..68faf4bdb35 100644 --- a/tests/logging_callback_tests/base_test.py +++ b/tests/logging_callback_tests/base_test.py @@ -2,14 +2,9 @@ import asyncio import httpx import json import pytest -import sys from typing import Any, Dict, List from unittest.mock import MagicMock, Mock, patch -import os -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm.exceptions import BadRequestError from litellm.llms.custom_httpx.http_handler import AsyncHTTPHandler, HTTPHandler diff --git a/tests/logging_callback_tests/conftest.py b/tests/logging_callback_tests/conftest.py index dedff9a5aee..66d0ee01f8e 100644 --- a/tests/logging_callback_tests/conftest.py +++ b/tests/logging_callback_tests/conftest.py @@ -10,13 +10,9 @@ import importlib import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from tests._vcr_conftest_common import ( # noqa: E402,F401 @@ -180,7 +176,6 @@ def setup_and_teardown(): Module-scoped setup. Reloads litellm only in single-process mode (skipped under xdist to avoid cross-worker interference). """ - sys.path.insert(0, os.path.abspath("../..")) import litellm diff --git a/tests/logging_callback_tests/create_mock_standard_logging_payload.py b/tests/logging_callback_tests/create_mock_standard_logging_payload.py index 106328e95e2..096c8ff8c60 100644 --- a/tests/logging_callback_tests/create_mock_standard_logging_payload.py +++ b/tests/logging_callback_tests/create_mock_standard_logging_payload.py @@ -1,9 +1,6 @@ import io -import os -import sys -sys.path.insert(0, os.path.abspath("../..")) import asyncio import gzip diff --git a/tests/logging_callback_tests/test_alerting.py b/tests/logging_callback_tests/test_alerting.py index 83513107ad3..3074e973a8e 100644 --- a/tests/logging_callback_tests/test_alerting.py +++ b/tests/logging_callback_tests/test_alerting.py @@ -6,7 +6,6 @@ import io import json import os import random -import sys import time from litellm._uuid import uuid from datetime import datetime, timedelta @@ -18,8 +17,6 @@ from litellm.types.integrations.slack_alerting import AlertType # import logging # logging.basicConfig(level=logging.DEBUG) -sys.path.insert(0, os.path.abspath("../..")) -import os import unittest.mock from unittest.mock import AsyncMock, MagicMock, patch diff --git a/tests/logging_callback_tests/test_amazing_s3_logs.py b/tests/logging_callback_tests/test_amazing_s3_logs.py index 08b9ac7d01a..befc5ae3996 100644 --- a/tests/logging_callback_tests/test_amazing_s3_logs.py +++ b/tests/logging_callback_tests/test_amazing_s3_logs.py @@ -1,11 +1,8 @@ -import sys -import os import io, asyncio from collections import defaultdict # import logging # logging.basicConfig(level=logging.DEBUG) -sys.path.insert(0, os.path.abspath("../..")) from litellm import completion import litellm diff --git a/tests/logging_callback_tests/test_assemble_streaming_responses.py b/tests/logging_callback_tests/test_assemble_streaming_responses.py index 919b76e95a6..d6905ce3565 100644 --- a/tests/logging_callback_tests/test_assemble_streaming_responses.py +++ b/tests/logging_callback_tests/test_assemble_streaming_responses.py @@ -9,14 +9,9 @@ Testing for _assemble_complete_response_from_streaming_chunks """ import json -import os -import sys from datetime import datetime from unittest.mock import AsyncMock -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import httpx diff --git a/tests/logging_callback_tests/test_bedrock_knowledgebase_hook.py b/tests/logging_callback_tests/test_bedrock_knowledgebase_hook.py index d6d0652ed77..3f9f2bacdd3 100644 --- a/tests/logging_callback_tests/test_bedrock_knowledgebase_hook.py +++ b/tests/logging_callback_tests/test_bedrock_knowledgebase_hook.py @@ -1,9 +1,7 @@ import io import os -import sys -sys.path.insert(0, os.path.abspath("../..")) import asyncio import litellm diff --git a/tests/logging_callback_tests/test_built_in_tools_cost_tracking.py b/tests/logging_callback_tests/test_built_in_tools_cost_tracking.py index 942c26438c8..53fe493ad9f 100644 --- a/tests/logging_callback_tests/test_built_in_tools_cost_tracking.py +++ b/tests/logging_callback_tests/test_built_in_tools_cost_tracking.py @@ -1,5 +1,3 @@ -import os -import sys import traceback from litellm._uuid import uuid import pytest @@ -14,9 +12,6 @@ import json # this file is to test litellm/proxy -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm import asyncio from typing import Optional diff --git a/tests/logging_callback_tests/test_custom_callback_router.py b/tests/logging_callback_tests/test_custom_callback_router.py index 70da10ffeeb..8cbe5fc6ccc 100644 --- a/tests/logging_callback_tests/test_custom_callback_router.py +++ b/tests/logging_callback_tests/test_custom_callback_router.py @@ -3,14 +3,12 @@ import asyncio import inspect import os -import sys import time import traceback from datetime import datetime import pytest -sys.path.insert(0, os.path.abspath("../..")) from typing import List, Literal, Optional from unittest.mock import AsyncMock, MagicMock, patch diff --git a/tests/logging_callback_tests/test_datadog.py b/tests/logging_callback_tests/test_datadog.py index bc7a9a211a4..83a652e8884 100644 --- a/tests/logging_callback_tests/test_datadog.py +++ b/tests/logging_callback_tests/test_datadog.py @@ -1,6 +1,5 @@ import io import os -import sys from litellm.integrations.datadog.datadog_handler import ( get_datadog_source, @@ -11,7 +10,6 @@ from litellm.integrations.datadog.datadog_handler import ( get_datadog_tags, ) -sys.path.insert(0, os.path.abspath("../..")) import asyncio import gzip diff --git a/tests/logging_callback_tests/test_datadog_llm_obs.py b/tests/logging_callback_tests/test_datadog_llm_obs.py index 56aae7aa8bf..bed1a214b44 100644 --- a/tests/logging_callback_tests/test_datadog_llm_obs.py +++ b/tests/logging_callback_tests/test_datadog_llm_obs.py @@ -3,11 +3,8 @@ Test the DataDogLLMObsLogger """ import io -import os -import sys -sys.path.insert(0, os.path.abspath("../..")) import asyncio import gzip diff --git a/tests/logging_callback_tests/test_dynamic_otel_keys.py b/tests/logging_callback_tests/test_dynamic_otel_keys.py index 2a463fddc0d..f91f9b166ed 100644 --- a/tests/logging_callback_tests/test_dynamic_otel_keys.py +++ b/tests/logging_callback_tests/test_dynamic_otel_keys.py @@ -1,7 +1,4 @@ -import sys -import os -sys.path.insert(0, os.path.abspath("../..")) from litellm.litellm_core_utils.initialize_dynamic_callback_params import ( initialize_standard_callback_dynamic_params, diff --git a/tests/logging_callback_tests/test_gcs_pub_sub.py b/tests/logging_callback_tests/test_gcs_pub_sub.py index 17322b965a7..10957fa2f92 100644 --- a/tests/logging_callback_tests/test_gcs_pub_sub.py +++ b/tests/logging_callback_tests/test_gcs_pub_sub.py @@ -1,9 +1,7 @@ import io import os -import sys -sys.path.insert(0, os.path.abspath("../..")) import asyncio import litellm diff --git a/tests/logging_callback_tests/test_generic_api_callback.py b/tests/logging_callback_tests/test_generic_api_callback.py index 9ad17b3d6e2..29d8f9e5694 100644 --- a/tests/logging_callback_tests/test_generic_api_callback.py +++ b/tests/logging_callback_tests/test_generic_api_callback.py @@ -1,9 +1,7 @@ import io import os -import sys -sys.path.insert(0, os.path.abspath("../..")) import asyncio import litellm diff --git a/tests/logging_callback_tests/test_humanloop_unit_tests.py b/tests/logging_callback_tests/test_humanloop_unit_tests.py index 9b45c24b81e..edea2098127 100644 --- a/tests/logging_callback_tests/test_humanloop_unit_tests.py +++ b/tests/logging_callback_tests/test_humanloop_unit_tests.py @@ -1,11 +1,6 @@ -import os -import sys import threading from datetime import datetime -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system-path import pytest from litellm.integrations.humanloop import HumanLoopPromptManager diff --git a/tests/logging_callback_tests/test_langfuse_e2e_test.py b/tests/logging_callback_tests/test_langfuse_e2e_test.py index bc64e30738f..5682d3720d8 100644 --- a/tests/logging_callback_tests/test_langfuse_e2e_test.py +++ b/tests/logging_callback_tests/test_langfuse_e2e_test.py @@ -3,7 +3,6 @@ import copy import json import logging import os -import sys import threading from typing import Any, Optional from unittest.mock import AsyncMock, MagicMock, patch @@ -11,7 +10,6 @@ from unittest.mock import AsyncMock, MagicMock, patch import httpx logging.basicConfig(level=logging.DEBUG) -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm import completion diff --git a/tests/logging_callback_tests/test_langfuse_unit_tests.py b/tests/logging_callback_tests/test_langfuse_unit_tests.py index 547e9d15f0b..1c25b169243 100644 --- a/tests/logging_callback_tests/test_langfuse_unit_tests.py +++ b/tests/logging_callback_tests/test_langfuse_unit_tests.py @@ -1,9 +1,5 @@ import os -import sys -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system-path import pytest from litellm.integrations.langfuse.langfuse import ( diff --git a/tests/logging_callback_tests/test_langsmith_unit_test.py b/tests/logging_callback_tests/test_langsmith_unit_test.py index 9cc1acd1ee4..17cd63d8974 100644 --- a/tests/logging_callback_tests/test_langsmith_unit_test.py +++ b/tests/logging_callback_tests/test_langsmith_unit_test.py @@ -1,9 +1,7 @@ import io import os -import sys -sys.path.insert(0, os.path.abspath("../..")) import asyncio import gzip @@ -52,7 +50,6 @@ async def test_get_credentials_from_env(): assert credentials["LANGSMITH_TENANT_ID"] == "test-tenant-id" # Test tenant_id from environment variable - import os os.environ["LANGSMITH_TENANT_ID"] = "env-tenant-id" credentials = logger.get_credentials_from_env() diff --git a/tests/logging_callback_tests/test_log_db_redis_services.py b/tests/logging_callback_tests/test_log_db_redis_services.py index a8c3929be16..e3bc8383c46 100644 --- a/tests/logging_callback_tests/test_log_db_redis_services.py +++ b/tests/logging_callback_tests/test_log_db_redis_services.py @@ -1,8 +1,5 @@ import io -import os -import sys -sys.path.insert(0, os.path.abspath("../..")) import asyncio import gzip diff --git a/tests/logging_callback_tests/test_logging_redaction_e2e_test.py b/tests/logging_callback_tests/test_logging_redaction_e2e_test.py index 3b42595b959..c754c7b8c2a 100644 --- a/tests/logging_callback_tests/test_logging_redaction_e2e_test.py +++ b/tests/logging_callback_tests/test_logging_redaction_e2e_test.py @@ -1,10 +1,7 @@ import io -import os -import sys from typing import Optional, Union -sys.path.insert(0, os.path.abspath("../..")) import asyncio import gzip diff --git a/tests/logging_callback_tests/test_moderations_api_logging.py b/tests/logging_callback_tests/test_moderations_api_logging.py index 9190f2aebe5..a2a356d3665 100644 --- a/tests/logging_callback_tests/test_moderations_api_logging.py +++ b/tests/logging_callback_tests/test_moderations_api_logging.py @@ -1,5 +1,3 @@ -import os -import sys import traceback from litellm._uuid import uuid import pytest @@ -12,9 +10,6 @@ import io import time import json -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm.router import Router import asyncio diff --git a/tests/logging_callback_tests/test_opentelemetry_unit_tests.py b/tests/logging_callback_tests/test_opentelemetry_unit_tests.py index 767f840a003..fcbd6dbc531 100644 --- a/tests/logging_callback_tests/test_opentelemetry_unit_tests.py +++ b/tests/logging_callback_tests/test_opentelemetry_unit_tests.py @@ -10,9 +10,6 @@ from dotenv import load_dotenv load_dotenv() -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import pytest import litellm from unittest.mock import patch, MagicMock, AsyncMock diff --git a/tests/logging_callback_tests/test_otel_logging.py b/tests/logging_callback_tests/test_otel_logging.py index b6d7ef4be4e..ff85a320904 100644 --- a/tests/logging_callback_tests/test_otel_logging.py +++ b/tests/logging_callback_tests/test_otel_logging.py @@ -1,12 +1,7 @@ import json -import os -import sys from datetime import datetime from unittest.mock import AsyncMock -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system-path import pytest import litellm diff --git a/tests/logging_callback_tests/test_pagerduty_alerting.py b/tests/logging_callback_tests/test_pagerduty_alerting.py index 108a1ead1a4..1426dc32081 100644 --- a/tests/logging_callback_tests/test_pagerduty_alerting.py +++ b/tests/logging_callback_tests/test_pagerduty_alerting.py @@ -1,11 +1,8 @@ import asyncio -import os import random -import sys from datetime import datetime, timedelta from typing import Optional -sys.path.insert(0, os.path.abspath("../..")) import pytest import litellm diff --git a/tests/logging_callback_tests/test_posthog.py b/tests/logging_callback_tests/test_posthog.py index b3f346bcf9d..92bbc255730 100644 --- a/tests/logging_callback_tests/test_posthog.py +++ b/tests/logging_callback_tests/test_posthog.py @@ -1,7 +1,5 @@ import os -import sys -sys.path.insert(0, os.path.abspath("../..")) import pytest diff --git a/tests/logging_callback_tests/test_spend_logs.py b/tests/logging_callback_tests/test_spend_logs.py index 709aa81f421..feecfc9f4ab 100644 --- a/tests/logging_callback_tests/test_spend_logs.py +++ b/tests/logging_callback_tests/test_spend_logs.py @@ -1,5 +1,3 @@ -import os -import sys import traceback from litellm._uuid import uuid @@ -13,9 +11,6 @@ import time # this file is to test litellm/proxy -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import asyncio import datetime import json diff --git a/tests/logging_callback_tests/test_standard_logging_payload.py b/tests/logging_callback_tests/test_standard_logging_payload.py index 6a632c32fc2..da1fbbaa04f 100644 --- a/tests/logging_callback_tests/test_standard_logging_payload.py +++ b/tests/logging_callback_tests/test_standard_logging_payload.py @@ -3,14 +3,9 @@ Unit tests for StandardLoggingPayloadSetup """ import json -import os -import sys from datetime import datetime from unittest.mock import AsyncMock -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system-path from datetime import datetime as dt_object import time import pytest diff --git a/tests/logging_callback_tests/test_standard_logging_payload_excluded_fields.py b/tests/logging_callback_tests/test_standard_logging_payload_excluded_fields.py index 4088bdd2cf7..d8c45d832ce 100644 --- a/tests/logging_callback_tests/test_standard_logging_payload_excluded_fields.py +++ b/tests/logging_callback_tests/test_standard_logging_payload_excluded_fields.py @@ -13,15 +13,12 @@ Example config: standard_logging_payload_excluded_fields: ["response", "messages"] """ -import os -import sys from copy import deepcopy from typing import Dict, List, Optional from unittest.mock import MagicMock, patch import pytest -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm.integrations.custom_logger import CustomLogger diff --git a/tests/logging_callback_tests/test_token_counting.py b/tests/logging_callback_tests/test_token_counting.py index e2160076b00..c942a9d2686 100644 --- a/tests/logging_callback_tests/test_token_counting.py +++ b/tests/logging_callback_tests/test_token_counting.py @@ -1,5 +1,4 @@ import os -import sys import traceback from litellm._uuid import uuid import pytest @@ -14,9 +13,6 @@ import json # this file is to test litellm/proxy -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm import asyncio from typing import Optional diff --git a/tests/logging_callback_tests/test_unit_test_litellm_logging.py b/tests/logging_callback_tests/test_unit_test_litellm_logging.py index f82813b7475..42ba4ff35f1 100644 --- a/tests/logging_callback_tests/test_unit_test_litellm_logging.py +++ b/tests/logging_callback_tests/test_unit_test_litellm_logging.py @@ -1,12 +1,7 @@ import json -import os -import sys from datetime import datetime from unittest.mock import AsyncMock -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system-path from typing import Literal diff --git a/tests/logging_callback_tests/test_unit_tests_init_callbacks.py b/tests/logging_callback_tests/test_unit_tests_init_callbacks.py index b2243eed049..f8917ddee78 100644 --- a/tests/logging_callback_tests/test_unit_tests_init_callbacks.py +++ b/tests/logging_callback_tests/test_unit_tests_init_callbacks.py @@ -1,12 +1,8 @@ import json import os -import sys from datetime import datetime from unittest.mock import AsyncMock -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system-path from typing import Literal diff --git a/tests/logging_callback_tests/test_view_request_resp_logs.py b/tests/logging_callback_tests/test_view_request_resp_logs.py index 37b65855774..249e84286d5 100644 --- a/tests/logging_callback_tests/test_view_request_resp_logs.py +++ b/tests/logging_callback_tests/test_view_request_resp_logs.py @@ -1,8 +1,5 @@ import io -import os -import sys -sys.path.insert(0, os.path.abspath("../..")) import asyncio import json diff --git a/tests/mcp_tests/conftest.py b/tests/mcp_tests/conftest.py index a3b425f72c3..d1dc3ec7216 100644 --- a/tests/mcp_tests/conftest.py +++ b/tests/mcp_tests/conftest.py @@ -2,13 +2,9 @@ import importlib import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm import asyncio @@ -29,9 +25,6 @@ def setup_and_teardown(): This fixture reloads litellm before every function. To speed up testing by removing callbacks being chained. """ curr_dir = os.getcwd() # Get the current working directory - sys.path.insert( - 0, os.path.abspath("../..") - ) # Adds the project directory to the system path from litellm import Router diff --git a/tests/mcp_tests/test_aresponses_api_with_mcp.py b/tests/mcp_tests/test_aresponses_api_with_mcp.py index 6da8ce598a9..7a48c366003 100644 --- a/tests/mcp_tests/test_aresponses_api_with_mcp.py +++ b/tests/mcp_tests/test_aresponses_api_with_mcp.py @@ -1,11 +1,9 @@ import logging import os -import sys import pytest from typing import List, Any, cast from unittest.mock import AsyncMock, patch -sys.path.insert(0, os.path.abspath("../../..")) # Import required modules import litellm diff --git a/tests/mcp_tests/test_mcp_client_unit.py b/tests/mcp_tests/test_mcp_client_unit.py index 43260eda1b7..aadaadd510e 100644 --- a/tests/mcp_tests/test_mcp_client_unit.py +++ b/tests/mcp_tests/test_mcp_client_unit.py @@ -3,13 +3,10 @@ Unit tests for the MCPClient class - critical functionality only. """ import base64 -import os -import sys import pytest from unittest.mock import AsyncMock, MagicMock, patch, ANY # Add the project root to the path -sys.path.insert(0, os.path.abspath("../../..")) import litellm.experimental_mcp_client.client as mcp_client_module from litellm.experimental_mcp_client.client import MCPClient diff --git a/tests/mcp_tests/test_mcp_guardrails.py b/tests/mcp_tests/test_mcp_guardrails.py index 42f4aa6778b..04401992449 100644 --- a/tests/mcp_tests/test_mcp_guardrails.py +++ b/tests/mcp_tests/test_mcp_guardrails.py @@ -7,14 +7,11 @@ including various guardrail types and proper exception handling. import asyncio import pytest -import sys -import os from datetime import datetime from typing import Optional, Dict, Any from unittest.mock import MagicMock, AsyncMock, patch # Add the project root to the path -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm.exceptions import BlockedPiiEntityError, GuardrailRaisedException diff --git a/tests/mcp_tests/test_mcp_litellm_client.py b/tests/mcp_tests/test_mcp_litellm_client.py index e197673ab10..cfc0692c8fa 100644 --- a/tests/mcp_tests/test_mcp_litellm_client.py +++ b/tests/mcp_tests/test_mcp_litellm_client.py @@ -1,16 +1,11 @@ # Create server parameters for stdio connection import os -import sys import pytest import asyncio -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from mcp import ClientSession, StdioServerParameters from mcp.client.stdio import stdio_client -import os from litellm import experimental_mcp_client import litellm import json diff --git a/tests/mcp_tests/test_mcp_logging.py b/tests/mcp_tests/test_mcp_logging.py index 55b49aa0d29..7ee745b311e 100644 --- a/tests/mcp_tests/test_mcp_logging.py +++ b/tests/mcp_tests/test_mcp_logging.py @@ -1,14 +1,10 @@ import os -import sys import pytest import asyncio from typing import Optional from unittest.mock import AsyncMock, patch -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path import litellm from litellm.types.utils import StandardLoggingPayload from litellm.integrations.custom_logger import CustomLogger diff --git a/tests/mcp_tests/test_mcp_server.py b/tests/mcp_tests/test_mcp_server.py index 434a9bc3809..e06c33263fb 100644 --- a/tests/mcp_tests/test_mcp_server.py +++ b/tests/mcp_tests/test_mcp_server.py @@ -1,13 +1,9 @@ # Create server parameters for stdio connection import os -import sys import pytest from unittest.mock import AsyncMock, MagicMock, patch from contextlib import asynccontextmanager -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from litellm.proxy._experimental.mcp_server.mcp_server_manager import ( MCPServerManager, diff --git a/tests/mcp_tests/test_semantic_tool_filter_e2e.py b/tests/mcp_tests/test_semantic_tool_filter_e2e.py index f71067fde6d..aa25c98107e 100644 --- a/tests/mcp_tests/test_semantic_tool_filter_e2e.py +++ b/tests/mcp_tests/test_semantic_tool_filter_e2e.py @@ -4,12 +4,10 @@ End-to-end test for MCP Semantic Tool Filtering import asyncio import os -import sys from unittest.mock import Mock import pytest -sys.path.insert(0, os.path.abspath("../..")) from mcp.types import Tool as MCPTool diff --git a/tests/ocr_tests/conftest.py b/tests/ocr_tests/conftest.py index 09d535dee4b..259aad5f782 100644 --- a/tests/ocr_tests/conftest.py +++ b/tests/ocr_tests/conftest.py @@ -5,12 +5,9 @@ # Vertex AI OCR) are replayed for 24h. See tests/llm_translation/Readme.md # for the design overview. -import os -import sys import pytest -sys.path.insert(0, os.path.abspath("../..")) from tests._vcr_conftest_common import ( # noqa: E402,F401 VerboseReporterState, diff --git a/tests/otel_tests/test_prometheus.py b/tests/otel_tests/test_prometheus.py index 90c71037609..84d5f48a706 100644 --- a/tests/otel_tests/test_prometheus.py +++ b/tests/otel_tests/test_prometheus.py @@ -6,14 +6,9 @@ import pytest import aiohttp import asyncio from litellm._uuid import uuid -import os -import sys from openai import AsyncOpenAI from typing import Dict, Any -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path END_USER_ID = "my-test-user-34" diff --git a/tests/pass_through_unit_tests/base_anthropic_messages_prompt_caching_test.py b/tests/pass_through_unit_tests/base_anthropic_messages_prompt_caching_test.py index e8d14b00681..520b31513f5 100644 --- a/tests/pass_through_unit_tests/base_anthropic_messages_prompt_caching_test.py +++ b/tests/pass_through_unit_tests/base_anthropic_messages_prompt_caching_test.py @@ -17,7 +17,6 @@ import sys from abc import ABC, abstractmethod from typing import Any, Dict, List -sys.path.insert(0, os.path.abspath("../../..")) sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))) import pytest diff --git a/tests/pass_through_unit_tests/base_anthropic_messages_tool_search_test.py b/tests/pass_through_unit_tests/base_anthropic_messages_tool_search_test.py index 64acc68c264..6a5bf627ac7 100644 --- a/tests/pass_through_unit_tests/base_anthropic_messages_tool_search_test.py +++ b/tests/pass_through_unit_tests/base_anthropic_messages_tool_search_test.py @@ -8,12 +8,9 @@ Reference: https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-se """ import json -import os -import sys from abc import ABC, abstractmethod from typing import Any, Dict, List -sys.path.insert(0, os.path.abspath("../../..")) import pytest import litellm diff --git a/tests/pass_through_unit_tests/base_anthropic_unified_messages_test.py b/tests/pass_through_unit_tests/base_anthropic_unified_messages_test.py index 821cb59887f..153c72e4a11 100644 --- a/tests/pass_through_unit_tests/base_anthropic_unified_messages_test.py +++ b/tests/pass_through_unit_tests/base_anthropic_unified_messages_test.py @@ -1,15 +1,10 @@ import json -import os -import sys from datetime import datetime from typing import AsyncIterator, Dict, Any import asyncio import unittest.mock from unittest.mock import AsyncMock, MagicMock -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path import litellm import pytest from dotenv import load_dotenv diff --git a/tests/pass_through_unit_tests/conftest.py b/tests/pass_through_unit_tests/conftest.py index 10615ddcb73..e6e98f790e8 100644 --- a/tests/pass_through_unit_tests/conftest.py +++ b/tests/pass_through_unit_tests/conftest.py @@ -1,9 +1,6 @@ -import os -import sys import pytest -sys.path.insert(0, os.path.abspath("../..")) from tests._vcr_conftest_common import ( # noqa: E402,F401 VerboseReporterState, diff --git a/tests/pass_through_unit_tests/messages_api_structured_output/base_anthropic_messages_structured_output_test.py b/tests/pass_through_unit_tests/messages_api_structured_output/base_anthropic_messages_structured_output_test.py index ce5e8aa25fe..8f27fa000f6 100644 --- a/tests/pass_through_unit_tests/messages_api_structured_output/base_anthropic_messages_structured_output_test.py +++ b/tests/pass_through_unit_tests/messages_api_structured_output/base_anthropic_messages_structured_output_test.py @@ -6,12 +6,9 @@ by making actual API calls and validating JSON response format. """ import json -import os -import sys from abc import ABC, abstractmethod from typing import Any, Dict, List, Optional -sys.path.insert(0, os.path.abspath("../../..")) import pytest import litellm diff --git a/tests/pass_through_unit_tests/messages_api_structured_output/test_anthropic_api_structured_output.py b/tests/pass_through_unit_tests/messages_api_structured_output/test_anthropic_api_structured_output.py index 261c7d18d65..6f87aed4393 100644 --- a/tests/pass_through_unit_tests/messages_api_structured_output/test_anthropic_api_structured_output.py +++ b/tests/pass_through_unit_tests/messages_api_structured_output/test_anthropic_api_structured_output.py @@ -7,10 +7,7 @@ by making actual API calls and validating JSON response format. Requires ANTHROPIC_API_KEY environment variable. """ -import os -import sys -sys.path.insert(0, os.path.abspath("../../../..")) from .base_anthropic_messages_structured_output_test import ( BaseAnthropicMessagesStructuredOutputTest, diff --git a/tests/pass_through_unit_tests/messages_api_structured_output/test_azure_anthropic_structured_output.py b/tests/pass_through_unit_tests/messages_api_structured_output/test_azure_anthropic_structured_output.py index b2470bf6b67..1ca4213a2b1 100644 --- a/tests/pass_through_unit_tests/messages_api_structured_output/test_azure_anthropic_structured_output.py +++ b/tests/pass_through_unit_tests/messages_api_structured_output/test_azure_anthropic_structured_output.py @@ -8,10 +8,8 @@ Requires Azure AI credentials and model deployment. """ import os -import sys from typing import Optional -sys.path.insert(0, os.path.abspath("../../../..")) from .base_anthropic_messages_structured_output_test import ( BaseAnthropicMessagesStructuredOutputTest, diff --git a/tests/pass_through_unit_tests/messages_api_structured_output/test_bedrock_converse_structured_output.py b/tests/pass_through_unit_tests/messages_api_structured_output/test_bedrock_converse_structured_output.py index 7af7e8e38eb..bb7aa3dec35 100644 --- a/tests/pass_through_unit_tests/messages_api_structured_output/test_bedrock_converse_structured_output.py +++ b/tests/pass_through_unit_tests/messages_api_structured_output/test_bedrock_converse_structured_output.py @@ -7,10 +7,7 @@ by making actual API calls and validating JSON response format. Requires AWS credentials and Bedrock model access. """ -import os -import sys -sys.path.insert(0, os.path.abspath("../../../..")) from .base_anthropic_messages_structured_output_test import ( BaseAnthropicMessagesStructuredOutputTest, diff --git a/tests/pass_through_unit_tests/messages_api_structured_output/test_bedrock_invoke_structured_output.py b/tests/pass_through_unit_tests/messages_api_structured_output/test_bedrock_invoke_structured_output.py index 09813507058..05a78d9ea00 100644 --- a/tests/pass_through_unit_tests/messages_api_structured_output/test_bedrock_invoke_structured_output.py +++ b/tests/pass_through_unit_tests/messages_api_structured_output/test_bedrock_invoke_structured_output.py @@ -7,12 +7,9 @@ by making actual API calls and validating JSON response format. Requires AWS credentials and Bedrock model access. """ -import os -import sys import pytest -sys.path.insert(0, os.path.abspath("../../../..")) from .base_anthropic_messages_structured_output_test import ( BaseAnthropicMessagesStructuredOutputTest, diff --git a/tests/pass_through_unit_tests/test_anthropic_messages_passthrough.py b/tests/pass_through_unit_tests/test_anthropic_messages_passthrough.py index a53efdd8255..940c9624ec4 100644 --- a/tests/pass_through_unit_tests/test_anthropic_messages_passthrough.py +++ b/tests/pass_through_unit_tests/test_anthropic_messages_passthrough.py @@ -1,15 +1,11 @@ import json import os -import sys from datetime import datetime from typing import AsyncIterator, Dict, Any import asyncio import unittest.mock from unittest.mock import AsyncMock, MagicMock -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path import litellm import pytest from dotenv import load_dotenv @@ -41,7 +37,6 @@ def event_loop(): @pytest.fixture(scope="function", autouse=True) def setup_and_teardown(event_loop): # Add event_loop as a dependency curr_dir = os.getcwd() - sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm import Router diff --git a/tests/pass_through_unit_tests/test_anthropic_messages_prompt_caching.py b/tests/pass_through_unit_tests/test_anthropic_messages_prompt_caching.py index a194ded12fd..e64218b677f 100644 --- a/tests/pass_through_unit_tests/test_anthropic_messages_prompt_caching.py +++ b/tests/pass_through_unit_tests/test_anthropic_messages_prompt_caching.py @@ -11,10 +11,7 @@ Per AWS docs (https://docs.aws.amazon.com/bedrock/latest/userguide/prompt-cachin - Claude 3.5 Haiku: GA, 2048 min tokens """ -import os -import sys -sys.path.insert(0, os.path.abspath("../../..")) import pytest from base_anthropic_messages_prompt_caching_test import ( diff --git a/tests/pass_through_unit_tests/test_anthropic_messages_tool_search.py b/tests/pass_through_unit_tests/test_anthropic_messages_tool_search.py index c8b91c3c49f..9006356ff2a 100644 --- a/tests/pass_through_unit_tests/test_anthropic_messages_tool_search.py +++ b/tests/pass_through_unit_tests/test_anthropic_messages_tool_search.py @@ -13,10 +13,7 @@ Supported providers: Reference: https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-search-tool """ -import os -import sys -sys.path.insert(0, os.path.abspath("../../..")) import pytest from base_anthropic_messages_tool_search_test import ( diff --git a/tests/pass_through_unit_tests/test_assemblyai_unit_tests_passthrough.py b/tests/pass_through_unit_tests/test_assemblyai_unit_tests_passthrough.py index 6fdd4cc0f24..bbc6b6b5937 100644 --- a/tests/pass_through_unit_tests/test_assemblyai_unit_tests_passthrough.py +++ b/tests/pass_through_unit_tests/test_assemblyai_unit_tests_passthrough.py @@ -1,12 +1,7 @@ import json -import os -import sys from datetime import datetime from unittest.mock import AsyncMock, Mock, patch -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system-path import httpx @@ -15,12 +10,7 @@ import litellm from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj -import os -import sys -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system-path from litellm.proxy.pass_through_endpoints.llm_provider_handlers.assembly_passthrough_logging_handler import ( AssemblyAIPassthroughLoggingHandler, diff --git a/tests/pass_through_unit_tests/test_bedrock_anthropic_messages_test.py b/tests/pass_through_unit_tests/test_bedrock_anthropic_messages_test.py index dcc44cae77e..e86c32f916d 100644 --- a/tests/pass_through_unit_tests/test_bedrock_anthropic_messages_test.py +++ b/tests/pass_through_unit_tests/test_bedrock_anthropic_messages_test.py @@ -1,6 +1,5 @@ import json import os -import sys from datetime import datetime from typing import AsyncIterator, Dict, Any import asyncio @@ -9,9 +8,6 @@ from unittest.mock import MagicMock import pytest from litellm.router import Router -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path import litellm from base_anthropic_unified_messages_test import BaseAnthropicMessagesTest diff --git a/tests/pass_through_unit_tests/test_bedrock_tool_use_beta_header.py b/tests/pass_through_unit_tests/test_bedrock_tool_use_beta_header.py index ed7f38cba4b..a28b8a147af 100644 --- a/tests/pass_through_unit_tests/test_bedrock_tool_use_beta_header.py +++ b/tests/pass_through_unit_tests/test_bedrock_tool_use_beta_header.py @@ -5,11 +5,8 @@ Tests that LiteLLM correctly filters out the advanced-tool-use-2025-11-20 beta h for Bedrock Invoke API, which doesn't support it and returns a 400 "invalid beta flag" error. """ -import os -import sys import pytest -sys.path.insert(0, os.path.abspath("../..")) import litellm diff --git a/tests/pass_through_unit_tests/test_claude_code_marketplace.py b/tests/pass_through_unit_tests/test_claude_code_marketplace.py index 1a225b44b50..2ca81f1d5d3 100644 --- a/tests/pass_through_unit_tests/test_claude_code_marketplace.py +++ b/tests/pass_through_unit_tests/test_claude_code_marketplace.py @@ -7,15 +7,12 @@ Tests: """ import json -import os -import sys import time from datetime import datetime, timezone from unittest.mock import AsyncMock, MagicMock import pytest -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm.proxy._types import UserAPIKeyAuth diff --git a/tests/pass_through_unit_tests/test_custom_logger_passthrough.py b/tests/pass_through_unit_tests/test_custom_logger_passthrough.py index 6e6507f9826..e70f2cf4430 100644 --- a/tests/pass_through_unit_tests/test_custom_logger_passthrough.py +++ b/tests/pass_through_unit_tests/test_custom_logger_passthrough.py @@ -1,6 +1,5 @@ import json import os -import sys from datetime import datetime from unittest.mock import AsyncMock, Mock, patch, MagicMock from typing import Optional @@ -8,9 +7,6 @@ from fastapi import Request import pytest import asyncio -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm.proxy._types import UserAPIKeyAuth diff --git a/tests/pass_through_unit_tests/test_pass_through_unit_tests.py b/tests/pass_through_unit_tests/test_pass_through_unit_tests.py index 77fb924c085..ed04b63000f 100644 --- a/tests/pass_through_unit_tests/test_pass_through_unit_tests.py +++ b/tests/pass_through_unit_tests/test_pass_through_unit_tests.py @@ -1,13 +1,8 @@ import json -import os -import sys from datetime import datetime from unittest.mock import AsyncMock, Mock, patch, MagicMock from typing import Optional -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import fastapi from fastapi import FastAPI diff --git a/tests/pass_through_unit_tests/test_passthrough_managed_ids.py b/tests/pass_through_unit_tests/test_passthrough_managed_ids.py index cbbf9257118..0fc0e0e751c 100644 --- a/tests/pass_through_unit_tests/test_passthrough_managed_ids.py +++ b/tests/pass_through_unit_tests/test_passthrough_managed_ids.py @@ -18,14 +18,11 @@ from __future__ import annotations import base64 import json -import sys -import os from typing import Any from unittest.mock import AsyncMock, MagicMock import pytest -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm.llms.base_llm.managed_resources.utils import ( diff --git a/tests/pass_through_unit_tests/test_unit_test_anthropic_pass_through.py b/tests/pass_through_unit_tests/test_unit_test_anthropic_pass_through.py index 5ab0319da47..8c59ce77451 100644 --- a/tests/pass_through_unit_tests/test_unit_test_anthropic_pass_through.py +++ b/tests/pass_through_unit_tests/test_unit_test_anthropic_pass_through.py @@ -1,12 +1,7 @@ import json -import os -import sys from datetime import datetime from unittest.mock import AsyncMock, Mock, patch -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import httpx diff --git a/tests/pass_through_unit_tests/test_unit_test_passthrough_router.py b/tests/pass_through_unit_tests/test_unit_test_passthrough_router.py index ee1f8772568..2b5bb6cf284 100644 --- a/tests/pass_through_unit_tests/test_unit_test_passthrough_router.py +++ b/tests/pass_through_unit_tests/test_unit_test_passthrough_router.py @@ -1,10 +1,8 @@ import json import os -import sys from datetime import datetime from unittest.mock import AsyncMock, Mock, patch, MagicMock -sys.path.insert(0, os.path.abspath("../..")) # import unittest from litellm.proxy.pass_through_endpoints.passthrough_endpoint_router import ( diff --git a/tests/pass_through_unit_tests/test_unit_test_streaming.py b/tests/pass_through_unit_tests/test_unit_test_streaming.py index ed98b720b37..376c9208aa1 100644 --- a/tests/pass_through_unit_tests/test_unit_test_streaming.py +++ b/tests/pass_through_unit_tests/test_unit_test_streaming.py @@ -1,12 +1,7 @@ import json -import os -import sys from datetime import datetime from unittest.mock import AsyncMock, Mock, patch, MagicMock -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import httpx import pytest diff --git a/tests/pass_through_unit_tests/test_vertex_ai_anthropic_streaming_cost_injection.py b/tests/pass_through_unit_tests/test_vertex_ai_anthropic_streaming_cost_injection.py index ac754aefaea..498f0a734a3 100644 --- a/tests/pass_through_unit_tests/test_vertex_ai_anthropic_streaming_cost_injection.py +++ b/tests/pass_through_unit_tests/test_vertex_ai_anthropic_streaming_cost_injection.py @@ -6,12 +6,9 @@ for Vertex AI streamRawPredict endpoints when include_cost_in_streaming_usage is """ import json -import os -import sys from datetime import datetime from unittest.mock import AsyncMock, MagicMock, patch -sys.path.insert(0, os.path.abspath("../..")) import httpx import pytest diff --git a/tests/pass_through_unit_tests/test_vertex_ai_live_passthrough.py b/tests/pass_through_unit_tests/test_vertex_ai_live_passthrough.py index f25d9e7c1d3..e2eb6d0b68b 100644 --- a/tests/pass_through_unit_tests/test_vertex_ai_live_passthrough.py +++ b/tests/pass_through_unit_tests/test_vertex_ai_live_passthrough.py @@ -6,8 +6,6 @@ including the logging handler, cost tracking, and WebSocket message processing. """ import json -import os -import sys from datetime import datetime from unittest.mock import AsyncMock, Mock, patch, MagicMock from typing import Dict, List, Any, Optional @@ -16,7 +14,6 @@ import pytest import httpx # Add the parent directory to the system path -sys.path.insert(0, os.path.abspath("../..")) from litellm.proxy.pass_through_endpoints.llm_provider_handlers.vertex_ai_live_passthrough_logging_handler import ( VertexAILivePassthroughLoggingHandler, diff --git a/tests/pass_through_unit_tests/test_websearch_interception_e2e.py b/tests/pass_through_unit_tests/test_websearch_interception_e2e.py index d4cf997ab58..091ea106b91 100644 --- a/tests/pass_through_unit_tests/test_websearch_interception_e2e.py +++ b/tests/pass_through_unit_tests/test_websearch_interception_e2e.py @@ -5,10 +5,8 @@ Makes actual calls to test WebSearch interception with Perplexity. Tests both streaming and non-streaming requests. """ -import os import sys -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm.integrations.websearch_interception import ( diff --git a/tests/proxy_admin_ui_tests/conftest.py b/tests/proxy_admin_ui_tests/conftest.py index 67365f4745d..93f00db8f79 100644 --- a/tests/proxy_admin_ui_tests/conftest.py +++ b/tests/proxy_admin_ui_tests/conftest.py @@ -2,13 +2,9 @@ import importlib import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm @@ -18,9 +14,6 @@ def setup_and_teardown(): This fixture reloads litellm before every function. To speed up testing by removing callbacks being chained. """ curr_dir = os.getcwd() # Get the current working directory - sys.path.insert( - 0, os.path.abspath("../..") - ) # Adds the project directory to the system path from litellm import Router diff --git a/tests/proxy_admin_ui_tests/test_access_group_team_sync.py b/tests/proxy_admin_ui_tests/test_access_group_team_sync.py index f7092d3ec00..b72a1453576 100644 --- a/tests/proxy_admin_ui_tests/test_access_group_team_sync.py +++ b/tests/proxy_admin_ui_tests/test_access_group_team_sync.py @@ -10,7 +10,6 @@ suite, which is the only place a `NOT (... = ANY(...))` guard going missing show import asyncio import os -import sys from contextlib import asynccontextmanager from datetime import timedelta from types import SimpleNamespace @@ -18,7 +17,6 @@ from unittest.mock import AsyncMock, patch import pytest -sys.path.insert(0, os.path.abspath("../..")) from litellm.proxy.management_helpers.access_group_team_sync import ( reconcile_team_access_group_membership, diff --git a/tests/proxy_admin_ui_tests/test_key_management.py b/tests/proxy_admin_ui_tests/test_key_management.py index 9fff120bba1..979ba31bffa 100644 --- a/tests/proxy_admin_ui_tests/test_key_management.py +++ b/tests/proxy_admin_ui_tests/test_key_management.py @@ -1,5 +1,4 @@ import os -import sys import traceback from litellm._uuid import uuid import datetime as dt @@ -16,9 +15,6 @@ import time # this file is to test litellm/proxy -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import asyncio import logging diff --git a/tests/proxy_admin_ui_tests/test_role_based_access.py b/tests/proxy_admin_ui_tests/test_role_based_access.py index 1c4ee2caa04..92e731b8c23 100644 --- a/tests/proxy_admin_ui_tests/test_role_based_access.py +++ b/tests/proxy_admin_ui_tests/test_role_based_access.py @@ -4,7 +4,6 @@ RBAC tests import os import re -import sys import traceback from litellm._uuid import uuid from datetime import datetime @@ -19,9 +18,6 @@ import time # this file is to test litellm/proxy -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import asyncio import logging from unittest.mock import MagicMock diff --git a/tests/proxy_admin_ui_tests/test_route_check_unit_tests.py b/tests/proxy_admin_ui_tests/test_route_check_unit_tests.py index 6396a92cf80..a31c0b923e3 100644 --- a/tests/proxy_admin_ui_tests/test_route_check_unit_tests.py +++ b/tests/proxy_admin_ui_tests/test_route_check_unit_tests.py @@ -1,5 +1,3 @@ -import os -import sys import traceback from litellm._uuid import uuid import datetime as dt @@ -16,9 +14,6 @@ import time # this file is to test litellm/proxy -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import asyncio import logging diff --git a/tests/proxy_admin_ui_tests/test_sso_sign_in.py b/tests/proxy_admin_ui_tests/test_sso_sign_in.py index 294a5c56199..dd618cf3836 100644 --- a/tests/proxy_admin_ui_tests/test_sso_sign_in.py +++ b/tests/proxy_admin_ui_tests/test_sso_sign_in.py @@ -3,18 +3,13 @@ from fastapi.testclient import TestClient from fastapi import Request, Header from unittest.mock import patch, MagicMock, AsyncMock -import sys import os -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm.proxy.proxy_server import app from litellm.proxy.utils import PrismaClient, ProxyLogging from litellm.proxy.management_endpoints.ui_sso import auth_callback from litellm.proxy._types import LitellmUserRoles -import os import jwt import time from litellm.caching.caching import DualCache diff --git a/tests/proxy_admin_ui_tests/test_usage_endpoints.py b/tests/proxy_admin_ui_tests/test_usage_endpoints.py index 0d1fa3afa0c..0831902c290 100644 --- a/tests/proxy_admin_ui_tests/test_usage_endpoints.py +++ b/tests/proxy_admin_ui_tests/test_usage_endpoints.py @@ -14,7 +14,6 @@ For all tests - test the following: """ import os -import sys import traceback from litellm._uuid import uuid from datetime import datetime @@ -29,9 +28,6 @@ import time # this file is to test litellm/proxy -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import asyncio import logging diff --git a/tests/proxy_unit_tests/conftest.py b/tests/proxy_unit_tests/conftest.py index a0326f64ed7..148751c33f2 100644 --- a/tests/proxy_unit_tests/conftest.py +++ b/tests/proxy_unit_tests/conftest.py @@ -3,15 +3,10 @@ import asyncio import copy import inspect -import os -import sys import warnings import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm import litellm.proxy.proxy_server diff --git a/tests/proxy_unit_tests/test_aproxy_startup.py b/tests/proxy_unit_tests/test_aproxy_startup.py index 324a881a7c3..98bf6ef8eb7 100644 --- a/tests/proxy_unit_tests/test_aproxy_startup.py +++ b/tests/proxy_unit_tests/test_aproxy_startup.py @@ -9,9 +9,6 @@ import io # this file is to test litellm/proxy -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import pytest, logging, asyncio import litellm from litellm.proxy.proxy_server import ( diff --git a/tests/proxy_unit_tests/test_audit_logs_proxy.py b/tests/proxy_unit_tests/test_audit_logs_proxy.py index a5332213886..878e19f5b6f 100644 --- a/tests/proxy_unit_tests/test_audit_logs_proxy.py +++ b/tests/proxy_unit_tests/test_audit_logs_proxy.py @@ -1,5 +1,4 @@ import os -import sys import traceback from litellm._uuid import uuid from datetime import datetime @@ -14,9 +13,6 @@ import time # this file is to test litellm/proxy -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import asyncio import logging diff --git a/tests/proxy_unit_tests/test_auth_checks.py b/tests/proxy_unit_tests/test_auth_checks.py index 3dc39969024..d436c99cd20 100644 --- a/tests/proxy_unit_tests/test_auth_checks.py +++ b/tests/proxy_unit_tests/test_auth_checks.py @@ -7,9 +7,6 @@ from dotenv import load_dotenv load_dotenv() -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import pytest, litellm import httpx from litellm.proxy._types import UserAPIKeyAuth diff --git a/tests/proxy_unit_tests/test_banned_keyword_list.py b/tests/proxy_unit_tests/test_banned_keyword_list.py index acf4bdbb8e0..35e625a6b9e 100644 --- a/tests/proxy_unit_tests/test_banned_keyword_list.py +++ b/tests/proxy_unit_tests/test_banned_keyword_list.py @@ -9,9 +9,6 @@ from dotenv import load_dotenv load_dotenv() -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import pytest import litellm from litellm.proxy.enterprise.enterprise_hooks.banned_keywords import ( diff --git a/tests/proxy_unit_tests/test_custom_callback_input.py b/tests/proxy_unit_tests/test_custom_callback_input.py index a032b8706bc..8b7a8a8973b 100644 --- a/tests/proxy_unit_tests/test_custom_callback_input.py +++ b/tests/proxy_unit_tests/test_custom_callback_input.py @@ -3,8 +3,6 @@ import asyncio import inspect import json -import os -import sys import time import traceback from litellm._uuid import uuid @@ -13,7 +11,6 @@ from datetime import datetime import pytest from pydantic import BaseModel -sys.path.insert(0, os.path.abspath("../..")) from typing import List, Literal, Optional, Union from unittest.mock import AsyncMock, MagicMock, patch diff --git a/tests/proxy_unit_tests/test_default_end_user_budget_simple.py b/tests/proxy_unit_tests/test_default_end_user_budget_simple.py index 6170b0a972e..edd0409343a 100644 --- a/tests/proxy_unit_tests/test_default_end_user_budget_simple.py +++ b/tests/proxy_unit_tests/test_default_end_user_budget_simple.py @@ -5,14 +5,11 @@ Tests the core scenarios where litellm.max_end_user_budget_id applies a default budget to end users without explicit budgets. """ -import sys -import os import uuid from unittest.mock import AsyncMock, MagicMock, patch import pytest -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm.proxy._types import LiteLLM_BudgetTable, LiteLLM_EndUserTable diff --git a/tests/proxy_unit_tests/test_e2e_pod_lock_manager.py b/tests/proxy_unit_tests/test_e2e_pod_lock_manager.py index b1e5fd29cde..6fac731a60d 100644 --- a/tests/proxy_unit_tests/test_e2e_pod_lock_manager.py +++ b/tests/proxy_unit_tests/test_e2e_pod_lock_manager.py @@ -1,5 +1,4 @@ import os -import sys import traceback from litellm._uuid import uuid from typing import List @@ -19,9 +18,6 @@ import fakeredis # this file is to test litellm/proxy -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import asyncio import logging diff --git a/tests/proxy_unit_tests/test_gemini_agents_endpoints.py b/tests/proxy_unit_tests/test_gemini_agents_endpoints.py index bdac9348f71..cddb0e526b4 100644 --- a/tests/proxy_unit_tests/test_gemini_agents_endpoints.py +++ b/tests/proxy_unit_tests/test_gemini_agents_endpoints.py @@ -9,15 +9,12 @@ longer accepted — they would appear in server logs. """ import json -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import pytest from fastapi import Request from fastapi.datastructures import Headers, QueryParams -sys.path.insert(0, os.path.abspath("../..")) from litellm.proxy.google_endpoints.agents_endpoints import ( _merge_query_params_into_data, diff --git a/tests/proxy_unit_tests/test_get_favicon.py b/tests/proxy_unit_tests/test_get_favicon.py index ddc8b1230a7..ad18bc90a1e 100644 --- a/tests/proxy_unit_tests/test_get_favicon.py +++ b/tests/proxy_unit_tests/test_get_favicon.py @@ -1,7 +1,5 @@ import os -import sys -sys.path.insert(0, os.path.abspath("../..")) import httpx import pytest diff --git a/tests/proxy_unit_tests/test_get_image.py b/tests/proxy_unit_tests/test_get_image.py index 57e472f86c4..9b7f3da8a7b 100644 --- a/tests/proxy_unit_tests/test_get_image.py +++ b/tests/proxy_unit_tests/test_get_image.py @@ -1,9 +1,6 @@ -import os -import sys from unittest import mock # Standard path insertion -sys.path.insert(0, os.path.abspath("../..")) import httpx import pytest diff --git a/tests/proxy_unit_tests/test_google_endpoint_routing.py b/tests/proxy_unit_tests/test_google_endpoint_routing.py index b978077c730..3dcfede92ea 100644 --- a/tests/proxy_unit_tests/test_google_endpoint_routing.py +++ b/tests/proxy_unit_tests/test_google_endpoint_routing.py @@ -1,12 +1,10 @@ import json import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import pytest import yaml -sys.path.insert(0, os.path.abspath("../..")) from litellm.proxy._types import UserAPIKeyAuth from litellm.proxy.google_endpoints.endpoints import google_generate_content diff --git a/tests/proxy_unit_tests/test_google_gemini_proxy_request.py b/tests/proxy_unit_tests/test_google_gemini_proxy_request.py index dbe30037313..6f8f90efc73 100644 --- a/tests/proxy_unit_tests/test_google_gemini_proxy_request.py +++ b/tests/proxy_unit_tests/test_google_gemini_proxy_request.py @@ -8,8 +8,6 @@ The request payload is correctly processed and forwarded to the httpx client. """ import json -import os -import sys import unittest.mock from typing import Optional from unittest.mock import AsyncMock, MagicMock, patch @@ -18,7 +16,6 @@ import httpx import pytest # Add the parent directory to the system path -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm.proxy._types import UserAPIKeyAuth diff --git a/tests/proxy_unit_tests/test_jwt.py b/tests/proxy_unit_tests/test_jwt.py index abd91113f96..6ad253f33e8 100644 --- a/tests/proxy_unit_tests/test_jwt.py +++ b/tests/proxy_unit_tests/test_jwt.py @@ -6,7 +6,6 @@ import base64 import logging import os import random -import sys import time import traceback from litellm._uuid import uuid @@ -15,9 +14,6 @@ from dotenv import load_dotenv load_dotenv() -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path from datetime import datetime, timedelta from unittest.mock import AsyncMock, MagicMock, patch diff --git a/tests/proxy_unit_tests/test_key_generate_prisma.py b/tests/proxy_unit_tests/test_key_generate_prisma.py index efedc156429..a3deeb46f6e 100644 --- a/tests/proxy_unit_tests/test_key_generate_prisma.py +++ b/tests/proxy_unit_tests/test_key_generate_prisma.py @@ -21,7 +21,6 @@ import os import re -import sys import traceback from litellm._uuid import uuid from datetime import datetime, timezone @@ -38,9 +37,6 @@ import time # this file is to test litellm/proxy -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import asyncio import logging diff --git a/tests/proxy_unit_tests/test_prisma_client_backoff_retry.py b/tests/proxy_unit_tests/test_prisma_client_backoff_retry.py index b49bef3632d..8fe1c68da59 100644 --- a/tests/proxy_unit_tests/test_prisma_client_backoff_retry.py +++ b/tests/proxy_unit_tests/test_prisma_client_backoff_retry.py @@ -11,10 +11,8 @@ import time from unittest.mock import AsyncMock, MagicMock, patch, call from unittest.mock import Mock import sys -import os # Add project root to path -sys.path.insert(0, os.path.abspath("../..")) from litellm.proxy.utils import PrismaClient, ProxyLogging from prisma.errors import PrismaError, ClientNotConnectedError diff --git a/tests/proxy_unit_tests/test_proxy_config_unit_test.py b/tests/proxy_unit_tests/test_proxy_config_unit_test.py index a567ad2b025..81648dc1158 100644 --- a/tests/proxy_unit_tests/test_proxy_config_unit_test.py +++ b/tests/proxy_unit_tests/test_proxy_config_unit_test.py @@ -1,5 +1,4 @@ import os -import sys import traceback from unittest import mock import pytest @@ -14,7 +13,6 @@ import io # this file is to test litellm/proxy -sys.path.insert(0, os.path.abspath("../..")) # Adds the parent directory to the system path import asyncio import logging diff --git a/tests/proxy_unit_tests/test_proxy_custom_auth.py b/tests/proxy_unit_tests/test_proxy_custom_auth.py index 0582cacb42d..b575e4c85c6 100644 --- a/tests/proxy_unit_tests/test_proxy_custom_auth.py +++ b/tests/proxy_unit_tests/test_proxy_custom_auth.py @@ -1,5 +1,4 @@ import os -import sys import traceback from dotenv import load_dotenv @@ -9,9 +8,6 @@ import io # this file is to test litellm/proxy -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import asyncio import pytest diff --git a/tests/proxy_unit_tests/test_proxy_custom_logger.py b/tests/proxy_unit_tests/test_proxy_custom_logger.py index 20b9678c7fa..2516df2d58d 100644 --- a/tests/proxy_unit_tests/test_proxy_custom_logger.py +++ b/tests/proxy_unit_tests/test_proxy_custom_logger.py @@ -7,9 +7,6 @@ import io, asyncio # this file is to test litellm/proxy -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import pytest, time import litellm from litellm import embedding, completion, completion_cost, Timeout diff --git a/tests/proxy_unit_tests/test_proxy_encrypt_decrypt.py b/tests/proxy_unit_tests/test_proxy_encrypt_decrypt.py index 396a34e9b85..88ee64b6c4b 100644 --- a/tests/proxy_unit_tests/test_proxy_encrypt_decrypt.py +++ b/tests/proxy_unit_tests/test_proxy_encrypt_decrypt.py @@ -1,5 +1,4 @@ import os -import sys import pytest from dotenv import load_dotenv @@ -7,9 +6,6 @@ from dotenv import load_dotenv load_dotenv() import io -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds-the parent directory to the system path from litellm.proxy import proxy_server from litellm.proxy.common_utils.encrypt_decrypt_utils import ( diff --git a/tests/proxy_unit_tests/test_proxy_exception_mapping.py b/tests/proxy_unit_tests/test_proxy_exception_mapping.py index e9884f8b269..efaaa181600 100644 --- a/tests/proxy_unit_tests/test_proxy_exception_mapping.py +++ b/tests/proxy_unit_tests/test_proxy_exception_mapping.py @@ -2,7 +2,6 @@ import json import os -import sys from unittest import mock from dotenv import load_dotenv @@ -11,9 +10,6 @@ load_dotenv() import asyncio import io -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import openai import pytest from fastapi import Response diff --git a/tests/proxy_unit_tests/test_proxy_pass_user_config.py b/tests/proxy_unit_tests/test_proxy_pass_user_config.py index 73998253f32..91911c142ea 100644 --- a/tests/proxy_unit_tests/test_proxy_pass_user_config.py +++ b/tests/proxy_unit_tests/test_proxy_pass_user_config.py @@ -7,9 +7,6 @@ import io # this file is to test litellm/proxy -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import pytest, logging, asyncio import litellm from litellm import embedding, completion, completion_cost, Timeout @@ -24,7 +21,6 @@ logging.basicConfig( # test /chat/completion request to the proxy from fastapi.testclient import TestClient from fastapi import FastAPI -import os from litellm.proxy.proxy_server import ( router, save_worker_config, diff --git a/tests/proxy_unit_tests/test_proxy_reject_logging.py b/tests/proxy_unit_tests/test_proxy_reject_logging.py index 440f2362276..eb5c5a52f0a 100644 --- a/tests/proxy_unit_tests/test_proxy_reject_logging.py +++ b/tests/proxy_unit_tests/test_proxy_reject_logging.py @@ -5,12 +5,10 @@ ## This tests the llm guard integration import asyncio -import os import random # What is this? ## Unit test for presidio pii masking -import sys import time import traceback from datetime import datetime @@ -19,9 +17,6 @@ from dotenv import load_dotenv load_dotenv() -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path from typing import Literal import pytest diff --git a/tests/proxy_unit_tests/test_proxy_routes.py b/tests/proxy_unit_tests/test_proxy_routes.py index 9d9c02257c2..129a93ea08d 100644 --- a/tests/proxy_unit_tests/test_proxy_routes.py +++ b/tests/proxy_unit_tests/test_proxy_routes.py @@ -1,5 +1,3 @@ -import os -import sys from dotenv import load_dotenv @@ -8,9 +6,6 @@ import io # this file is to test litellm/proxy -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import asyncio import logging diff --git a/tests/proxy_unit_tests/test_proxy_server.py b/tests/proxy_unit_tests/test_proxy_server.py index bb8127a8b91..21dbf3e090f 100644 --- a/tests/proxy_unit_tests/test_proxy_server.py +++ b/tests/proxy_unit_tests/test_proxy_server.py @@ -1,5 +1,4 @@ import os -import sys import traceback from unittest import mock @@ -14,9 +13,6 @@ import json # this file is to test litellm/proxy -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import asyncio import logging diff --git a/tests/proxy_unit_tests/test_proxy_setting_guardrails.py b/tests/proxy_unit_tests/test_proxy_setting_guardrails.py index d16546249a4..71b7783f5ee 100644 --- a/tests/proxy_unit_tests/test_proxy_setting_guardrails.py +++ b/tests/proxy_unit_tests/test_proxy_setting_guardrails.py @@ -1,6 +1,5 @@ import json import os -import sys from unittest import mock from dotenv import load_dotenv @@ -9,9 +8,6 @@ load_dotenv() import asyncio import io -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import openai import pytest from fastapi import Response diff --git a/tests/proxy_unit_tests/test_proxy_token_counter.py b/tests/proxy_unit_tests/test_proxy_token_counter.py index 1079a5228a1..39ec4bb1887 100644 --- a/tests/proxy_unit_tests/test_proxy_token_counter.py +++ b/tests/proxy_unit_tests/test_proxy_token_counter.py @@ -5,7 +5,6 @@ import json import logging import os -import sys import tempfile from unittest.mock import AsyncMock, MagicMock, patch @@ -17,9 +16,6 @@ load_dotenv() # this file is to test litellm/proxy -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path from fastapi import HTTPException, Request diff --git a/tests/proxy_unit_tests/test_proxy_utils.py b/tests/proxy_unit_tests/test_proxy_utils.py index de2a9282300..3bde72ccd49 100644 --- a/tests/proxy_unit_tests/test_proxy_utils.py +++ b/tests/proxy_unit_tests/test_proxy_utils.py @@ -1,7 +1,6 @@ import asyncio import json import os -import sys from datetime import datetime from typing import Any, Dict, List, Optional, Union from unittest.mock import Mock @@ -14,9 +13,6 @@ from litellm.integrations.custom_guardrail import CustomGuardrail from litellm.proxy.utils import _get_docs_url, _get_openapi_url, _get_redoc_url from litellm.types.guardrails import GuardrailEventHooks -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path from unittest.mock import AsyncMock, MagicMock, patch import litellm diff --git a/tests/proxy_unit_tests/test_response_polling_handler.py b/tests/proxy_unit_tests/test_response_polling_handler.py index 8d9c7a6a095..772d3622745 100644 --- a/tests/proxy_unit_tests/test_response_polling_handler.py +++ b/tests/proxy_unit_tests/test_response_polling_handler.py @@ -15,15 +15,12 @@ following the OpenAI Response API format. """ import json -import os -import sys from datetime import datetime, timezone from typing import Any, Dict, Optional from unittest.mock import AsyncMock, Mock, patch import pytest -sys.path.insert(0, os.path.abspath("../..")) from litellm.proxy.response_polling.polling_handler import ResponsePollingHandler diff --git a/tests/proxy_unit_tests/test_response_polling_pre_call_checks.py b/tests/proxy_unit_tests/test_response_polling_pre_call_checks.py index fe411b1d858..459834d0fd2 100644 --- a/tests/proxy_unit_tests/test_response_polling_pre_call_checks.py +++ b/tests/proxy_unit_tests/test_response_polling_pre_call_checks.py @@ -6,14 +6,11 @@ BEFORE a polling ID is created, so rate-limited requests get a synchronous error instead of a polling ID that immediately fails. """ -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import pytest from fastapi import HTTPException, Request, Response -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm.proxy._types import UserAPIKeyAuth diff --git a/tests/proxy_unit_tests/test_search_api_logging.py b/tests/proxy_unit_tests/test_search_api_logging.py index 71bbe5351a2..5a833d37615 100644 --- a/tests/proxy_unit_tests/test_search_api_logging.py +++ b/tests/proxy_unit_tests/test_search_api_logging.py @@ -8,14 +8,12 @@ model_group, spend, etc.) import asyncio import os -import sys import time from datetime import datetime from unittest.mock import AsyncMock, patch import pytest -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm import Router from litellm.caching import DualCache diff --git a/tests/proxy_unit_tests/test_skills_db.py b/tests/proxy_unit_tests/test_skills_db.py index 9548e78d6ed..8eb07a5ad48 100644 --- a/tests/proxy_unit_tests/test_skills_db.py +++ b/tests/proxy_unit_tests/test_skills_db.py @@ -10,7 +10,6 @@ Tests the SDK-level skills methods when using the LiteLLM database backend: """ import os -import sys import zipfile from contextlib import contextmanager from io import BytesIO @@ -18,7 +17,6 @@ from pathlib import Path import pytest -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm.caching.caching import DualCache diff --git a/tests/proxy_unit_tests/test_unit_test_max_model_budget_limiter.py b/tests/proxy_unit_tests/test_unit_test_max_model_budget_limiter.py index 8b5e6c5497b..3785ccdcfba 100644 --- a/tests/proxy_unit_tests/test_unit_test_max_model_budget_limiter.py +++ b/tests/proxy_unit_tests/test_unit_test_max_model_budget_limiter.py @@ -1,8 +1,5 @@ -import os -import sys from unittest.mock import AsyncMock, patch -sys.path.insert(0, os.path.abspath("../..")) # Adds the parent directory to the system-path import pytest diff --git a/tests/proxy_unit_tests/test_unit_test_proxy_hooks.py b/tests/proxy_unit_tests/test_unit_test_proxy_hooks.py index 492b4803af4..e6ffea35e52 100644 --- a/tests/proxy_unit_tests/test_unit_test_proxy_hooks.py +++ b/tests/proxy_unit_tests/test_unit_test_proxy_hooks.py @@ -1,13 +1,10 @@ import asyncio -import os -import sys from unittest.mock import Mock, patch, AsyncMock import pytest from fastapi import Request from litellm.proxy.utils import _get_redoc_url, _get_docs_url from datetime import datetime -sys.path.insert(0, os.path.abspath("../..")) import litellm diff --git a/tests/proxy_unit_tests/test_update_spend.py b/tests/proxy_unit_tests/test_update_spend.py index 2df381c8190..a28a78cc4a1 100644 --- a/tests/proxy_unit_tests/test_update_spend.py +++ b/tests/proxy_unit_tests/test_update_spend.py @@ -1,15 +1,10 @@ import asyncio -import os -import sys from unittest.mock import Mock from litellm.proxy.utils import _get_redoc_url, _get_docs_url import pytest from fastapi import Request -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from unittest.mock import MagicMock, patch, AsyncMock diff --git a/tests/proxy_unit_tests/test_user_api_key_auth.py b/tests/proxy_unit_tests/test_user_api_key_auth.py index 49ec29d3ac5..cc7de71aa56 100644 --- a/tests/proxy_unit_tests/test_user_api_key_auth.py +++ b/tests/proxy_unit_tests/test_user_api_key_auth.py @@ -1,13 +1,10 @@ # What is this? ## Unit tests for user_api_key_auth helper functions -import os -import sys import litellm.proxy import litellm.proxy.proxy_server -sys.path.insert(0, os.path.abspath("../..")) # Adds the parent directory to the system path from typing import Dict, List, Optional from unittest.mock import MagicMock, patch, AsyncMock diff --git a/tests/router_unit_tests/conftest.py b/tests/router_unit_tests/conftest.py index db6a722a926..cca1028aec7 100644 --- a/tests/router_unit_tests/conftest.py +++ b/tests/router_unit_tests/conftest.py @@ -2,14 +2,9 @@ import asyncio import importlib -import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm # noqa: E402,F401 from tests._vcr_conftest_common import ( # noqa: E402,F401 @@ -44,9 +39,6 @@ def setup_and_teardown(): """ This fixture reloads litellm before every function. To speed up testing by removing callbacks being chained. """ - sys.path.insert( - 0, os.path.abspath("../..") - ) # Adds the project directory to the system path from litellm.litellm_core_utils.logging_worker import GLOBAL_LOGGING_WORKER @@ -58,8 +50,6 @@ def setup_and_teardown(): try: if hasattr(litellm, "proxy") and hasattr(litellm.proxy, "proxy_server"): - import litellm.proxy.proxy_server - importlib.reload(litellm.proxy.proxy_server) except Exception as e: print(f"Error reloading litellm.proxy.proxy_server: {e}") diff --git a/tests/router_unit_tests/create_mock_standard_logging_payload.py b/tests/router_unit_tests/create_mock_standard_logging_payload.py index 106328e95e2..096c8ff8c60 100644 --- a/tests/router_unit_tests/create_mock_standard_logging_payload.py +++ b/tests/router_unit_tests/create_mock_standard_logging_payload.py @@ -1,9 +1,6 @@ import io -import os -import sys -sys.path.insert(0, os.path.abspath("../..")) import asyncio import gzip diff --git a/tests/router_unit_tests/test_completion_no_copy.py b/tests/router_unit_tests/test_completion_no_copy.py index 28f40779496..ef157d3b903 100644 --- a/tests/router_unit_tests/test_completion_no_copy.py +++ b/tests/router_unit_tests/test_completion_no_copy.py @@ -5,11 +5,8 @@ Verifies that spreading deployment["litellm_params"] directly (without copy) doesn't cause side effects that mutate the deployment in router.model_list. """ -import sys -import os import pytest -sys.path.insert(0, os.path.abspath("../..")) from litellm import Router from unittest.mock import AsyncMock, Mock, patch diff --git a/tests/router_unit_tests/test_default_deployment_copy.py b/tests/router_unit_tests/test_default_deployment_copy.py index 90401479308..3cb9c3683d6 100644 --- a/tests/router_unit_tests/test_default_deployment_copy.py +++ b/tests/router_unit_tests/test_default_deployment_copy.py @@ -5,10 +5,7 @@ Tests the critical side effect: ensure modifying returned deployment doesn't corrupt the original default_deployment instance. """ -import sys -import os -sys.path.insert(0, os.path.abspath("../..")) from litellm import Router diff --git a/tests/router_unit_tests/test_prompt_management_check.py b/tests/router_unit_tests/test_prompt_management_check.py index 81c6c6f0138..313ba2c3340 100644 --- a/tests/router_unit_tests/test_prompt_management_check.py +++ b/tests/router_unit_tests/test_prompt_management_check.py @@ -5,10 +5,7 @@ Verifies that the early return for models without "/" doesn't break prompt management model detection. """ -import sys -import os -sys.path.insert(0, os.path.abspath("../..")) from litellm import Router diff --git a/tests/router_unit_tests/test_router_acancel_batch.py b/tests/router_unit_tests/test_router_acancel_batch.py index 016da592e94..c15658d5d14 100644 --- a/tests/router_unit_tests/test_router_acancel_batch.py +++ b/tests/router_unit_tests/test_router_acancel_batch.py @@ -4,10 +4,7 @@ Test router.acancel_batch() functionality This ensures the router's batch cancellation method has test coverage. """ -import sys -import os -sys.path.insert(0, os.path.abspath("../..")) import pytest from unittest.mock import patch, AsyncMock, MagicMock diff --git a/tests/router_unit_tests/test_router_adding_deployments.py b/tests/router_unit_tests/test_router_adding_deployments.py index 6200cc6ebcc..dfbaf1257c6 100644 --- a/tests/router_unit_tests/test_router_adding_deployments.py +++ b/tests/router_unit_tests/test_router_adding_deployments.py @@ -1,9 +1,6 @@ import sys, os import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path from litellm import Router from litellm.router import Deployment, LiteLLM_Params from unittest.mock import patch diff --git a/tests/router_unit_tests/test_router_aresponses_streaming_fallback.py b/tests/router_unit_tests/test_router_aresponses_streaming_fallback.py index 17124a94a8f..ee4750e9db8 100644 --- a/tests/router_unit_tests/test_router_aresponses_streaming_fallback.py +++ b/tests/router_unit_tests/test_router_aresponses_streaming_fallback.py @@ -10,14 +10,11 @@ Targets the four helpers introduced on Router: - _aresponses_streaming_iterator """ -import os -import sys from typing import Any, AsyncIterator, List from unittest.mock import AsyncMock, MagicMock, patch import pytest -sys.path.insert(0, os.path.abspath("../..")) from litellm import Router from litellm.types.llms.openai import ( diff --git a/tests/router_unit_tests/test_router_batch_utils.py b/tests/router_unit_tests/test_router_batch_utils.py index b8760906645..c9f19731372 100644 --- a/tests/router_unit_tests/test_router_batch_utils.py +++ b/tests/router_unit_tests/test_router_batch_utils.py @@ -1,9 +1,4 @@ -import sys -import os -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import pytest import json diff --git a/tests/router_unit_tests/test_router_cooldown_utils.py b/tests/router_unit_tests/test_router_cooldown_utils.py index a51b0dc21af..242709708e3 100644 --- a/tests/router_unit_tests/test_router_cooldown_utils.py +++ b/tests/router_unit_tests/test_router_cooldown_utils.py @@ -2,9 +2,6 @@ import sys, os, time import traceback, asyncio import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm import Router from litellm.router import Deployment, LiteLLM_Params diff --git a/tests/router_unit_tests/test_router_embedding_headers.py b/tests/router_unit_tests/test_router_embedding_headers.py index 5bf98243dcc..738f09e6ece 100644 --- a/tests/router_unit_tests/test_router_embedding_headers.py +++ b/tests/router_unit_tests/test_router_embedding_headers.py @@ -9,13 +9,10 @@ just like router.completion() does, which properly sets up metadata and allows default_litellm_params (including headers) to be propagated. """ -import os -import sys from unittest.mock import MagicMock, patch, AsyncMock import pytest -sys.path.insert(0, os.path.abspath("../..")) from litellm import Router diff --git a/tests/router_unit_tests/test_router_embedding_integration.py b/tests/router_unit_tests/test_router_embedding_integration.py index 6f5781336eb..75dacbaf08e 100644 --- a/tests/router_unit_tests/test_router_embedding_integration.py +++ b/tests/router_unit_tests/test_router_embedding_integration.py @@ -5,13 +5,10 @@ These tests simulate real-world scenarios where headers and configuration need to be properly propagated through the router to the LLM API. """ -import os -import sys from unittest.mock import MagicMock, patch, AsyncMock import pytest -sys.path.insert(0, os.path.abspath("../..")) from litellm import Router diff --git a/tests/router_unit_tests/test_router_endpoints.py b/tests/router_unit_tests/test_router_endpoints.py index 658ad4f3b5c..d37af5b456a 100644 --- a/tests/router_unit_tests/test_router_endpoints.py +++ b/tests/router_unit_tests/test_router_endpoints.py @@ -1,4 +1,3 @@ -import sys import os import json import traceback @@ -8,9 +7,6 @@ from fastapi import Request from datetime import datetime from unittest.mock import AsyncMock, patch, MagicMock -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path from litellm import Router, CustomLogger from litellm.types.utils import StandardLoggingPayload diff --git a/tests/router_unit_tests/test_router_handle_error.py b/tests/router_unit_tests/test_router_handle_error.py index a84c90ccb78..6b57efc7f37 100644 --- a/tests/router_unit_tests/test_router_handle_error.py +++ b/tests/router_unit_tests/test_router_handle_error.py @@ -3,9 +3,6 @@ import traceback, asyncio import pytest from typing import List -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm import Router from litellm.router import Deployment, LiteLLM_Params diff --git a/tests/router_unit_tests/test_router_helper_utils.py b/tests/router_unit_tests/test_router_helper_utils.py index 82bdbd7bfc9..dcd2e9edf7b 100644 --- a/tests/router_unit_tests/test_router_helper_utils.py +++ b/tests/router_unit_tests/test_router_helper_utils.py @@ -1,13 +1,9 @@ -import sys import os import traceback from dotenv import load_dotenv from fastapi import Request from datetime import datetime -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path from litellm import Router import pytest import litellm diff --git a/tests/router_unit_tests/test_router_index_management.py b/tests/router_unit_tests/test_router_index_management.py index 3f0a185e8bf..87ddaadaf3d 100644 --- a/tests/router_unit_tests/test_router_index_management.py +++ b/tests/router_unit_tests/test_router_index_management.py @@ -1,11 +1,7 @@ -import sys import os import pytest import ast -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path from litellm import Router diff --git a/tests/router_unit_tests/test_router_prompt_caching.py b/tests/router_unit_tests/test_router_prompt_caching.py index 574eccda162..5c36c30e818 100644 --- a/tests/router_unit_tests/test_router_prompt_caching.py +++ b/tests/router_unit_tests/test_router_prompt_caching.py @@ -1,14 +1,9 @@ -import sys -import os import traceback import asyncio from dotenv import load_dotenv from fastapi import Request from datetime import datetime -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path from litellm import Router import pytest import litellm diff --git a/tests/search_tests/conftest.py b/tests/search_tests/conftest.py index 78ba19a7724..deef6527a8f 100644 --- a/tests/search_tests/conftest.py +++ b/tests/search_tests/conftest.py @@ -6,12 +6,9 @@ # are replayed for 24h. See tests/llm_translation/Readme.md for the # design overview. -import os -import sys import pytest -sys.path.insert(0, os.path.abspath("../..")) from tests._vcr_conftest_common import ( # noqa: E402,F401 VerboseReporterState, diff --git a/tests/search_tests/test_duckduckgo_search.py b/tests/search_tests/test_duckduckgo_search.py index 635e26e1c0c..69d19edded7 100644 --- a/tests/search_tests/test_duckduckgo_search.py +++ b/tests/search_tests/test_duckduckgo_search.py @@ -3,11 +3,9 @@ Tests for DuckDuckGo Search API integration. """ import os -import sys import pytest from unittest.mock import AsyncMock, patch, MagicMock -sys.path.insert(0, os.path.abspath("../..")) import litellm from tests.search_tests.base_search_unit_tests import BaseSearchTest diff --git a/tests/search_tests/test_google_pse_search.py b/tests/search_tests/test_google_pse_search.py index 21d58a95491..12b1a714709 100644 --- a/tests/search_tests/test_google_pse_search.py +++ b/tests/search_tests/test_google_pse_search.py @@ -2,11 +2,8 @@ Tests for Google Programmable Search Engine (PSE) API integration. """ -import os -import sys import pytest -sys.path.insert(0, os.path.abspath("../..")) from tests.search_tests.base_search_unit_tests import BaseSearchTest diff --git a/tests/search_tests/test_linkup_search.py b/tests/search_tests/test_linkup_search.py index 5e1fe4ddd9b..ab9bffc5633 100644 --- a/tests/search_tests/test_linkup_search.py +++ b/tests/search_tests/test_linkup_search.py @@ -3,11 +3,9 @@ Tests for Linkup Search API integration. """ import os -import sys import pytest from unittest.mock import Mock, patch -sys.path.insert(0, os.path.abspath("../..")) import litellm from tests.search_tests.base_search_unit_tests import BaseSearchTest diff --git a/tests/search_tests/test_nimble_search.py b/tests/search_tests/test_nimble_search.py index c83b7236a09..df432f8ae84 100644 --- a/tests/search_tests/test_nimble_search.py +++ b/tests/search_tests/test_nimble_search.py @@ -3,13 +3,10 @@ Tests for Nimble Search API integration. """ import json -import os -import sys from unittest.mock import AsyncMock, Mock, patch import pytest -sys.path.insert(0, os.path.abspath("../..")) import litellm from tests.search_tests.base_search_unit_tests import BaseSearchTest diff --git a/tests/search_tests/test_perplexity_search.py b/tests/search_tests/test_perplexity_search.py index c9e09ed404e..e1189a71355 100644 --- a/tests/search_tests/test_perplexity_search.py +++ b/tests/search_tests/test_perplexity_search.py @@ -3,10 +3,8 @@ Tests for Perplexity Search API integration. """ import os -import sys import pytest -sys.path.insert(0, os.path.abspath("../..")) from tests.search_tests.base_search_unit_tests import BaseSearchTest diff --git a/tests/search_tests/test_search_tool_name_filtering.py b/tests/search_tests/test_search_tool_name_filtering.py index 5424582a90c..902e95c7a4b 100644 --- a/tests/search_tests/test_search_tool_name_filtering.py +++ b/tests/search_tests/test_search_tool_name_filtering.py @@ -6,10 +6,7 @@ which search tool configuration to use, but should not be sent to external search provider APIs. """ -import sys -import os -sys.path.insert(0, os.path.abspath("../..")) from litellm.types.utils import all_litellm_params from litellm.utils import filter_out_litellm_params diff --git a/tests/search_tests/test_searchapi_search.py b/tests/search_tests/test_searchapi_search.py index d16868502a4..58ba6aa018a 100644 --- a/tests/search_tests/test_searchapi_search.py +++ b/tests/search_tests/test_searchapi_search.py @@ -10,13 +10,11 @@ Tests the SearchAPI.io search provider implementation including: import json import os -import sys from unittest.mock import MagicMock, Mock, patch import httpx import pytest -sys.path.insert(0, os.path.abspath("../..")) from litellm.llms.searchapi.search.transformation import SearchAPIConfig from litellm.llms.base_llm.search.transformation import SearchResponse, SearchResult diff --git a/tests/search_tests/test_serper_search.py b/tests/search_tests/test_serper_search.py index 99aae0f64e6..02e9d734443 100644 --- a/tests/search_tests/test_serper_search.py +++ b/tests/search_tests/test_serper_search.py @@ -3,11 +3,9 @@ Tests for Serper Search API integration. """ import os -import sys import pytest from unittest.mock import AsyncMock, patch, MagicMock -sys.path.insert(0, os.path.abspath("../..")) import litellm diff --git a/tests/search_tests/test_tavily_search.py b/tests/search_tests/test_tavily_search.py index a737685916c..4a5338deadb 100644 --- a/tests/search_tests/test_tavily_search.py +++ b/tests/search_tests/test_tavily_search.py @@ -3,11 +3,9 @@ Tests for Tavily Search API integration. """ import os -import sys import pytest from unittest.mock import AsyncMock, patch, MagicMock -sys.path.insert(0, os.path.abspath("../..")) import litellm diff --git a/tests/test_keys.py b/tests/test_keys.py index 2d8ff2232a1..e39c715de03 100644 --- a/tests/test_keys.py +++ b/tests/test_keys.py @@ -8,9 +8,6 @@ from openai import AsyncOpenAI import sys, os from typing import Optional -sys.path.insert( - 0, os.path.abspath("../") -) # Adds the parent directory to the system path import litellm from litellm.proxy._types import LitellmUserRoles diff --git a/tests/test_litellm/a2a_protocol/providers/pydantic_ai_agents/test_pydantic_ai_agent_transformation.py b/tests/test_litellm/a2a_protocol/providers/pydantic_ai_agents/test_pydantic_ai_agent_transformation.py index 717a7c902b5..c5626afa954 100644 --- a/tests/test_litellm/a2a_protocol/providers/pydantic_ai_agents/test_pydantic_ai_agent_transformation.py +++ b/tests/test_litellm/a2a_protocol/providers/pydantic_ai_agents/test_pydantic_ai_agent_transformation.py @@ -4,12 +4,9 @@ Tests for Pydantic AI agents transformation. Tests the helper functions and response transformation without making real API calls. """ -import os -import sys import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm.a2a_protocol.providers.pydantic_ai_agents.transformation import ( PydanticAITransformation, diff --git a/tests/test_litellm/a2a_protocol/providers/watsonx_orchestrate/test_watsonx_orchestrate_transformation.py b/tests/test_litellm/a2a_protocol/providers/watsonx_orchestrate/test_watsonx_orchestrate_transformation.py index 7968eed4146..43dfdaba02d 100644 --- a/tests/test_litellm/a2a_protocol/providers/watsonx_orchestrate/test_watsonx_orchestrate_transformation.py +++ b/tests/test_litellm/a2a_protocol/providers/watsonx_orchestrate/test_watsonx_orchestrate_transformation.py @@ -1,14 +1,11 @@ import asyncio import json -import os -import sys import time from pathlib import Path import httpx import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm.a2a_protocol.providers.config_manager import A2AProviderConfigManager from litellm.a2a_protocol.providers.watsonx_orchestrate import handler as wxo_handler diff --git a/tests/test_litellm/batches/test_batch_utils.py b/tests/test_litellm/batches/test_batch_utils.py index 08cdf945b80..41b4bb8cf76 100644 --- a/tests/test_litellm/batches/test_batch_utils.py +++ b/tests/test_litellm/batches/test_batch_utils.py @@ -16,15 +16,12 @@ deterministic stand-ins so the arithmetic under test is the only variable. import json import logging -import os -import sys from types import MappingProxyType import httpx import pytest import respx -sys.path.insert(0, os.path.abspath("../../../..")) import litellm import litellm.batches.batch_utils as bu diff --git a/tests/test_litellm/batches/test_main.py b/tests/test_litellm/batches/test_main.py index 17e9ee29d4d..c3edb40c819 100644 --- a/tests/test_litellm/batches/test_main.py +++ b/tests/test_litellm/batches/test_main.py @@ -23,8 +23,6 @@ production. Provider env vars are not required: missing creds resolve to None an flow through harmlessly because the handler is mocked. """ -import os -import sys from contextlib import ExitStack from dataclasses import dataclass from typing import Any, Dict @@ -33,7 +31,6 @@ from unittest.mock import MagicMock, patch import pytest -sys.path.insert(0, os.path.abspath("../../../..")) import litellm import litellm.batches.main as bm diff --git a/tests/test_litellm/caching/test_azure_blob_cache.py b/tests/test_litellm/caching/test_azure_blob_cache.py index c5c85e1551d..63f4681fd06 100644 --- a/tests/test_litellm/caching/test_azure_blob_cache.py +++ b/tests/test_litellm/caching/test_azure_blob_cache.py @@ -1,13 +1,8 @@ -import os -import sys from unittest.mock import MagicMock, patch, AsyncMock import pytest from fastapi.testclient import TestClient -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from litellm.caching.azure_blob_cache import AzureBlobCache diff --git a/tests/test_litellm/caching/test_caching_handler.py b/tests/test_litellm/caching/test_caching_handler.py index 9684e82f550..6c60aa6e220 100644 --- a/tests/test_litellm/caching/test_caching_handler.py +++ b/tests/test_litellm/caching/test_caching_handler.py @@ -1,7 +1,5 @@ import asyncio import json -import os -import sys import time from unittest.mock import MagicMock, patch @@ -10,9 +8,6 @@ import pytest import respx from fastapi.testclient import TestClient -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from datetime import datetime from unittest.mock import AsyncMock diff --git a/tests/test_litellm/caching/test_embedding_router.py b/tests/test_litellm/caching/test_embedding_router.py index 9ebe669d32d..00a80c63303 100644 --- a/tests/test_litellm/caching/test_embedding_router.py +++ b/tests/test_litellm/caching/test_embedding_router.py @@ -1,8 +1,5 @@ -import os -import sys from unittest.mock import MagicMock -sys.path.insert(0, os.path.abspath("../../..")) import litellm from litellm.caching._embedding_router import ( diff --git a/tests/test_litellm/caching/test_gcs_cache.py b/tests/test_litellm/caching/test_gcs_cache.py index 40bfa447d63..6222cf4760a 100644 --- a/tests/test_litellm/caching/test_gcs_cache.py +++ b/tests/test_litellm/caching/test_gcs_cache.py @@ -1,10 +1,7 @@ -import os -import sys from unittest.mock import MagicMock, AsyncMock, patch import pytest -sys.path.insert(0, os.path.abspath("../../..")) from litellm.caching.gcs_cache import GCSCache diff --git a/tests/test_litellm/caching/test_in_memory_cache.py b/tests/test_litellm/caching/test_in_memory_cache.py index 7be03d23fbe..85e8308ae91 100644 --- a/tests/test_litellm/caching/test_in_memory_cache.py +++ b/tests/test_litellm/caching/test_in_memory_cache.py @@ -1,7 +1,5 @@ import asyncio import json -import os -import sys import threading import time from concurrent.futures import ThreadPoolExecutor @@ -12,9 +10,6 @@ import pytest import respx from fastapi.testclient import TestClient -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from unittest.mock import AsyncMock from litellm.caching.in_memory_cache import InMemoryCache diff --git a/tests/test_litellm/caching/test_llm_caching_handler.py b/tests/test_litellm/caching/test_llm_caching_handler.py index 5f0e82dbb80..dd81b877c0e 100644 --- a/tests/test_litellm/caching/test_llm_caching_handler.py +++ b/tests/test_litellm/caching/test_llm_caching_handler.py @@ -9,15 +9,10 @@ See: https://github.com/BerriAI/litellm/pull/22247 """ import asyncio -import os -import sys import warnings import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from litellm.caching.evicted_client_closer import EvictedClientCloser from litellm.caching.llm_caching_handler import LLMClientCache diff --git a/tests/test_litellm/caching/test_qdrant_semantic_cache.py b/tests/test_litellm/caching/test_qdrant_semantic_cache.py index a5fbaf151ca..e07578dd7e5 100644 --- a/tests/test_litellm/caching/test_qdrant_semantic_cache.py +++ b/tests/test_litellm/caching/test_qdrant_semantic_cache.py @@ -1,13 +1,9 @@ -import os import sys import types from unittest.mock import AsyncMock, MagicMock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path def test_qdrant_semantic_cache_initialization(monkeypatch): diff --git a/tests/test_litellm/caching/test_redis_cache.py b/tests/test_litellm/caching/test_redis_cache.py index 6a76decd5b1..decf59130fe 100644 --- a/tests/test_litellm/caching/test_redis_cache.py +++ b/tests/test_litellm/caching/test_redis_cache.py @@ -1,13 +1,8 @@ import asyncio -import os -import sys from unittest.mock import MagicMock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from unittest.mock import AsyncMock from litellm.caching.redis_cache import RedisCache diff --git a/tests/test_litellm/caching/test_redis_cluster_cache.py b/tests/test_litellm/caching/test_redis_cluster_cache.py index 26878865187..372425aa9fa 100644 --- a/tests/test_litellm/caching/test_redis_cluster_cache.py +++ b/tests/test_litellm/caching/test_redis_cluster_cache.py @@ -1,14 +1,9 @@ import json -import os -import sys from unittest.mock import MagicMock, patch import pytest from fastapi.testclient import TestClient -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from litellm.caching.redis_cache import RedisCache from litellm.caching.redis_cluster_cache import RedisClusterCache diff --git a/tests/test_litellm/caching/test_redis_semantic_cache.py b/tests/test_litellm/caching/test_redis_semantic_cache.py index 66271579d31..be4367fd8bd 100644 --- a/tests/test_litellm/caching/test_redis_semantic_cache.py +++ b/tests/test_litellm/caching/test_redis_semantic_cache.py @@ -1,12 +1,8 @@ -import os import sys from unittest.mock import AsyncMock, MagicMock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path # Tests for RedisSemanticCache @@ -893,7 +889,6 @@ async def test_redis_semantic_cache_async_paths_set_similarity_on_misses(): def test_redis_get_embedding_routes_through_router(monkeypatch): - import sys import types from litellm.caching.redis_semantic_cache import RedisSemanticCache @@ -928,7 +923,6 @@ def test_redis_get_embedding_routes_through_router(monkeypatch): def test_redis_get_embedding_falls_back_to_direct(monkeypatch): - import sys import types from litellm.caching.redis_semantic_cache import RedisSemanticCache @@ -1138,7 +1132,6 @@ def test_redis_sync_get_cache_passes_precomputed_vector(): @pytest.mark.asyncio async def test_redis_async_embedding_forwards_full_metadata(monkeypatch): - import sys import types from litellm.caching.redis_semantic_cache import RedisSemanticCache @@ -1169,7 +1162,6 @@ LONG_PROMPT = " ".join(f"token{i}" for i in range(300)) def _proxy_with_router(monkeypatch: pytest.MonkeyPatch, router: MagicMock, model_name: str) -> None: - import sys import types fake_proxy = types.ModuleType("litellm.proxy.proxy_server") @@ -1223,7 +1215,6 @@ async def test_redis_async_embedding_explicit_limit_beats_deployment_limit(monke def test_redis_get_embedding_truncates_direct_path_with_explicit_limit(monkeypatch): - import sys import types from litellm.caching.redis_semantic_cache import RedisSemanticCache @@ -1342,7 +1333,6 @@ def _router_proxy_module(router, model_name): def test_redis_sync_embedding_call_is_bounded(monkeypatch): - import sys from litellm.caching.redis_semantic_cache import RedisSemanticCache @@ -1366,7 +1356,6 @@ def test_redis_sync_embedding_call_is_bounded(monkeypatch): @pytest.mark.asyncio async def test_redis_async_embedding_call_is_bounded(monkeypatch): - import sys from litellm.caching.redis_semantic_cache import RedisSemanticCache @@ -1391,7 +1380,6 @@ async def test_redis_async_embedding_call_is_bounded(monkeypatch): @pytest.mark.asyncio async def test_redis_async_embedding_gives_up_on_unresponsive_endpoint(monkeypatch): import asyncio - import sys import time from litellm.caching.redis_semantic_cache import RedisSemanticCache @@ -1422,7 +1410,6 @@ async def test_redis_async_embedding_gives_up_on_unresponsive_endpoint(monkeypat @pytest.mark.asyncio async def test_redis_async_get_cache_fails_open_when_embedding_hangs(monkeypatch): import asyncio - import sys import time from litellm.caching.redis_semantic_cache import RedisSemanticCache diff --git a/tests/test_litellm/caching/test_s3_cache.py b/tests/test_litellm/caching/test_s3_cache.py index 795511c5bc2..f9a0b165e12 100644 --- a/tests/test_litellm/caching/test_s3_cache.py +++ b/tests/test_litellm/caching/test_s3_cache.py @@ -1,5 +1,3 @@ -import os -import sys from unittest.mock import MagicMock, patch import json import datetime @@ -7,9 +5,6 @@ import asyncio import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from litellm.caching.s3_cache import S3Cache diff --git a/tests/test_litellm/caching/test_valkey_semantic_cache.py b/tests/test_litellm/caching/test_valkey_semantic_cache.py index acf5a914e5c..749658784ac 100644 --- a/tests/test_litellm/caching/test_valkey_semantic_cache.py +++ b/tests/test_litellm/caching/test_valkey_semantic_cache.py @@ -9,7 +9,6 @@ from unittest.mock import AsyncMock, MagicMock import pytest -sys.path.insert(0, os.path.abspath("../../..")) from litellm.caching.valkey_semantic_cache import ValkeySemanticCache diff --git a/tests/test_litellm/completion_extras/litellm_responses_transformation/test_completion_extras_litellm_responses_transformation_handler.py b/tests/test_litellm/completion_extras/litellm_responses_transformation/test_completion_extras_litellm_responses_transformation_handler.py index 42b5ba235bc..c5d7ca96a21 100644 --- a/tests/test_litellm/completion_extras/litellm_responses_transformation/test_completion_extras_litellm_responses_transformation_handler.py +++ b/tests/test_litellm/completion_extras/litellm_responses_transformation/test_completion_extras_litellm_responses_transformation_handler.py @@ -1,11 +1,8 @@ -import os -import sys from datetime import datetime from unittest.mock import AsyncMock, MagicMock, patch import pytest -sys.path.insert(0, os.path.abspath("../../..")) import litellm from litellm.completion_extras.litellm_responses_transformation.handler import ( diff --git a/tests/test_litellm/completion_extras/litellm_responses_transformation/test_completion_extras_litellm_responses_transformation_transformation.py b/tests/test_litellm/completion_extras/litellm_responses_transformation/test_completion_extras_litellm_responses_transformation_transformation.py index 858ca482eb7..4ff92aaf87d 100644 --- a/tests/test_litellm/completion_extras/litellm_responses_transformation/test_completion_extras_litellm_responses_transformation_transformation.py +++ b/tests/test_litellm/completion_extras/litellm_responses_transformation/test_completion_extras_litellm_responses_transformation_transformation.py @@ -1,7 +1,6 @@ import datetime import json import os -import sys import unittest from typing import TYPE_CHECKING, List, Literal, Optional, Tuple from unittest.mock import ANY, MagicMock, Mock, patch @@ -9,9 +8,6 @@ from unittest.mock import ANY, MagicMock, Mock, patch import httpx import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system-path import litellm from litellm.completion_extras.litellm_responses_transformation.transformation import ( LiteLLMResponsesTransformationHandler, @@ -1518,7 +1514,6 @@ def test_map_reasoning_effort_adds_summary_detailed(monkeypatch): When flag is enabled (flag=True or env var), summary="detailed" is added. """ - import os import litellm from litellm.completion_extras.litellm_responses_transformation.transformation import ( diff --git a/tests/test_litellm/conftest.py b/tests/test_litellm/conftest.py index ceb491e3d11..1fe73b552da 100644 --- a/tests/test_litellm/conftest.py +++ b/tests/test_litellm/conftest.py @@ -9,13 +9,9 @@ import importlib import os -import sys from pathlib import Path import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import asyncio import litellm @@ -462,7 +458,6 @@ def setup_and_teardown(): Use this sparingly - most state should be handled by isolate_litellm_state. Only reload modules here if absolutely necessary. """ - sys.path.insert(0, os.path.abspath("../..")) import litellm diff --git a/tests/test_litellm/containers/test_azure_container_transformation.py b/tests/test_litellm/containers/test_azure_container_transformation.py index cdcccf7c04e..1c990220e11 100644 --- a/tests/test_litellm/containers/test_azure_container_transformation.py +++ b/tests/test_litellm/containers/test_azure_container_transformation.py @@ -1,12 +1,9 @@ -import os -import sys from unittest.mock import AsyncMock, MagicMock from urllib.parse import parse_qs, urlparse import httpx import pytest -sys.path.insert(0, os.path.abspath("../../../")) import litellm from litellm.llms.azure.containers.transformation import AzureContainerConfig diff --git a/tests/test_litellm/containers/test_container_api.py b/tests/test_litellm/containers/test_container_api.py index de6fd1bc8ce..885c4cd294a 100644 --- a/tests/test_litellm/containers/test_container_api.py +++ b/tests/test_litellm/containers/test_container_api.py @@ -1,15 +1,10 @@ import asyncio import json -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import httpx import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path import litellm from litellm.containers.main import ( diff --git a/tests/test_litellm/containers/test_container_integration.py b/tests/test_litellm/containers/test_container_integration.py index 062d0359f60..6c3a876fc45 100644 --- a/tests/test_litellm/containers/test_container_integration.py +++ b/tests/test_litellm/containers/test_container_integration.py @@ -1,14 +1,10 @@ import json import os -import sys from unittest.mock import MagicMock, patch import pytest import httpx -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path import litellm from litellm.types.containers.main import ( diff --git a/tests/test_litellm/containers/test_container_regional_api_base.py b/tests/test_litellm/containers/test_container_regional_api_base.py index d450d7f9cf0..055f7d4b166 100644 --- a/tests/test_litellm/containers/test_container_regional_api_base.py +++ b/tests/test_litellm/containers/test_container_regional_api_base.py @@ -7,13 +7,11 @@ US Data Residency instead of defaulting to https://api.openai.com/v1. """ import os -import sys from unittest.mock import MagicMock, patch import httpx import pytest -sys.path.insert(0, os.path.abspath("../../..")) import litellm diff --git a/tests/test_litellm/containers/test_container_transformation.py b/tests/test_litellm/containers/test_container_transformation.py index f0432816fce..8bc3ffda544 100644 --- a/tests/test_litellm/containers/test_container_transformation.py +++ b/tests/test_litellm/containers/test_container_transformation.py @@ -1,14 +1,10 @@ import json import os -import sys from unittest.mock import MagicMock, patch import httpx import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path import litellm from litellm.llms.openai.containers.transformation import OpenAIContainerConfig diff --git a/tests/test_litellm/containers/test_container_utils.py b/tests/test_litellm/containers/test_container_utils.py index 35e9ed36916..a81d1263d6b 100644 --- a/tests/test_litellm/containers/test_container_utils.py +++ b/tests/test_litellm/containers/test_container_utils.py @@ -1,11 +1,6 @@ -import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path import litellm from litellm.containers.utils import ( diff --git a/tests/test_litellm/enterprise/enterprise_callbacks/send_emails/test_base_email.py b/tests/test_litellm/enterprise/enterprise_callbacks/send_emails/test_base_email.py index 61303340570..8b89c592f02 100644 --- a/tests/test_litellm/enterprise/enterprise_callbacks/send_emails/test_base_email.py +++ b/tests/test_litellm/enterprise/enterprise_callbacks/send_emails/test_base_email.py @@ -1,7 +1,6 @@ import asyncio import json import os -import sys import unittest.mock as mock from unittest.mock import patch @@ -13,7 +12,6 @@ from litellm_enterprise.enterprise_callbacks.send_emails.base_email import ( BaseEmailLogger, ) -sys.path.insert(0, os.path.abspath("../../..")) from litellm_enterprise.types.enterprise_callbacks.send_emails import ( EmailEvent, SendKeyCreatedEmailEvent, diff --git a/tests/test_litellm/enterprise/enterprise_callbacks/send_emails/test_endpoints.py b/tests/test_litellm/enterprise/enterprise_callbacks/send_emails/test_endpoints.py index d1e8f37184a..f0e1461c616 100644 --- a/tests/test_litellm/enterprise/enterprise_callbacks/send_emails/test_endpoints.py +++ b/tests/test_litellm/enterprise/enterprise_callbacks/send_emails/test_endpoints.py @@ -1,13 +1,10 @@ import json -import os -import sys import unittest.mock as mock import pytest from fastapi import HTTPException from fastapi.testclient import TestClient -sys.path.insert(0, os.path.abspath("../../..")) from litellm_enterprise.enterprise_callbacks.send_emails.endpoints import ( _get_email_settings, diff --git a/tests/test_litellm/enterprise/enterprise_callbacks/send_emails/test_resend_email.py b/tests/test_litellm/enterprise/enterprise_callbacks/send_emails/test_resend_email.py index fbfd609cca6..6bf77ac2d28 100644 --- a/tests/test_litellm/enterprise/enterprise_callbacks/send_emails/test_resend_email.py +++ b/tests/test_litellm/enterprise/enterprise_callbacks/send_emails/test_resend_email.py @@ -1,11 +1,9 @@ import os -import sys import unittest.mock as mock import pytest from httpx import Response -sys.path.insert(0, os.path.abspath("../../..")) import litellm from litellm_enterprise.enterprise_callbacks.send_emails.resend_email import ( diff --git a/tests/test_litellm/enterprise/enterprise_callbacks/send_emails/test_sendgrid_email.py b/tests/test_litellm/enterprise/enterprise_callbacks/send_emails/test_sendgrid_email.py index b7fcce8dbf3..465a03cfff7 100644 --- a/tests/test_litellm/enterprise/enterprise_callbacks/send_emails/test_sendgrid_email.py +++ b/tests/test_litellm/enterprise/enterprise_callbacks/send_emails/test_sendgrid_email.py @@ -1,11 +1,9 @@ import os -import sys import unittest.mock as mock import pytest from httpx import Response -sys.path.insert(0, os.path.abspath("../../..")) import litellm from litellm_enterprise.enterprise_callbacks.send_emails.sendgrid_email import ( diff --git a/tests/test_litellm/enterprise/proxy/test_managed_files_hook.py b/tests/test_litellm/enterprise/proxy/test_managed_files_hook.py index fcd03e77aa2..eddfc4fbd34 100644 --- a/tests/test_litellm/enterprise/proxy/test_managed_files_hook.py +++ b/tests/test_litellm/enterprise/proxy/test_managed_files_hook.py @@ -14,8 +14,8 @@ import pytest from typing import Optional from unittest.mock import AsyncMock, MagicMock, patch -from litellm.proxy._types import UserAPIKeyAuth -from litellm.types.llms.openai import OpenAIFileObject +from litellm.proxy._types import LitellmUserRoles, ProxyException, UserAPIKeyAuth +from litellm.types.llms.openai import FileListPage, OpenAIFileObject from litellm.types.utils import LiteLLMBatch @@ -66,6 +66,114 @@ def _make_user_api_key_dict() -> UserAPIKeyAuth: ) +def _make_team_member_api_key_dict() -> UserAPIKeyAuth: + """The shape most real virtual keys carry: a user_id and a team_id.""" + return UserAPIKeyAuth( + api_key="sk-test", + user_id="test-user", + team_id="test-team", + parent_otel_span=None, + ) + + +def _make_service_account_api_key_dict() -> UserAPIKeyAuth: + return UserAPIKeyAuth( + api_key="sk-service", + team_id="test-team", + parent_otel_span=None, + ) + + +def _make_admin_api_key_dict() -> UserAPIKeyAuth: + return UserAPIKeyAuth( + api_key="sk-admin", + user_id="admin-user", + user_role=LitellmUserRoles.PROXY_ADMIN, + parent_otel_span=None, + ) + + +def _make_managed_file_row( + unified_file_id: str, + purpose: str = "batch_output", + created_by: str = "test-user", + team_id: Optional[str] = None, +) -> MagicMock: + file_object = _make_file_object(f"file-provider-{unified_file_id}").model_copy( + update={"purpose": purpose} + ) + return MagicMock( + unified_file_id=unified_file_id, + file_object=file_object.model_dump(), + created_by=created_by, + team_id=team_id, + ) + + +def _make_unparseable_managed_file_row( + unified_file_id: str, + created_by: str = "test-user", + team_id: Optional[str] = None, +) -> MagicMock: + """A row whose stored blob cannot be parsed back into a file object.""" + return MagicMock( + unified_file_id=unified_file_id, + file_object=None, + created_by=created_by, + team_id=team_id, + ) + + +def _row_matches_where(row, where) -> bool: + """Apply the Prisma ``where`` shapes build_owner_filter actually emits: + ``{}``, a single equality, and the ``OR`` of equalities a key carrying + both a user_id and a team_id produces.""" + for field, expected in where.items(): + if field == "OR": + if not any(_row_matches_where(row, clause) for clause in expected): + return False + elif getattr(row, field) != expected: + return False + return True + + +class _FakeManagedFileTable: + """In-memory stand-in for the managed file table, newest row first.""" + + def __init__(self, rows): + self.rows = list(rows) + self.find_many_calls = [] + self.find_first_calls = [] + + def _owned_rows(self, where): + return [row for row in self.rows if _row_matches_where(row, where)] + + async def find_first(self, where): + self.find_first_calls.append(where) + return next(iter(self._owned_rows(where)), None) + + async def find_many(self, where, take=None, order=None, cursor=None, skip=0): + self.find_many_calls.append( + {"where": where, "take": take, "order": order, "cursor": cursor, "skip": skip} + ) + rows = self._owned_rows(where) + if cursor is not None: + start = next( + index + for index, row in enumerate(rows) + if row.unified_file_id == cursor["unified_file_id"] + ) + rows = rows[start + skip :] + return rows if take is None else rows[:take] + + +def _make_managed_files_over_rows(rows): + managed_files = _make_managed_files_instance() + table = _FakeManagedFileTable(rows) + managed_files.prisma_client.db.litellm_managedfiletable = table + return managed_files, table + + def _make_managed_files_instance(): """Create a _PROXY_LiteLLMManagedFiles with storage methods mocked out.""" from litellm_enterprise.proxy.hooks.managed_files import ( @@ -190,6 +298,578 @@ async def test_get_user_created_file_ids_remaps_stored_raw_provider_id_to_unifie assert files[0].purpose == raw_provider_object.purpose +@pytest.mark.asyncio +async def test_afile_list_returns_owner_scoped_managed_files(): + managed_files = _make_managed_files_instance() + managed_files.prisma_client.db.litellm_managedfiletable.find_many = AsyncMock( + return_value=[ + MagicMock( + file_object=_make_file_object("file-provider-id").model_dump(), + unified_file_id="unified-file-id", + ), + MagicMock( + file_object=_make_file_object("file-other-purpose").model_copy( + update={"purpose": "batch"} + ).model_dump(), + unified_file_id="unified-other-purpose", + ), + ] + ) + + response = await managed_files.afile_list( + purpose="batch_output", + litellm_parent_otel_span=None, + user_api_key_dict=_make_user_api_key_dict(), + ) + + managed_files.prisma_client.db.litellm_managedfiletable.find_many.assert_awaited_once_with( + where={"created_by": "test-user"}, + take=10001, + order=[{"created_at": "desc"}, {"unified_file_id": "desc"}], + ) + assert [file.id for file in response.data] == ["unified-file-id"] + assert response.first_id == "unified-file-id" + assert response.last_id == "unified-file-id" + assert response.has_more is False + + +@pytest.mark.asyncio +async def test_afile_list_returns_a_page_object_callbacks_can_read(): + """Post-call hooks receive the listing and read ``.data`` off it, the way the + provider SDK's page lets them. The body on the wire stays a plain list page.""" + from fastapi.encoders import jsonable_encoder + + managed_files, _ = _make_managed_files_over_rows([_make_managed_file_row("unified-file-id")]) + + page = await managed_files.afile_list( + purpose=None, + litellm_parent_otel_span=None, + user_api_key_dict=_make_user_api_key_dict(), + ) + + assert isinstance(page, FileListPage) + assert [file.id for file in page.data] == ["unified-file-id"] + + body = jsonable_encoder(page) + assert list(body) == ["object", "data", "first_id", "last_id", "has_more"] + assert body["object"] == "list" + assert [file["id"] for file in body["data"]] == ["unified-file-id"] + assert body["first_id"] == "unified-file-id" + assert body["last_id"] == "unified-file-id" + assert body["has_more"] is False + + +@pytest.mark.asyncio +@pytest.mark.parametrize("purpose", ["nonexistent_purpose", "EVALS", "batch "]) +async def test_afile_list_rejects_a_purpose_the_files_api_never_accepts(purpose): + """No stored file can carry an undocumented purpose, so filtering on one is a + bad request rather than a legitimately empty page.""" + managed_files, table = _make_managed_files_over_rows([_make_managed_file_row("unified-file-id")]) + + with pytest.raises(ProxyException) as exc_info: + await managed_files.afile_list( + purpose=purpose, + litellm_parent_otel_span=None, + user_api_key_dict=_make_user_api_key_dict(), + ) + + assert exc_info.value.code == "400" + assert exc_info.value.type == "invalid_request_error" + assert exc_info.value.param == "purpose" + assert table.find_many_calls == [] + + +@pytest.mark.asyncio +@pytest.mark.parametrize("purpose", ["batch", "assistants", "fine-tune", "evals", None]) +async def test_afile_list_accepts_every_documented_purpose(purpose): + managed_files, _ = _make_managed_files_over_rows([_make_managed_file_row("unified-file-id")]) + + page = await managed_files.afile_list( + purpose=purpose, + litellm_parent_otel_span=None, + user_api_key_dict=_make_user_api_key_dict(), + ) + + assert isinstance(page, FileListPage) + + +@pytest.mark.asyncio +async def test_afile_list_does_not_leak_another_callers_files(): + managed_files, table = _make_managed_files_over_rows( + [ + _make_managed_file_row("unified-mine-2"), + _make_managed_file_row("unified-theirs", created_by="other-user"), + _make_managed_file_row("unified-mine-1"), + ] + ) + + response = await managed_files.afile_list( + purpose=None, + litellm_parent_otel_span=None, + user_api_key_dict=_make_user_api_key_dict(), + ) + + assert [file.id for file in response.data] == ["unified-mine-2", "unified-mine-1"] + assert table.find_many_calls[0]["where"] == {"created_by": "test-user"} + + +@pytest.mark.asyncio +async def test_afile_list_returns_own_and_team_files_for_a_key_carrying_both_ids(): + managed_files, table = _make_managed_files_over_rows( + [ + _make_managed_file_row("unified-mine"), + _make_managed_file_row("unified-teammates", created_by="other-user", team_id="test-team"), + _make_managed_file_row("unified-outsiders", created_by="outsider", team_id="other-team"), + ] + ) + + response = await managed_files.afile_list( + purpose=None, + litellm_parent_otel_span=None, + user_api_key_dict=_make_team_member_api_key_dict(), + ) + + assert [file.id for file in response.data] == ["unified-mine", "unified-teammates"] + assert table.find_many_calls[0]["where"] == { + "OR": [{"created_by": "test-user"}, {"team_id": "test-team"}] + } + + +@pytest.mark.asyncio +async def test_afile_list_scopes_a_service_account_key_to_its_team(): + managed_files, table = _make_managed_files_over_rows( + [ + _make_managed_file_row("unified-teams", created_by="other-user", team_id="test-team"), + _make_managed_file_row("unified-outsiders", created_by="outsider", team_id="other-team"), + ] + ) + + response = await managed_files.afile_list( + purpose=None, + litellm_parent_otel_span=None, + user_api_key_dict=_make_service_account_api_key_dict(), + ) + + assert [file.id for file in response.data] == ["unified-teams"] + assert table.find_many_calls[0]["where"] == {"team_id": "test-team"} + + +@pytest.mark.asyncio +async def test_afile_list_returns_every_callers_files_for_a_proxy_admin(): + managed_files, table = _make_managed_files_over_rows( + [ + _make_managed_file_row("unified-mine"), + _make_managed_file_row("unified-theirs", created_by="other-user", team_id="other-team"), + ] + ) + + response = await managed_files.afile_list( + purpose=None, + litellm_parent_otel_span=None, + user_api_key_dict=_make_admin_api_key_dict(), + ) + + assert [file.id for file in response.data] == ["unified-mine", "unified-theirs"] + assert table.find_many_calls[0]["where"] == {} + + +@pytest.mark.asyncio +async def test_afile_list_pages_a_team_key_across_both_halves_of_its_filter(): + """Keyset pagination has to walk an OR filter as one ordered set, without + repeating a row across pages or dropping one between them.""" + managed_files, table = _make_managed_files_over_rows( + [ + _make_managed_file_row("unified-0"), + _make_managed_file_row("unified-1", created_by="other-user", team_id="test-team"), + _make_managed_file_row("unified-2"), + _make_managed_file_row("unified-3", created_by="outsider", team_id="other-team"), + _make_managed_file_row("unified-4", created_by="other-user", team_id="test-team"), + ] + ) + user_api_key_dict = _make_team_member_api_key_dict() + + seen = [] + cursor = None + for _ in range(4): + response = await managed_files.afile_list( + purpose=None, + litellm_parent_otel_span=None, + user_api_key_dict=user_api_key_dict, + limit=2, + after=cursor, + ) + seen.extend(file.id for file in response.data) + if not response.has_more: + break + cursor = response.last_id + + assert seen == ["unified-0", "unified-1", "unified-2", "unified-4"] + assert all( + call["where"] == {"OR": [{"created_by": "test-user"}, {"team_id": "test-team"}]} + for call in table.find_many_calls + ) + + +@pytest.mark.asyncio +async def test_afile_list_orders_newest_first_and_breaks_ties_on_the_cursor_column(): + managed_files, table = _make_managed_files_over_rows([_make_managed_file_row("unified-mine")]) + + await managed_files.afile_list( + purpose=None, + litellm_parent_otel_span=None, + user_api_key_dict=_make_user_api_key_dict(), + ) + + assert table.find_many_calls[0]["order"] == [ + {"created_at": "desc"}, + {"unified_file_id": "desc"}, + ] + + +@pytest.mark.asyncio +async def test_afile_list_denies_a_caller_without_a_user_or_team(): + managed_files, table = _make_managed_files_over_rows([_make_managed_file_row("unified-mine")]) + + response = await managed_files.afile_list( + purpose=None, + litellm_parent_otel_span=None, + user_api_key_dict=UserAPIKeyAuth(api_key="sk-test", parent_otel_span=None), + ) + + assert response.data == [] + assert response.has_more is False + assert table.find_many_calls == [] + + +@pytest.mark.asyncio +async def test_afile_list_filters_by_purpose(): + managed_files, _ = _make_managed_files_over_rows( + [ + _make_managed_file_row("unified-batch-output"), + _make_managed_file_row("unified-batch", purpose="batch"), + ] + ) + + response = await managed_files.afile_list( + purpose="batch", + litellm_parent_otel_span=None, + user_api_key_dict=_make_user_api_key_dict(), + ) + + assert [file.id for file in response.data] == ["unified-batch"] + + +async def _walk_afile_list(managed_files, user_api_key_dict, purpose, limit): + """Page through the listing the way the official SDK does, off ``data[-1].id``.""" + seen = [] + after = None + while True: + page = await managed_files.afile_list( + purpose=purpose, + litellm_parent_otel_span=None, + user_api_key_dict=user_api_key_dict, + limit=limit, + after=after, + ) + page_ids = [file.id for file in page.data] + assert not set(page_ids) & set(seen) + seen.extend(page_ids) + if not page.has_more: + return seen + assert page_ids, "an SDK stops paging on an empty page, so has_more must never ride one" + after = page_ids[-1] + + +@pytest.mark.asyncio +async def test_afile_list_fills_a_page_past_rows_the_purpose_filter_drops(): + """The newest rows do not match, so the page must reach past them rather than come back empty.""" + managed_files, _ = _make_managed_files_over_rows( + [ + _make_managed_file_row("unified-0"), + _make_managed_file_row("unified-1"), + _make_managed_file_row("unified-2", purpose="batch"), + _make_managed_file_row("unified-3"), + _make_managed_file_row("unified-4", purpose="batch"), + ] + ) + user_api_key_dict = _make_user_api_key_dict() + + first_page = await managed_files.afile_list( + purpose="batch", + litellm_parent_otel_span=None, + user_api_key_dict=user_api_key_dict, + limit=1, + ) + + assert [file.id for file in first_page.data] == ["unified-2"] + assert first_page.has_more is True + assert first_page.last_id == "unified-2" + + second_page = await managed_files.afile_list( + purpose="batch", + litellm_parent_otel_span=None, + user_api_key_dict=user_api_key_dict, + limit=1, + after=first_page.last_id, + ) + + assert [file.id for file in second_page.data] == ["unified-4"] + assert second_page.has_more is False + + +@pytest.mark.parametrize("limit", [1, 2, 3]) +@pytest.mark.asyncio +async def test_afile_list_walks_every_purpose_match_at_any_limit(limit): + managed_files, _ = _make_managed_files_over_rows( + [ + _make_managed_file_row("unified-0"), + _make_managed_file_row("unified-1"), + _make_managed_file_row("unified-2", purpose="batch"), + _make_managed_file_row("unified-3"), + _make_managed_file_row("unified-4", purpose="batch"), + _make_managed_file_row("unified-5", purpose="batch"), + _make_managed_file_row("unified-6"), + ] + ) + + seen = await _walk_afile_list(managed_files, _make_user_api_key_dict(), "batch", limit) + + assert seen == ["unified-2", "unified-4", "unified-5"] + + +@pytest.mark.asyncio +async def test_afile_list_fills_a_page_past_rows_that_do_not_parse(): + managed_files, _ = _make_managed_files_over_rows( + [ + _make_unparseable_managed_file_row("unified-0"), + _make_unparseable_managed_file_row("unified-1"), + _make_managed_file_row("unified-2"), + ] + ) + + page = await managed_files.afile_list( + purpose=None, + litellm_parent_otel_span=None, + user_api_key_dict=_make_user_api_key_dict(), + limit=1, + ) + + assert [file.id for file in page.data] == ["unified-2"] + assert page.has_more is False + + +_DEEP_SCAN_ROW_COUNT = 2000 +_DEEP_SCAN_QUERY_BUDGET = 10 + + +@pytest.mark.asyncio +async def test_afile_list_bounds_the_queries_a_deep_purpose_match_costs(): + """A tiny limit over rows the filter drops must not turn one request into thousands of queries.""" + managed_files, table = _make_managed_files_over_rows( + [_make_managed_file_row(f"unified-{index:05d}") for index in range(_DEEP_SCAN_ROW_COUNT)] + + [_make_managed_file_row("unified-match", purpose="batch")] + ) + + page = await managed_files.afile_list( + purpose="batch", + litellm_parent_otel_span=None, + user_api_key_dict=_make_user_api_key_dict(), + limit=1, + ) + + assert [file.id for file in page.data] == ["unified-match"] + assert page.has_more is False + assert len(table.find_many_calls) <= _DEEP_SCAN_QUERY_BUDGET + + +@pytest.mark.asyncio +async def test_afile_list_bounds_the_queries_a_deep_unparseable_run_costs(): + """Rows that will not parse drop out like a filter does, so they get the same bound.""" + managed_files, table = _make_managed_files_over_rows( + [_make_unparseable_managed_file_row(f"unified-{index:05d}") for index in range(_DEEP_SCAN_ROW_COUNT)] + + [_make_managed_file_row("unified-parses")] + ) + + page = await managed_files.afile_list( + purpose=None, + litellm_parent_otel_span=None, + user_api_key_dict=_make_user_api_key_dict(), + limit=1, + ) + + assert [file.id for file in page.data] == ["unified-parses"] + assert page.has_more is False + assert len(table.find_many_calls) <= _DEEP_SCAN_QUERY_BUDGET + + +@pytest.mark.asyncio +async def test_afile_list_reads_one_chunk_when_the_first_one_fills_the_page(): + """The widened chunk must stay off the common path, where the newest rows already fill the page.""" + managed_files, table = _make_managed_files_over_rows( + [_make_managed_file_row(f"unified-{index:05d}") for index in range(_DEEP_SCAN_ROW_COUNT)] + ) + + page = await managed_files.afile_list( + purpose=None, + litellm_parent_otel_span=None, + user_api_key_dict=_make_user_api_key_dict(), + limit=2, + ) + + assert [file.id for file in page.data] == ["unified-00000", "unified-00001"] + assert page.has_more is True + assert [call["take"] for call in table.find_many_calls] == [3] + + +@pytest.mark.asyncio +async def test_afile_list_reports_no_more_pages_when_nothing_matches(): + managed_files, _ = _make_managed_files_over_rows( + [_make_managed_file_row(f"unified-{index}") for index in range(5)] + ) + + page = await managed_files.afile_list( + purpose="batch", + litellm_parent_otel_span=None, + user_api_key_dict=_make_user_api_key_dict(), + limit=2, + ) + + assert page.data == [] + assert page.has_more is False + assert page.first_id is None + assert page.last_id is None + + +@pytest.mark.asyncio +async def test_afile_list_honors_limit_and_reports_more_pages(): + managed_files, table = _make_managed_files_over_rows( + [_make_managed_file_row(f"unified-{index}") for index in range(5)] + ) + + response = await managed_files.afile_list( + purpose=None, + litellm_parent_otel_span=None, + user_api_key_dict=_make_user_api_key_dict(), + limit=2, + ) + + assert [file.id for file in response.data] == ["unified-0", "unified-1"] + assert response.has_more is True + assert table.find_many_calls[0]["take"] == 3 + + +@pytest.mark.asyncio +async def test_afile_list_pages_through_every_file_without_overlap(): + managed_files, table = _make_managed_files_over_rows( + [_make_managed_file_row(f"unified-{index}") for index in range(5)] + ) + user_api_key_dict = _make_user_api_key_dict() + + seen = [] + after = None + while True: + page = await managed_files.afile_list( + purpose=None, + litellm_parent_otel_span=None, + user_api_key_dict=user_api_key_dict, + limit=2, + after=after, + ) + page_ids = [file.id for file in page.data] + assert not set(page_ids) & set(seen) + seen.extend(page_ids) + if not page.has_more: + break + after = page.last_id + + assert seen == [f"unified-{index}" for index in range(5)] + assert table.find_many_calls[1]["cursor"] == {"unified_file_id": "unified-1"} + assert table.find_many_calls[1]["skip"] == 1 + + +@pytest.mark.parametrize( + "unknown_cursor", + ["unified-theirs", "unified-nowhere"], + ids=["another-users-file", "no-such-file"], +) +@pytest.mark.asyncio +async def test_afile_list_rejects_an_after_cursor_outside_the_callers_files(unknown_cursor): + from litellm.proxy._types import ProxyException + + managed_files, table = _make_managed_files_over_rows( + [ + _make_managed_file_row("unified-mine"), + _make_managed_file_row("unified-theirs", created_by="other-user"), + ] + ) + + with pytest.raises(ProxyException) as exc_info: + await managed_files.afile_list( + purpose=None, + litellm_parent_otel_span=None, + user_api_key_dict=_make_user_api_key_dict(), + after=unknown_cursor, + ) + + assert exc_info.value.code == "400" + assert exc_info.value.type == "invalid_request_error" + assert exc_info.value.param == "after" + assert exc_info.value.message == f"Invalid 'after' cursor: no file found with id '{unknown_cursor}'." + assert table.find_first_calls[0] == { + "created_by": "test-user", + "unified_file_id": unknown_cursor, + } + assert table.find_many_calls == [] + + +@pytest.mark.parametrize( + "limit, bound, expected_range", + [ + (0, "below minimum", ">= 1"), + (-1, "below minimum", ">= 1"), + (10001, "above maximum", "<= 10000"), + ], +) +@pytest.mark.asyncio +async def test_afile_list_rejects_a_limit_outside_the_openai_range(limit, bound, expected_range): + from litellm.proxy._types import ProxyException + + managed_files, table = _make_managed_files_over_rows([_make_managed_file_row("unified-mine")]) + + with pytest.raises(ProxyException) as exc_info: + await managed_files.afile_list( + purpose=None, + litellm_parent_otel_span=None, + user_api_key_dict=_make_user_api_key_dict(), + limit=limit, + ) + + assert exc_info.value.code == "400" + assert exc_info.value.type == "invalid_request_error" + assert exc_info.value.param == "limit" + assert exc_info.value.message == ( + f"Invalid 'limit': integer {bound} value. Expected a value {expected_range}, but got {limit} instead." + ) + assert table.find_many_calls == [] + + +@pytest.mark.parametrize("limit", [1, 10000]) +@pytest.mark.asyncio +async def test_afile_list_accepts_the_ends_of_the_openai_limit_range(limit): + managed_files, table = _make_managed_files_over_rows([_make_managed_file_row("unified-mine")]) + + response = await managed_files.afile_list( + purpose=None, + litellm_parent_otel_span=None, + user_api_key_dict=_make_user_api_key_dict(), + limit=limit, + ) + + assert [file.id for file in response.data] == ["unified-mine"] + assert response.has_more is False + assert table.find_many_calls[0]["take"] == limit + 1 + + @pytest.mark.asyncio async def test_parse_managed_file_object_warning_omits_rejected_values(caplog): from litellm_enterprise.proxy.hooks.managed_files import ( diff --git a/tests/test_litellm/experimental_mcp_client/test_mcp_client.py b/tests/test_litellm/experimental_mcp_client/test_mcp_client.py index 1ddb2cc1c8d..51fdfa4ce31 100644 --- a/tests/test_litellm/experimental_mcp_client/test_mcp_client.py +++ b/tests/test_litellm/experimental_mcp_client/test_mcp_client.py @@ -21,7 +21,6 @@ from mcp.types import ( ) # Add the parent directory to the path so we can import litellm -sys.path.insert(0, "../../../") import litellm.experimental_mcp_client.client as mcp_client_module from litellm.experimental_mcp_client.client import ( diff --git a/tests/test_litellm/experimental_mcp_client/test_tools.py b/tests/test_litellm/experimental_mcp_client/test_tools.py index 804e99b6f4e..89f67452f29 100644 --- a/tests/test_litellm/experimental_mcp_client/test_tools.py +++ b/tests/test_litellm/experimental_mcp_client/test_tools.py @@ -1,13 +1,8 @@ import json -import os -import sys from unittest.mock import AsyncMock, MagicMock import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from mcp.types import ( CallToolRequestParams, diff --git a/tests/test_litellm/google_genai/test_google_genai_adapter.py b/tests/test_litellm/google_genai/test_google_genai_adapter.py index 8f5f4d41f3c..81834451859 100644 --- a/tests/test_litellm/google_genai/test_google_genai_adapter.py +++ b/tests/test_litellm/google_genai/test_google_genai_adapter.py @@ -3,20 +3,13 @@ Test to verify the Google GenAI generate_content adapter functionality """ import json -import os -import sys import unittest import pytest from litellm.google_genai.main import agenerate_content -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path -import os -import sys import litellm diff --git a/tests/test_litellm/google_genai/test_google_genai_adapter_fixes.py b/tests/test_litellm/google_genai/test_google_genai_adapter_fixes.py index 36022dcb5db..8ea9dcfb990 100644 --- a/tests/test_litellm/google_genai/test_google_genai_adapter_fixes.py +++ b/tests/test_litellm/google_genai/test_google_genai_adapter_fixes.py @@ -3,16 +3,11 @@ Test to verify the Google GenAI adapter fixes """ import json -import os -import sys import unittest from unittest.mock import patch import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path import litellm from litellm.google_genai.adapters.handler import GenerateContentToCompletionHandler diff --git a/tests/test_litellm/google_genai/test_google_genai_handler.py b/tests/test_litellm/google_genai/test_google_genai_handler.py index 0dc218d297b..bf037c59854 100644 --- a/tests/test_litellm/google_genai/test_google_genai_handler.py +++ b/tests/test_litellm/google_genai/test_google_genai_handler.py @@ -3,15 +3,10 @@ Test to verify the Google GenAI generate_content handler functionality """ import json -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../../../..") -) # Adds the parent directory to the system path import litellm from litellm.google_genai.adapters.handler import GenerateContentToCompletionHandler diff --git a/tests/test_litellm/google_genai/test_google_genai_main.py b/tests/test_litellm/google_genai/test_google_genai_main.py index 8441b62e559..238fff7deca 100644 --- a/tests/test_litellm/google_genai/test_google_genai_main.py +++ b/tests/test_litellm/google_genai/test_google_genai_main.py @@ -4,17 +4,10 @@ Test to verify the Google GenAI generate_content adapter functionality """ import json -import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path -import os -import sys import litellm diff --git a/tests/test_litellm/google_genai/test_google_genai_transformation.py b/tests/test_litellm/google_genai/test_google_genai_transformation.py index 6b0cd500a82..f0d0fc6126d 100644 --- a/tests/test_litellm/google_genai/test_google_genai_transformation.py +++ b/tests/test_litellm/google_genai/test_google_genai_transformation.py @@ -2,12 +2,7 @@ """ Test to verify the Google GenAI transformation logic for generateContent parameters """ -import os -import sys -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path import pytest diff --git a/tests/test_litellm/images/test_image_generation_extra_headers.py b/tests/test_litellm/images/test_image_generation_extra_headers.py index a6e5031c7db..a65bdeb892b 100644 --- a/tests/test_litellm/images/test_image_generation_extra_headers.py +++ b/tests/test_litellm/images/test_image_generation_extra_headers.py @@ -6,13 +6,10 @@ to the OpenAI SDK on the openai/litellm_proxy/openai_compatible_providers code paths. """ -import os -import sys from unittest.mock import MagicMock, patch import pytest -sys.path.insert(0, os.path.abspath("../../..")) import litellm from litellm.images.main import image_generation diff --git a/tests/test_litellm/integrations/SlackAlerting/test_hanging_request_check.py b/tests/test_litellm/integrations/SlackAlerting/test_hanging_request_check.py index 063aabd309b..4b579dfe82f 100644 --- a/tests/test_litellm/integrations/SlackAlerting/test_hanging_request_check.py +++ b/tests/test_litellm/integrations/SlackAlerting/test_hanging_request_check.py @@ -1,6 +1,4 @@ import json -import os -import sys import time from typing import Optional from unittest.mock import AsyncMock, MagicMock, patch @@ -8,7 +6,6 @@ from unittest.mock import AsyncMock, MagicMock, patch import pytest # Adds the grandparent directory to sys.path to allow importing project modules -sys.path.insert(0, os.path.abspath("../..")) from litellm.integrations.SlackAlerting.hanging_request_check import ( AlertingHangingRequestCheck, diff --git a/tests/test_litellm/integrations/SlackAlerting/test_model_deprecation_alert.py b/tests/test_litellm/integrations/SlackAlerting/test_model_deprecation_alert.py index fd54d26c1f6..997e80b45df 100644 --- a/tests/test_litellm/integrations/SlackAlerting/test_model_deprecation_alert.py +++ b/tests/test_litellm/integrations/SlackAlerting/test_model_deprecation_alert.py @@ -1,14 +1,11 @@ """Tests for the Slack alerting model deprecation hook.""" import asyncio -import os -import sys from itertools import chain, repeat from unittest.mock import AsyncMock, MagicMock, patch import pytest -sys.path.insert(0, os.path.abspath("../../../..")) import litellm from litellm.constants import SLACK_MODEL_DEPRECATION_LOCK_ID diff --git a/tests/test_litellm/integrations/SlackAlerting/test_slack_alerting.py b/tests/test_litellm/integrations/SlackAlerting/test_slack_alerting.py index 23a35098697..cfbd3e76a88 100644 --- a/tests/test_litellm/integrations/SlackAlerting/test_slack_alerting.py +++ b/tests/test_litellm/integrations/SlackAlerting/test_slack_alerting.py @@ -1,8 +1,6 @@ import asyncio import datetime import json -import os -import sys import time import unittest from typing import Final, List, Optional, Tuple @@ -10,7 +8,6 @@ from unittest.mock import ANY, AsyncMock, MagicMock, Mock, patch import pytest -sys.path.insert(0, os.path.abspath("../../..")) # Adds the parent directory to the system-path import litellm from litellm.caching.caching import DualCache from litellm.integrations.SlackAlerting.slack_alerting import SlackAlerting diff --git a/tests/test_litellm/integrations/SlackAlerting/test_slack_alerting_digest.py b/tests/test_litellm/integrations/SlackAlerting/test_slack_alerting_digest.py index b3fee1f045b..edce5c5f3a2 100644 --- a/tests/test_litellm/integrations/SlackAlerting/test_slack_alerting_digest.py +++ b/tests/test_litellm/integrations/SlackAlerting/test_slack_alerting_digest.py @@ -10,11 +10,9 @@ Verifies that: """ import os -import sys import unittest from datetime import datetime, timedelta -sys.path.insert(0, os.path.abspath("../../..")) from litellm.integrations.SlackAlerting.slack_alerting import SlackAlerting from litellm.proxy._types import AlertType diff --git a/tests/test_litellm/integrations/SlackAlerting/test_slack_alerting_utils.py b/tests/test_litellm/integrations/SlackAlerting/test_slack_alerting_utils.py index 027fed1b5ff..403cd51701d 100644 --- a/tests/test_litellm/integrations/SlackAlerting/test_slack_alerting_utils.py +++ b/tests/test_litellm/integrations/SlackAlerting/test_slack_alerting_utils.py @@ -1,13 +1,10 @@ import json -import os -import sys from typing import Optional from unittest.mock import MagicMock import pytest # Adds the grandparent directory to sys.path to allow importing project modules -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm.integrations.langfuse.langfuse_prompt_management import ( diff --git a/tests/test_litellm/integrations/arize/test_arize.py b/tests/test_litellm/integrations/arize/test_arize.py index 1ca3349eeb7..cdafd856b49 100644 --- a/tests/test_litellm/integrations/arize/test_arize.py +++ b/tests/test_litellm/integrations/arize/test_arize.py @@ -1,11 +1,8 @@ import json -import os -import sys from typing import Optional from unittest.mock import MagicMock, Mock, patch # Adds the grandparent directory to sys.path to allow importing project modules -sys.path.insert(0, os.path.abspath("../..")) import asyncio diff --git a/tests/test_litellm/integrations/arize/test_arize_health_check.py b/tests/test_litellm/integrations/arize/test_arize_health_check.py index 3f10e9dcbd7..f7364dc27eb 100644 --- a/tests/test_litellm/integrations/arize/test_arize_health_check.py +++ b/tests/test_litellm/integrations/arize/test_arize_health_check.py @@ -4,11 +4,9 @@ Test Arize health check functionality and proxy integration. import json import os -import sys from unittest.mock import patch, MagicMock # Adds the grandparent directory to sys.path to allow importing project modules -sys.path.insert(0, os.path.abspath("../..")) import asyncio import pytest diff --git a/tests/test_litellm/integrations/arize/test_arize_utils.py b/tests/test_litellm/integrations/arize/test_arize_utils.py index b02fe35cad0..50f2823d632 100644 --- a/tests/test_litellm/integrations/arize/test_arize_utils.py +++ b/tests/test_litellm/integrations/arize/test_arize_utils.py @@ -1,10 +1,7 @@ import json -import os -import sys from typing import Optional # Adds the grandparent directory to sys.path to allow importing project modules -sys.path.insert(0, os.path.abspath("../..")) import asyncio diff --git a/tests/test_litellm/integrations/azure_storage/test_azure_storage.py b/tests/test_litellm/integrations/azure_storage/test_azure_storage.py index 5d7c55e81af..16c518ff412 100644 --- a/tests/test_litellm/integrations/azure_storage/test_azure_storage.py +++ b/tests/test_litellm/integrations/azure_storage/test_azure_storage.py @@ -1,12 +1,8 @@ -import os import sys from unittest.mock import AsyncMock, MagicMock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from litellm.integrations.azure_storage.azure_storage import AzureBlobStorageLogger from litellm.types.utils import StandardLoggingPayload diff --git a/tests/test_litellm/integrations/bitbucket/test_bitbucket_integration.py b/tests/test_litellm/integrations/bitbucket/test_bitbucket_integration.py index 142be536f6b..955821f66e0 100644 --- a/tests/test_litellm/integrations/bitbucket/test_bitbucket_integration.py +++ b/tests/test_litellm/integrations/bitbucket/test_bitbucket_integration.py @@ -1,13 +1,8 @@ import json -import os -import sys from unittest.mock import MagicMock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path import litellm from litellm.integrations.bitbucket import BitBucketPromptManager diff --git a/tests/test_litellm/integrations/bitbucket/test_bitbucket_prompt_manager.py b/tests/test_litellm/integrations/bitbucket/test_bitbucket_prompt_manager.py index 4a15da87c89..d6668bf9ad8 100644 --- a/tests/test_litellm/integrations/bitbucket/test_bitbucket_prompt_manager.py +++ b/tests/test_litellm/integrations/bitbucket/test_bitbucket_prompt_manager.py @@ -1,14 +1,9 @@ import json -import os import re -import sys from unittest.mock import MagicMock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from litellm.integrations.bitbucket.bitbucket_client import BitBucketClient from litellm.integrations.bitbucket.bitbucket_prompt_manager import ( diff --git a/tests/test_litellm/integrations/cloudzero/test_cz_stream_api.py b/tests/test_litellm/integrations/cloudzero/test_cz_stream_api.py index a715116e5ee..1a95e45b2d5 100644 --- a/tests/test_litellm/integrations/cloudzero/test_cz_stream_api.py +++ b/tests/test_litellm/integrations/cloudzero/test_cz_stream_api.py @@ -1,5 +1,3 @@ -import os -import sys import zoneinfo from datetime import datetime, timezone from unittest.mock import MagicMock, Mock, patch @@ -8,7 +6,6 @@ import httpx import polars as pl import pytest -sys.path.insert(0, os.path.abspath("../../../..")) from litellm.integrations.cloudzero.cz_stream_api import CloudZeroStreamer diff --git a/tests/test_litellm/integrations/cloudzero/test_dry_run_endpoint.py b/tests/test_litellm/integrations/cloudzero/test_dry_run_endpoint.py index c5f377aa09b..795692f2cdf 100644 --- a/tests/test_litellm/integrations/cloudzero/test_dry_run_endpoint.py +++ b/tests/test_litellm/integrations/cloudzero/test_dry_run_endpoint.py @@ -2,14 +2,11 @@ Test the CloudZero dry run endpoint functionality """ -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import polars as pl import pytest -sys.path.insert(0, os.path.abspath("../../../..")) from litellm.integrations.cloudzero.cloudzero import CloudZeroLogger diff --git a/tests/test_litellm/integrations/cloudzero/test_transform.py b/tests/test_litellm/integrations/cloudzero/test_transform.py index 416eacdc63a..3ec2fe6779e 100644 --- a/tests/test_litellm/integrations/cloudzero/test_transform.py +++ b/tests/test_litellm/integrations/cloudzero/test_transform.py @@ -1,12 +1,9 @@ -import os -import sys from datetime import datetime from unittest.mock import MagicMock, patch import polars as pl import pytest -sys.path.insert(0, os.path.abspath("../../../..")) from litellm.integrations.cloudzero.transform import CBFTransformer from litellm.types.integrations.cloudzero import CBFRecord diff --git a/tests/test_litellm/integrations/datadog/test_datadog_tags_regression.py b/tests/test_litellm/integrations/datadog/test_datadog_tags_regression.py index 624995085aa..110ac75e73b 100644 --- a/tests/test_litellm/integrations/datadog/test_datadog_tags_regression.py +++ b/tests/test_litellm/integrations/datadog/test_datadog_tags_regression.py @@ -1,11 +1,9 @@ import datetime import os -import sys from unittest.mock import patch import pytest -sys.path.insert(0, os.path.abspath("../../../")) from litellm.integrations.datadog.datadog import DataDogLogger from litellm.integrations.datadog.datadog_handler import get_datadog_tags, normalize_datadog_tag_value diff --git a/tests/test_litellm/integrations/dotprompt/test_prompt_manager.py b/tests/test_litellm/integrations/dotprompt/test_prompt_manager.py index d849582b3c4..b92ed13302e 100644 --- a/tests/test_litellm/integrations/dotprompt/test_prompt_manager.py +++ b/tests/test_litellm/integrations/dotprompt/test_prompt_manager.py @@ -1,15 +1,10 @@ import json -import os -import sys import tempfile from pathlib import Path import pytest from fastapi.testclient import TestClient -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from unittest.mock import MagicMock, Mock, patch diff --git a/tests/test_litellm/integrations/gcs_pubsub/test_pub_sub.py b/tests/test_litellm/integrations/gcs_pubsub/test_pub_sub.py index 7ff28bfe831..3c7f577d1d8 100644 --- a/tests/test_litellm/integrations/gcs_pubsub/test_pub_sub.py +++ b/tests/test_litellm/integrations/gcs_pubsub/test_pub_sub.py @@ -1,7 +1,6 @@ import datetime import json import os -import sys import unittest from typing import List, Optional, Tuple from unittest.mock import ANY, MagicMock, Mock, patch @@ -9,9 +8,6 @@ from unittest.mock import ANY, MagicMock, Mock, patch import httpx import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system-path import litellm diff --git a/tests/test_litellm/integrations/gitlab/test_gitlab_client.py b/tests/test_litellm/integrations/gitlab/test_gitlab_client.py index 529868ca06a..d6f588c4965 100644 --- a/tests/test_litellm/integrations/gitlab/test_gitlab_client.py +++ b/tests/test_litellm/integrations/gitlab/test_gitlab_client.py @@ -1,13 +1,8 @@ import base64 import json -import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from litellm.integrations.gitlab.gitlab_client import GitLabClient diff --git a/tests/test_litellm/integrations/gitlab/test_gitlab_integration.py b/tests/test_litellm/integrations/gitlab/test_gitlab_integration.py index 8118af56b0e..7d5b490fea4 100644 --- a/tests/test_litellm/integrations/gitlab/test_gitlab_integration.py +++ b/tests/test_litellm/integrations/gitlab/test_gitlab_integration.py @@ -1,12 +1,7 @@ -import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from unittest.mock import MagicMock, patch from litellm.integrations.gitlab.gitlab_prompt_manager import GitLabPromptManager diff --git a/tests/test_litellm/integrations/gitlab/test_gitlab_prompt_manager.py b/tests/test_litellm/integrations/gitlab/test_gitlab_prompt_manager.py index adccd94141f..120cc877b51 100644 --- a/tests/test_litellm/integrations/gitlab/test_gitlab_prompt_manager.py +++ b/tests/test_litellm/integrations/gitlab/test_gitlab_prompt_manager.py @@ -1,13 +1,8 @@ -import os import re -import sys from unittest.mock import MagicMock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from litellm.integrations.gitlab.gitlab_client import GitLabClient from litellm.integrations.gitlab.gitlab_prompt_manager import ( diff --git a/tests/test_litellm/integrations/open_telemetry/conftest.py b/tests/test_litellm/integrations/open_telemetry/conftest.py index b29335aedd8..367e9fba07f 100644 --- a/tests/test_litellm/integrations/open_telemetry/conftest.py +++ b/tests/test_litellm/integrations/open_telemetry/conftest.py @@ -11,8 +11,6 @@ emitter in isolation. See ``LIT-3193_test_matrix.md`` (same directory) for the cell list. """ -import os -import sys from datetime import datetime from typing import Optional, Tuple from unittest.mock import MagicMock @@ -24,7 +22,6 @@ from opentelemetry.sdk.trace.export.in_memory_span_exporter import ( InMemorySpanExporter, ) -sys.path.insert(0, os.path.abspath("../../..")) import litellm from litellm.integrations.opentelemetry import OpenTelemetry diff --git a/tests/test_litellm/integrations/otel/test_otel_v2_dynamic.py b/tests/test_litellm/integrations/otel/test_otel_v2_dynamic.py index ca62253aa2f..a9a78dcb2f1 100644 --- a/tests/test_litellm/integrations/otel/test_otel_v2_dynamic.py +++ b/tests/test_litellm/integrations/otel/test_otel_v2_dynamic.py @@ -1,10 +1,7 @@ """Per-request multi-tenant credential routing (V1 parity).""" import base64 -import os -import sys -sys.path.insert(0, os.path.abspath("../../../..")) from opentelemetry.trace import NoOpTracer diff --git a/tests/test_litellm/integrations/otel/test_otel_v2_mount.py b/tests/test_litellm/integrations/otel/test_otel_v2_mount.py index 7240d49d022..0cd71db4ae1 100644 --- a/tests/test_litellm/integrations/otel/test_otel_v2_mount.py +++ b/tests/test_litellm/integrations/otel/test_otel_v2_mount.py @@ -4,12 +4,9 @@ surface and the server-span + shared-provider behavior it produces. """ -import os -import sys import pytest -sys.path.insert(0, os.path.abspath("../../../..")) pytest.importorskip("opentelemetry") pytest.importorskip("opentelemetry.instrumentation.fastapi") diff --git a/tests/test_litellm/integrations/otel/test_otel_v2_sources_of_truth.py b/tests/test_litellm/integrations/otel/test_otel_v2_sources_of_truth.py index 19d0cfc0b18..2a66d5ee139 100644 --- a/tests/test_litellm/integrations/otel/test_otel_v2_sources_of_truth.py +++ b/tests/test_litellm/integrations/otel/test_otel_v2_sources_of_truth.py @@ -4,6 +4,7 @@ and the typed StandardLoggingPayload adapter. These need no OTel SDK.""" import logging import re from pathlib import Path +from typing import Final import pytest @@ -14,6 +15,7 @@ from litellm.integrations.otel import ( Error, GenAI, GenAIOperation, + GenAIOutputType, HTTP, LiteLLM, OpenTelemetryV2Config, @@ -21,8 +23,10 @@ from litellm.integrations.otel import ( is_otel_v2_enabled, promoted_baggage, resolve_operation, + resolve_output_type, resolve_provider, ) +from litellm.integrations.otel.mappers.genai import GenAIMapper from litellm.integrations.otel.model import spans as spans_mod from litellm.integrations.otel.model.payloads import ( LLMCallSpanData, @@ -264,6 +268,74 @@ def test_vector_store_file_management_is_not_chat(call_type): assert resolve_operation(call_type).value == "litellm.vector_store_file_management" +_NON_CHAT_ROUTES: Final = ( + ("image_generation", GenAIOperation.GENERATE_CONTENT, GenAIOutputType.IMAGE), + ("speech", GenAIOperation.GENERATE_CONTENT, GenAIOutputType.SPEECH), + ("transcription", GenAIOperation.GENERATE_CONTENT, GenAIOutputType.TEXT), + ("ocr", GenAIOperation.GENERATE_CONTENT, GenAIOutputType.TEXT), + ("moderation", GenAIOperation.LITELLM_MODERATION, None), +) + + +@pytest.mark.parametrize( + ("call_type", "operation", "output_type"), + [ + (f"{prefix}{call_type}", operation, output_type) + for call_type, operation, output_type in _NON_CHAT_ROUTES + for prefix in ("", "a") + ], +) +def test_non_chat_inference_routes_follow_genai_semconv(call_type, operation, output_type): + """Image generation, speech, transcription and OCR all produce content, so the + convention names them ``generate_content`` and separates them by the requested + output modality rather than by an invented operation. Moderation classifies + instead of generating and the convention names nothing for it, so it keeps a + vendor value. Either way the spans must not land in the chat series a dashboard + reads.""" + assert resolve_operation(call_type) is operation + assert resolve_output_type(call_type) is output_type + + +@pytest.mark.parametrize( + ("call_type", "operation", "output_type"), + [(f"a{call_type}", operation, output_type) for call_type, operation, output_type in _NON_CHAT_ROUTES], +) +def test_non_chat_route_spans_carry_semconv_name_and_modality(call_type, operation, output_type): + """The emitted span, not just the mapping table: name is + ``{gen_ai.operation.name} {gen_ai.request.model}``, the modality rides + ``gen_ai.output.type``, and the route stays recoverable from + ``litellm.call_type`` now that several routes share one operation.""" + data = LLMCallSpanData.from_standard_logging_payload( + _sample_payload(call_type=call_type, model="some-model", custom_llm_provider="openai") + ) + attrs = GenAIMapper().map(data) + + assert spans_mod.llm_call_span_name(data) == f"{operation.value} some-model" + assert attrs[GenAI.OPERATION_NAME] == operation.value + assert attrs[GenAI.PROVIDER_NAME] == "openai" + assert attrs[GenAI.REQUEST_MODEL] == "some-model" + assert attrs[LiteLLM.CALL_TYPE] == call_type + assert attrs.get(GenAI.OUTPUT_TYPE) == (output_type.value if output_type else None) + + +def test_non_chat_route_error_span_keeps_error_attributes(): + """Modality mapping must not cost the failure signal: a failed non-chat call + still carries the error type alongside the standardized operation.""" + data = LLMCallSpanData.from_standard_logging_payload( + _sample_payload( + call_type="aspeech", + model="tts-1", + status="failure", + error_information={"error_class": "BadRequestError"}, + ) + ) + attrs = GenAIMapper().map(data) + + assert attrs[GenAI.OPERATION_NAME] == GenAIOperation.GENERATE_CONTENT.value + assert attrs[GenAI.OUTPUT_TYPE] == GenAIOutputType.SPEECH.value + assert attrs[Error.TYPE] == "BadRequestError" + + def test_vendor_operation_values_are_namespaced(): """A vendor value must stay under the ``litellm.`` prefix: an unprefixed invented name could collide with a value the convention adds later, silently changing what diff --git a/tests/test_litellm/integrations/test_agentops.py b/tests/test_litellm/integrations/test_agentops.py index 85ee34a0d8c..5d4055ac75f 100644 --- a/tests/test_litellm/integrations/test_agentops.py +++ b/tests/test_litellm/integrations/test_agentops.py @@ -1,12 +1,8 @@ import os -import sys from unittest.mock import MagicMock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system-path from litellm.integrations.agentops.agentops import AgentOps, AgentOpsConfig diff --git a/tests/test_litellm/integrations/test_anthropic_cache_control_hook.py b/tests/test_litellm/integrations/test_anthropic_cache_control_hook.py index 7bf15f59eb9..b6e063a6d94 100644 --- a/tests/test_litellm/integrations/test_anthropic_cache_control_hook.py +++ b/tests/test_litellm/integrations/test_anthropic_cache_control_hook.py @@ -12,7 +12,6 @@ from unittest.mock import ANY, MagicMock, Mock, patch import httpx import pytest -sys.path.insert(0, os.path.abspath("../..")) # Adds the parent directory to the system-path import litellm from litellm.integrations.anthropic_cache_control_hook import ( AnthropicCacheControlHook, @@ -37,7 +36,7 @@ def _rendered_log_message(call): @pytest.mark.asyncio -async def test_anthropic_cache_control_hook_system_message(): +async def test_anthropic_cache_control_hook_system_message(monkeypatch: pytest.MonkeyPatch): # Use patch.dict to mock environment variables instead of setting them directly with patch.dict( os.environ, @@ -48,7 +47,7 @@ async def test_anthropic_cache_control_hook_system_message(): }, ): anthropic_cache_control_hook = AnthropicCacheControlHook() - litellm.callbacks = [anthropic_cache_control_hook] + monkeypatch.setattr(litellm, "callbacks", [anthropic_cache_control_hook]) # Mock response data mock_response = MagicMock() @@ -116,7 +115,7 @@ async def test_anthropic_cache_control_hook_system_message(): @pytest.mark.asyncio -async def test_anthropic_cache_control_hook_user_message(): +async def test_anthropic_cache_control_hook_user_message(monkeypatch: pytest.MonkeyPatch): # Use patch.dict to mock environment variables instead of setting them directly with patch.dict( os.environ, @@ -127,7 +126,7 @@ async def test_anthropic_cache_control_hook_user_message(): }, ): anthropic_cache_control_hook = AnthropicCacheControlHook() - litellm.callbacks = [anthropic_cache_control_hook] + monkeypatch.setattr(litellm, "callbacks", [anthropic_cache_control_hook]) # Mock response data mock_response = MagicMock() @@ -188,7 +187,7 @@ async def test_anthropic_cache_control_hook_user_message(): @pytest.mark.asyncio -async def test_anthropic_cache_control_hook_negative_indices(): +async def test_anthropic_cache_control_hook_negative_indices(monkeypatch: pytest.MonkeyPatch): """ Test the bug fix for handling negative indices in cache control injection points. This test verifies that negative indices (-1, -2) are properly converted to positive indices @@ -204,7 +203,7 @@ async def test_anthropic_cache_control_hook_negative_indices(): }, ): anthropic_cache_control_hook = AnthropicCacheControlHook() - litellm.callbacks = [anthropic_cache_control_hook] + monkeypatch.setattr(litellm, "callbacks", [anthropic_cache_control_hook]) # Mock response data mock_response = MagicMock() @@ -302,7 +301,7 @@ async def test_anthropic_cache_control_hook_negative_indices(): @pytest.mark.asyncio -async def test_anthropic_cache_control_hook_out_of_bounds_logging(): +async def test_anthropic_cache_control_hook_out_of_bounds_logging(monkeypatch: pytest.MonkeyPatch): """ Test that warning logs are generated when out-of-bounds indices are used. This verifies that the verbose_logger.warning is called with the correct message. @@ -316,7 +315,7 @@ async def test_anthropic_cache_control_hook_out_of_bounds_logging(): }, ): anthropic_cache_control_hook = AnthropicCacheControlHook() - litellm.callbacks = [anthropic_cache_control_hook] + monkeypatch.setattr(litellm, "callbacks", [anthropic_cache_control_hook]) # Mock response data mock_response = MagicMock() @@ -365,7 +364,7 @@ async def test_anthropic_cache_control_hook_out_of_bounds_logging(): @pytest.mark.asyncio -async def test_anthropic_cache_control_hook_negative_out_of_bounds_logging(): +async def test_anthropic_cache_control_hook_negative_out_of_bounds_logging(monkeypatch: pytest.MonkeyPatch): """ Test that warning logs are generated for negative indices that are out of bounds. """ @@ -378,7 +377,7 @@ async def test_anthropic_cache_control_hook_negative_out_of_bounds_logging(): }, ): anthropic_cache_control_hook = AnthropicCacheControlHook() - litellm.callbacks = [anthropic_cache_control_hook] + monkeypatch.setattr(litellm, "callbacks", [anthropic_cache_control_hook]) # Mock response data mock_response = MagicMock() @@ -431,7 +430,7 @@ async def test_anthropic_cache_control_hook_negative_out_of_bounds_logging(): @pytest.mark.asyncio -async def test_anthropic_cache_control_hook_multiple_user_messages(): +async def test_anthropic_cache_control_hook_multiple_user_messages(monkeypatch: pytest.MonkeyPatch): """ Test cache control injection on multiple user messages specifically. Note: Bedrock API combines consecutive user messages into a single message with multiple content blocks. @@ -445,7 +444,7 @@ async def test_anthropic_cache_control_hook_multiple_user_messages(): }, ): anthropic_cache_control_hook = AnthropicCacheControlHook() - litellm.callbacks = [anthropic_cache_control_hook] + monkeypatch.setattr(litellm, "callbacks", [anthropic_cache_control_hook]) # Mock response data mock_response = MagicMock() @@ -523,7 +522,7 @@ async def test_anthropic_cache_control_hook_multiple_user_messages(): @pytest.mark.asyncio @pytest.mark.parametrize("bad_index", [10, -10]) -async def test_anthropic_cache_control_hook_out_of_bounds(bad_index): +async def test_anthropic_cache_control_hook_out_of_bounds(bad_index, monkeypatch: pytest.MonkeyPatch): """ Verify the hook does not raise an error and makes no changes when an out-of-bounds index is provided. @@ -537,7 +536,7 @@ async def test_anthropic_cache_control_hook_out_of_bounds(bad_index): }, ): anthropic_cache_control_hook = AnthropicCacheControlHook() - litellm.callbacks = [anthropic_cache_control_hook] + monkeypatch.setattr(litellm, "callbacks", [anthropic_cache_control_hook]) # Mock response data mock_response = MagicMock() @@ -586,7 +585,7 @@ async def test_anthropic_cache_control_hook_out_of_bounds(bad_index): "message_list", [[{"role": "user", "content": "Single message"}]], # Single message only - empty list will fail at API level ) -async def test_anthropic_cache_control_hook_single_message(message_list): +async def test_anthropic_cache_control_hook_single_message(message_list, monkeypatch: pytest.MonkeyPatch): """ Verify the hook runs without error on very short message lists. """ @@ -599,7 +598,7 @@ async def test_anthropic_cache_control_hook_single_message(message_list): }, ): anthropic_cache_control_hook = AnthropicCacheControlHook() - litellm.callbacks = [anthropic_cache_control_hook] + monkeypatch.setattr(litellm, "callbacks", [anthropic_cache_control_hook]) # Mock response data mock_response = MagicMock() @@ -637,7 +636,7 @@ async def test_anthropic_cache_control_hook_single_message(message_list): @pytest.mark.asyncio -async def test_anthropic_cache_control_hook_empty_message_list(): +async def test_anthropic_cache_control_hook_empty_message_list(monkeypatch: pytest.MonkeyPatch): """ Verify that empty message lists are handled appropriately (should fail at API level, not hook level). """ @@ -650,7 +649,7 @@ async def test_anthropic_cache_control_hook_empty_message_list(): }, ): anthropic_cache_control_hook = AnthropicCacheControlHook() - litellm.callbacks = [anthropic_cache_control_hook] + monkeypatch.setattr(litellm, "callbacks", [anthropic_cache_control_hook]) client = AsyncHTTPHandler() with patch.object(client, "post", return_value=MagicMock()) as mock_post: @@ -668,7 +667,7 @@ async def test_anthropic_cache_control_hook_empty_message_list(): @pytest.mark.asyncio -async def test_anthropic_cache_control_hook_no_op(): +async def test_anthropic_cache_control_hook_no_op(monkeypatch: pytest.MonkeyPatch): """ Verify that if no injection points are specified, messages remain unmodified. """ @@ -681,7 +680,7 @@ async def test_anthropic_cache_control_hook_no_op(): }, ): anthropic_cache_control_hook = AnthropicCacheControlHook() - litellm.callbacks = [anthropic_cache_control_hook] + monkeypatch.setattr(litellm, "callbacks", [anthropic_cache_control_hook]) # Mock response data mock_response = MagicMock() @@ -726,7 +725,7 @@ async def test_anthropic_cache_control_hook_no_op(): @pytest.mark.asyncio -async def test_anthropic_cache_control_hook_multiple_content_items_last_only(): +async def test_anthropic_cache_control_hook_multiple_content_items_last_only(monkeypatch: pytest.MonkeyPatch): """ Test that cache_control is only applied to the last content item in a list, not all items. This verifies the fix for https://github.com/BerriAI/litellm/issues/15696 @@ -740,7 +739,7 @@ async def test_anthropic_cache_control_hook_multiple_content_items_last_only(): }, ): anthropic_cache_control_hook = AnthropicCacheControlHook() - litellm.callbacks = [anthropic_cache_control_hook] + monkeypatch.setattr(litellm, "callbacks", [anthropic_cache_control_hook]) mock_response = MagicMock() mock_response.json.return_value = { @@ -797,7 +796,7 @@ async def test_anthropic_cache_control_hook_multiple_content_items_last_only(): @pytest.mark.asyncio -async def test_anthropic_cache_control_hook_document_analysis_multiple_pages(): +async def test_anthropic_cache_control_hook_document_analysis_multiple_pages(monkeypatch: pytest.MonkeyPatch): """ Test cache_control with multiple document pages to ensure only the last page gets cached. This simulates document analysis with 6 content blocks, verifying the fix for issue 15696. @@ -811,7 +810,7 @@ async def test_anthropic_cache_control_hook_document_analysis_multiple_pages(): }, ): anthropic_cache_control_hook = AnthropicCacheControlHook() - litellm.callbacks = [anthropic_cache_control_hook] + monkeypatch.setattr(litellm, "callbacks", [anthropic_cache_control_hook]) mock_response = MagicMock() mock_response.json.return_value = { @@ -969,7 +968,7 @@ def test_gemini_cache_control_injection_list_content_detected(): @pytest.mark.asyncio -async def test_anthropic_cache_control_hook_string_negative_index(): +async def test_anthropic_cache_control_hook_string_negative_index(monkeypatch: pytest.MonkeyPatch): """ Test that string negative indices like "-1" are handled correctly. @@ -986,7 +985,7 @@ async def test_anthropic_cache_control_hook_string_negative_index(): }, ): anthropic_cache_control_hook = AnthropicCacheControlHook() - litellm.callbacks = [anthropic_cache_control_hook] + monkeypatch.setattr(litellm, "callbacks", [anthropic_cache_control_hook]) mock_response = MagicMock() mock_response.json.return_value = { @@ -1185,7 +1184,7 @@ def test_cache_control_hook_does_not_overwrite_existing_cache_control(): @pytest.mark.asyncio -async def test_cache_control_hook_bedrock_payload_caps_cachepoints_at_four(): +async def test_cache_control_hook_bedrock_payload_caps_cachepoints_at_four(monkeypatch: pytest.MonkeyPatch): """End-to-end: outgoing Bedrock payload must not exceed 4 cachePoint blocks. Reproduces the customer report where 4 client cache_control system blocks @@ -1199,7 +1198,7 @@ async def test_cache_control_hook_bedrock_payload_caps_cachepoints_at_four(): "AWS_REGION_NAME": "us-east-1", }, ): - litellm.callbacks = [AnthropicCacheControlHook()] + monkeypatch.setattr(litellm, "callbacks", [AnthropicCacheControlHook()]) mock_response = MagicMock() mock_response.json.return_value = { @@ -1289,7 +1288,7 @@ def test_cache_control_hook_reserves_slot_for_tool_config_point(): @pytest.mark.asyncio -async def test_cache_control_hook_bedrock_payload_caps_with_tool_config_point(): +async def test_cache_control_hook_bedrock_payload_caps_with_tool_config_point(monkeypatch: pytest.MonkeyPatch): """End-to-end: message + tool_config injection must not exceed 4 cachePoints.""" with patch.dict( os.environ, @@ -1299,7 +1298,7 @@ async def test_cache_control_hook_bedrock_payload_caps_with_tool_config_point(): "AWS_REGION_NAME": "us-east-1", }, ): - litellm.callbacks = [AnthropicCacheControlHook()] + monkeypatch.setattr(litellm, "callbacks", [AnthropicCacheControlHook()]) mock_response = MagicMock() mock_response.json.return_value = { diff --git a/tests/test_litellm/integrations/test_athina.py b/tests/test_litellm/integrations/test_athina.py index 49d8fc693e7..4f64f26db9a 100644 --- a/tests/test_litellm/integrations/test_athina.py +++ b/tests/test_litellm/integrations/test_athina.py @@ -1,13 +1,8 @@ import datetime import json -import os -import sys import unittest from unittest.mock import ANY, MagicMock, patch -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system-path from litellm.integrations.athina import AthinaLogger diff --git a/tests/test_litellm/integrations/test_custom_prompt_management.py b/tests/test_litellm/integrations/test_custom_prompt_management.py index 7d5d02bf4b6..0bf2063a98d 100644 --- a/tests/test_litellm/integrations/test_custom_prompt_management.py +++ b/tests/test_litellm/integrations/test_custom_prompt_management.py @@ -1,7 +1,5 @@ import datetime import json -import os -import sys import unittest from typing import List, Optional, Tuple from unittest.mock import ANY, MagicMock, Mock, patch @@ -9,9 +7,6 @@ from unittest.mock import ANY, MagicMock, Mock, patch import httpx import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system-path import litellm from litellm.integrations.custom_prompt_management import CustomPromptManagement from litellm.llms.custom_httpx.http_handler import AsyncHTTPHandler diff --git a/tests/test_litellm/integrations/test_galileo.py b/tests/test_litellm/integrations/test_galileo.py index 8905795bbc6..d0709b966d4 100644 --- a/tests/test_litellm/integrations/test_galileo.py +++ b/tests/test_litellm/integrations/test_galileo.py @@ -1,11 +1,8 @@ -import os -import sys from datetime import datetime, timezone from unittest.mock import AsyncMock, MagicMock, patch import pytest -sys.path.insert(0, os.path.abspath("../..")) from litellm.integrations.galileo import GalileoObserve from litellm.types.llms.openai import HttpxBinaryResponseContent, ResponsesAPIResponse diff --git a/tests/test_litellm/integrations/test_helicone.py b/tests/test_litellm/integrations/test_helicone.py index da07fa1a9bf..64960de050a 100644 --- a/tests/test_litellm/integrations/test_helicone.py +++ b/tests/test_litellm/integrations/test_helicone.py @@ -1,8 +1,6 @@ -import os import sys import types -sys.path.insert(0, os.path.abspath("../../..")) from litellm.integrations.helicone import HeliconeLogger diff --git a/tests/test_litellm/integrations/test_langfuse.py b/tests/test_litellm/integrations/test_langfuse.py index 73a62e5594d..747f733a46d 100644 --- a/tests/test_litellm/integrations/test_langfuse.py +++ b/tests/test_litellm/integrations/test_langfuse.py @@ -1,6 +1,5 @@ import datetime import json -import os import sys import types import unittest @@ -13,7 +12,6 @@ import litellm from litellm.integrations.langfuse import langfuse as langfuse_module from litellm.integrations.langfuse.langfuse import LangFuseLogger -sys.path.insert(0, os.path.abspath("../..")) # Import LangfuseUsageDetails directly from the module where it's defined from litellm.types.integrations.langfuse import * diff --git a/tests/test_litellm/integrations/test_langsmith_init.py b/tests/test_litellm/integrations/test_langsmith_init.py index 129dda4abde..d3393ac3d28 100644 --- a/tests/test_litellm/integrations/test_langsmith_init.py +++ b/tests/test_litellm/integrations/test_langsmith_init.py @@ -1,10 +1,8 @@ import os -import sys from unittest.mock import MagicMock, patch import pytest -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm.integrations.langsmith import LangsmithLogger diff --git a/tests/test_litellm/integrations/test_lunary.py b/tests/test_litellm/integrations/test_lunary.py index 0a1ec100594..6491f5c8b82 100644 --- a/tests/test_litellm/integrations/test_lunary.py +++ b/tests/test_litellm/integrations/test_lunary.py @@ -1,7 +1,4 @@ -import os -import sys -sys.path.insert(0, os.path.abspath("../../..")) from litellm.integrations.lunary import parse_tool_calls from litellm.types.utils import ( diff --git a/tests/test_litellm/integrations/test_mlflow.py b/tests/test_litellm/integrations/test_mlflow.py index 32358641984..61010f8531c 100644 --- a/tests/test_litellm/integrations/test_mlflow.py +++ b/tests/test_litellm/integrations/test_mlflow.py @@ -1,12 +1,9 @@ import asyncio import json -import os -import sys from datetime import datetime from unittest.mock import MagicMock, patch # Adds the grandparent directory to sys.path to allow importing project modules -sys.path.insert(0, os.path.abspath("../..")) import pytest diff --git a/tests/test_litellm/integrations/test_opentelemetry.py b/tests/test_litellm/integrations/test_opentelemetry.py index a5ad3d771e3..229214bf1e1 100644 --- a/tests/test_litellm/integrations/test_opentelemetry.py +++ b/tests/test_litellm/integrations/test_opentelemetry.py @@ -14,7 +14,6 @@ from parameterized import parameterized from unittest.mock import MagicMock, patch # Adds the grandparent directory to sys.path to allow importing project modules -sys.path.insert(0, os.path.abspath("../..")) from opentelemetry import trace from opentelemetry.sdk._logs import LoggerProvider as OTLoggerProvider from opentelemetry.sdk._logs.export import InMemoryLogExporter, SimpleLogRecordProcessor diff --git a/tests/test_litellm/integrations/test_otel_guardrail_violation_spans.py b/tests/test_litellm/integrations/test_otel_guardrail_violation_spans.py index c3e9d67ddad..16d77fe38a5 100644 --- a/tests/test_litellm/integrations/test_otel_guardrail_violation_spans.py +++ b/tests/test_litellm/integrations/test_otel_guardrail_violation_spans.py @@ -24,8 +24,6 @@ real ``OpenTelemetry`` integration. No monkey patching of the integration under test — only the OTEL exporter is in-memory. """ -import os -import sys import time import unittest from datetime import datetime, timedelta, timezone @@ -35,7 +33,6 @@ from opentelemetry.sdk.trace.export import SimpleSpanProcessor from opentelemetry.sdk.trace.export.in_memory_span_exporter import InMemorySpanExporter from opentelemetry.trace import StatusCode -sys.path.insert(0, os.path.abspath("../..")) from litellm.integrations.opentelemetry import ( LITELLM_REQUEST_SPAN_NAME, diff --git a/tests/test_litellm/integrations/test_otel_team_attributes_matrix.py b/tests/test_litellm/integrations/test_otel_team_attributes_matrix.py index 1ce55fa7a58..daf7d0fdaf0 100644 --- a/tests/test_litellm/integrations/test_otel_team_attributes_matrix.py +++ b/tests/test_litellm/integrations/test_otel_team_attributes_matrix.py @@ -31,8 +31,6 @@ Strategy """ import asyncio -import os -import sys import unittest from datetime import datetime from unittest.mock import MagicMock @@ -43,7 +41,6 @@ from opentelemetry.sdk.trace.export.in_memory_span_exporter import ( InMemorySpanExporter, ) -sys.path.insert(0, os.path.abspath("../..")) from litellm.integrations.opentelemetry import ( LITELLM_PROXY_REQUEST_SPAN_NAME, diff --git a/tests/test_litellm/integrations/test_prometheus_invalid_key_filtering.py b/tests/test_litellm/integrations/test_prometheus_invalid_key_filtering.py index 5dbe487ab0a..278a4ef1df6 100644 --- a/tests/test_litellm/integrations/test_prometheus_invalid_key_filtering.py +++ b/tests/test_litellm/integrations/test_prometheus_invalid_key_filtering.py @@ -5,14 +5,11 @@ Tests functionality that prevents invalid API key requests (401 status codes) from being recorded in Prometheus metrics. """ -import os -import sys from unittest.mock import Mock, patch import pytest from prometheus_client import REGISTRY -sys.path.insert(0, os.path.abspath("../../..")) from litellm.integrations.prometheus import PrometheusLogger from litellm.proxy._types import UserAPIKeyAuth diff --git a/tests/test_litellm/integrations/test_prometheus_none_metadata.py b/tests/test_litellm/integrations/test_prometheus_none_metadata.py index fff2e48bf5a..c2d4c831609 100644 --- a/tests/test_litellm/integrations/test_prometheus_none_metadata.py +++ b/tests/test_litellm/integrations/test_prometheus_none_metadata.py @@ -6,14 +6,11 @@ can be None, causing AttributeError: 'NoneType' object has no attribute 'get' in set_llm_deployment_success_metrics. """ -import os -import sys from datetime import datetime import pytest from prometheus_client import REGISTRY -sys.path.insert(0, os.path.abspath("../../..")) from litellm.integrations.prometheus import PrometheusLogger from litellm.types.integrations.prometheus import UserAPIKeyLabelValues diff --git a/tests/test_litellm/integrations/test_prometheus_remaining_tokens_router_fallback.py b/tests/test_litellm/integrations/test_prometheus_remaining_tokens_router_fallback.py index d754de86569..45b378d10fe 100644 --- a/tests/test_litellm/integrations/test_prometheus_remaining_tokens_router_fallback.py +++ b/tests/test_litellm/integrations/test_prometheus_remaining_tokens_router_fallback.py @@ -20,14 +20,11 @@ Tests cover: - llm_router unavailable / model_group missing / router raises → silent no-op. """ -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import pytest from prometheus_client import REGISTRY -sys.path.insert(0, os.path.abspath("../../..")) from litellm.integrations.prometheus import PrometheusLogger from litellm.types.integrations.prometheus import UserAPIKeyLabelValues diff --git a/tests/test_litellm/integrations/test_prometheus_services.py b/tests/test_litellm/integrations/test_prometheus_services.py index 2efd226dc9d..2303061ede8 100644 --- a/tests/test_litellm/integrations/test_prometheus_services.py +++ b/tests/test_litellm/integrations/test_prometheus_services.py @@ -1,6 +1,4 @@ import json -import os -import sys import time from unittest.mock import AsyncMock, patch @@ -13,9 +11,6 @@ from litellm.integrations.prometheus_services import ( ServiceTypes, ) -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path def test_is_metric_registered_does_not_use_registry_collect(): diff --git a/tests/test_litellm/integrations/websearch_interception/test_websearch_agentic_loop_cap.py b/tests/test_litellm/integrations/websearch_interception/test_websearch_agentic_loop_cap.py new file mode 100644 index 00000000000..40fd8c4e9e6 --- /dev/null +++ b/tests/test_litellm/integrations/websearch_interception/test_websearch_agentic_loop_cap.py @@ -0,0 +1,754 @@ +""" +Unit tests for what an intercepted request returns once a safety rail refuses +another agentic loop. + +The web search interception loop injects an internal tool (litellm_web_search) +that the client never declared. When the loop cap or the repeated-fingerprint +guard trips, the turn has to end with a terminal response: leaking that internal +tool_use block leaves the client holding a tool call it cannot answer. + +Also covers the max_agentic_loops knob on websearch_interception_params, from +config.yaml through to the settings the loop actually reads. +""" + +import json +from unittest.mock import MagicMock + +import pytest + +import litellm +from litellm.integrations.custom_logger import CustomLogger +from litellm.integrations.websearch_interception.handler import ( + WebSearchInterceptionLogger, +) +from litellm.llms.anthropic.experimental_pass_through.messages.fake_stream_iterator import ( + FakeAnthropicMessagesStreamIterator, +) +from litellm.litellm_core_utils.agentic_loop_settings import DEFAULT_MAX_AGENTIC_LOOPS +from litellm.llms.custom_httpx.llm_http_handler import BaseLLMHTTPHandler +from litellm.secret_managers.main import get_secret +from litellm.types.integrations.custom_logger import ( + AgenticLoopPlan, + AgenticLoopRequestPatch, + AgenticLoopSafetyError, +) + +INTERNAL_TOOL_NAME = "litellm_web_search" + + +@pytest.fixture(autouse=True) +def only_the_callbacks_these_tests_register(monkeypatch): + """ + These tests drive the hooks with a callback of their own on the logging + object, so a logger another test left on litellm.callbacks would join the + run and change what the hooks do. + """ + monkeypatch.setattr(litellm, "callbacks", []) + + +def _internal_tool_use_block(block_id: str = "toolu_internal_1") -> dict: + return { + "id": block_id, + "type": "tool_use", + "name": INTERNAL_TOOL_NAME, + "input": {"query": "who won the world cup"}, + } + + +def _native_search_blocks(index: int = 1) -> list[dict]: + return [ + { + "type": "server_tool_use", + "id": f"srvtoolu_{index}", + "name": "web_search", + "input": {"query": "who won the world cup"}, + }, + { + "type": "web_search_tool_result", + "tool_use_id": f"srvtoolu_{index}", + "content": [{"type": "web_search_result", "url": "https://example.com", "title": "Result"}], + }, + ] + + +def _response_asking_for_another_search(block_id: str = "toolu_internal_1") -> dict: + return { + "id": "msg_123", + "type": "message", + "role": "assistant", + "model": "claude-sonnet-4-5", + "content": [ + *_native_search_blocks(index=1), + {"type": "text", "text": "Let me check one more source."}, + _internal_tool_use_block(block_id), + ], + "stop_reason": "tool_use", + "usage": {"input_tokens": 10, "output_tokens": 5}, + } + + +def _block_types(response: dict) -> list[str]: + return [block["type"] for block in response["content"]] + + +def _tool_use_names(response: dict) -> list[str]: + return [block.get("name") for block in response["content"] if block.get("type") == "tool_use"] + + +class _InterceptingCallback(CustomLogger): + """ + Stands in for the websearch interceptor: asks for another loop whenever the + response carries an internal web search tool_use block, and injects the + native block pair on the way back out. + """ + + def __init__(self): + self.plan_calls = 0 + self.post_hook_calls = 0 + + async def async_should_run_agentic_loop( + self, response, model, messages, tools, stream, custom_llm_provider, kwargs + ): + if not isinstance(response, dict): + return True, {"tool_calls": [_internal_tool_use_block()]} + tool_calls = [ + block + for block in response.get("content", []) + if block.get("type") == "tool_use" and block.get("name") == INTERNAL_TOOL_NAME + ] + if not tool_calls: + return False, {} + return True, {"tool_calls": tool_calls, "tool_type": "websearch"} + + async def async_build_agentic_loop_plan( + self, + tools, + model, + messages, + response, + anthropic_messages_provider_config, + anthropic_messages_optional_request_params, + logging_obj, + stream, + kwargs, + ): + self.plan_calls += 1 + return AgenticLoopPlan( + run_agentic_loop=True, + request_patch=AgenticLoopRequestPatch( + messages=[{"role": "user", "content": "here are the search results"}], + max_tokens=1024, + ), + ) + + async def async_post_agentic_loop_response_hook(self, response, plan, kwargs): + self.post_hook_calls += 1 + if isinstance(response, dict): + response["content"] = [*_native_search_blocks(index=2), *response.get("content", [])] + return response + + +def _logging_obj(callback: CustomLogger, converted_stream: bool = False) -> MagicMock: + logging_obj = MagicMock() + logging_obj.model_call_details = {"websearch_interception_converted_stream": converted_stream} + logging_obj.dynamic_success_callbacks = [callback] + logging_obj.litellm_call_id = "call-abc" + return logging_obj + + +async def _run_hooks( + handler: BaseLLMHTTPHandler, + callback: CustomLogger, + kwargs: dict, + response: object = None, + stream: bool = False, + converted_stream: bool = False, + api_surface: str = "anthropic_messages", +): + return await handler._call_agentic_completion_hooks( + response=_response_asking_for_another_search() if response is None else response, + model="claude-sonnet-4-5", + messages=[{"role": "user", "content": "who won the world cup"}], + anthropic_messages_provider_config=MagicMock(), + anthropic_messages_optional_request_params={}, + logging_obj=_logging_obj(callback, converted_stream=converted_stream), + stream=stream, + custom_llm_provider="anthropic", + kwargs=kwargs, + api_surface=api_surface, + ) + + +class TestCappedLoopReturnsTerminalResponse: + def setup_method(self): + self.handler = BaseLLMHTTPHandler() + self.callback = _InterceptingCallback() + + @pytest.mark.asyncio + async def test_internal_tool_use_block_is_dropped(self): + result = await _run_hooks( + self.handler, + self.callback, + kwargs={"_agentic_loop_depth": 3, "max_agentic_loops": 3}, + ) + + assert isinstance(result, dict) + assert INTERNAL_TOOL_NAME not in _tool_use_names(result) + + @pytest.mark.asyncio + async def test_stop_reason_is_closed_out(self): + result = await _run_hooks( + self.handler, + self.callback, + kwargs={"_agentic_loop_depth": 3, "max_agentic_loops": 3}, + ) + + assert result["stop_reason"] == "end_turn" + + @pytest.mark.asyncio + async def test_native_blocks_and_text_survive(self): + result = await _run_hooks( + self.handler, + self.callback, + kwargs={"_agentic_loop_depth": 3, "max_agentic_loops": 3}, + ) + + assert _block_types(result) == ["server_tool_use", "web_search_tool_result", "text"] + + @pytest.mark.asyncio + async def test_turn_carrying_only_the_refused_call_still_ends_cleanly(self): + """ + The refused call can be every block the model produced, which leaves the + turn with no content once it is dropped. That still has to come back as a + finished turn rather than as the leaked call, so the client stops instead + of waiting on a tool it cannot run, and the rest of the message survives + so the request is still billed and traceable. + + An empty turn renders as nothing, which is the ceiling being set too low + for the question rather than a malformed response. + """ + nothing_but_the_refused_call = { + "id": "msg_123", + "type": "message", + "role": "assistant", + "model": "claude-sonnet-4-5", + "content": [_internal_tool_use_block()], + "stop_reason": "tool_use", + "usage": {"input_tokens": 10, "output_tokens": 5}, + } + + result = await _run_hooks( + self.handler, + self.callback, + kwargs={"_agentic_loop_depth": 3, "max_agentic_loops": 3}, + response=nothing_but_the_refused_call, + ) + + assert result["content"] == [] + assert result["stop_reason"] == "end_turn" + assert result["usage"] == {"input_tokens": 10, "output_tokens": 5} + assert result["id"] == "msg_123" + + @pytest.mark.asyncio + async def test_no_follow_up_model_call_is_planned(self): + """ + The rail has to end the turn without planning another model call, and it + has to end it by returning rather than by raising, which is the half that + the caller's response depends on. + """ + result = await _run_hooks( + self.handler, + self.callback, + kwargs={"_agentic_loop_depth": 3, "max_agentic_loops": 3}, + ) + + assert self.callback.plan_calls == 0 + assert result["stop_reason"] == "end_turn" + + @pytest.mark.asyncio + async def test_original_response_is_not_mutated(self): + response = _response_asking_for_another_search() + + await _run_hooks( + self.handler, + self.callback, + kwargs={"_agentic_loop_depth": 3, "max_agentic_loops": 3}, + response=response, + ) + + assert response["stop_reason"] == "tool_use" + assert INTERNAL_TOOL_NAME in _tool_use_names(response) + + @pytest.mark.asyncio + async def test_repeated_fingerprint_guard_is_terminal_too(self): + tool_calls = {"tool_calls": [_internal_tool_use_block()], "tool_type": "websearch"} + seen = json.dumps(tool_calls, sort_keys=True, default=str) + + result = await _run_hooks( + self.handler, + self.callback, + kwargs={"_agentic_loop_depth": 0, "max_agentic_loops": 3, "_agentic_loop_fingerprints": [seen]}, + ) + + assert self.callback.plan_calls == 0 + assert INTERNAL_TOOL_NAME not in _tool_use_names(result) + assert result["stop_reason"] == "end_turn" + + @pytest.mark.asyncio + async def test_client_declared_tool_use_is_left_alone(self): + response = _response_asking_for_another_search() + client_tool_use = {"id": "toolu_client_1", "type": "tool_use", "name": "get_weather", "input": {}} + response["content"].append(client_tool_use) + + result = await _run_hooks( + self.handler, + self.callback, + kwargs={"_agentic_loop_depth": 3, "max_agentic_loops": 3}, + response=response, + ) + + assert _tool_use_names(result) == ["get_weather"] + assert result["stop_reason"] == "tool_use" + + def test_only_the_refused_tool_calls_are_dropped(self): + """ + A block is matched on the id the rail refused, not on the tool name, so a + second block sharing that name survives when the rail never listed it. A + callback that picks its tool calls out by name hands both over and both + go, which is its own call to make; this is about not widening it here. + """ + response = _response_asking_for_another_search() + response["content"].append( + {"id": "toolu_client_1", "type": "tool_use", "name": INTERNAL_TOOL_NAME, "input": {}} + ) + + result = BaseLLMHTTPHandler._finalize_refused_agentic_response( + response=response, + tool_calls={"tool_calls": [_internal_tool_use_block()]}, + ) + + assert [block["id"] for block in result["content"] if block.get("type") == "tool_use"] == ["toolu_client_1"] + assert result["stop_reason"] == "tool_use" + + def test_tool_calls_without_ids_still_match_by_name(self): + """ + Not every callback shape carries ids on its tool calls, so the name is + still what decides when the rail refused a call that has no id. + """ + result = BaseLLMHTTPHandler._finalize_refused_agentic_response( + response=_response_asking_for_another_search(), + tool_calls={"tool_calls": [{"name": INTERNAL_TOOL_NAME, "input": {}}]}, + ) + + assert _tool_use_names(result) == [] + assert result["stop_reason"] == "end_turn" + + @pytest.mark.asyncio + async def test_streaming_caller_is_left_to_its_existing_behavior(self): + """ + A streaming caller has already sent the original message to the client, so + a finalized turn would land as a second message rather than replace the + first. The rail keeps raising there and the caller handles it as before. + """ + with pytest.raises(AgenticLoopSafetyError): + await _run_hooks( + self.handler, + self.callback, + kwargs={"_agentic_loop_depth": 3, "max_agentic_loops": 3}, + stream=True, + ) + + assert self.callback.plan_calls == 0 + + @pytest.mark.asyncio + async def test_responses_surface_is_left_to_its_existing_behavior(self): + """ + The responses surface carries a pydantic model rather than the anthropic + dict this finalizer rewrites, so it keeps raising instead of being handed + a response that was never actually finalized. + """ + with pytest.raises(AgenticLoopSafetyError): + await _run_hooks( + self.handler, + self.callback, + kwargs={"_agentic_loop_depth": 3, "max_agentic_loops": 3}, + api_surface="responses", + ) + + @pytest.mark.asyncio + async def test_non_dict_response_is_returned_untouched(self): + response = MagicMock() + + result = await _run_hooks( + self.handler, + self.callback, + kwargs={"_agentic_loop_depth": 3, "max_agentic_loops": 3}, + response=response, + ) + + assert result is response + + @pytest.mark.asyncio + async def test_converted_stream_gets_a_terminal_fake_stream(self): + """ + A converted stream is wrapped back into an Anthropic SSE stream here, the + same as every other return in this function, so a streaming client gets a + terminal stream rather than a bare dict. The interceptor turns the client's + stream into a non-streaming upstream call, so stream is False on this path + and the converted flag on the logging object is what marks it. + """ + result = await _run_hooks( + self.handler, + self.callback, + kwargs={"_agentic_loop_depth": 3, "max_agentic_loops": 3}, + converted_stream=True, + ) + + assert isinstance(result, FakeAnthropicMessagesStreamIterator) + assert result.response["stop_reason"] == "end_turn" + assert INTERNAL_TOOL_NAME not in _tool_use_names(result.response) + + def test_rails_cannot_trip_in_the_outermost_frame(self): + """ + Backs the invariant the test above relies on: at depth 0 the fingerprint set + is empty and the ceiling is at least 1, so neither rail can refuse. + """ + depth, max_loops, fingerprints = BaseLLMHTTPHandler._get_agentic_loop_settings(kwargs={}) + + assert depth == 0 + assert fingerprints == [] + assert max_loops >= 1 + + depth, max_loops, fingerprints = BaseLLMHTTPHandler._get_agentic_loop_settings( + kwargs={"max_agentic_loops": 1} + ) + + assert max_loops == 1 + assert BaseLLMHTTPHandler._check_agentic_loop_safety( + tool_calls={"tool_calls": [_internal_tool_use_block()]}, + fingerprints=fingerprints, + depth=depth, + max_loops=max_loops, + model="claude-sonnet-4-5", + ) + + def test_safety_error_is_still_a_value_error(self): + assert issubclass(AgenticLoopSafetyError, ValueError) + + def test_safety_error_type_names_the_rail(self): + with pytest.raises(AgenticLoopSafetyError, match="max_agentic_loops"): + BaseLLMHTTPHandler._check_agentic_loop_safety( + tool_calls={"tool_calls": [_internal_tool_use_block()]}, + fingerprints=[], + depth=3, + max_loops=3, + model="claude-sonnet-4-5", + ) + + +class TestOuterFramePostHookStillRuns: + """ + The cap used to raise through the parent frame's await, which skipped the + parent's post-loop hook. The parent now gets its terminal response back and + finishes normally, so the blocks it was going to inject still land. + """ + + @pytest.mark.asyncio + async def test_parent_frame_injects_its_blocks_after_the_cap_trips(self, monkeypatch): + handler = BaseLLMHTTPHandler() + callback = _InterceptingCallback() + + async def fake_acreate(**call_kwargs): + return await handler._call_agentic_completion_hooks( + response=_response_asking_for_another_search(block_id="toolu_internal_2"), + model=call_kwargs["model"], + messages=call_kwargs["messages"], + anthropic_messages_provider_config=MagicMock(), + anthropic_messages_optional_request_params={}, + logging_obj=_logging_obj(callback), + stream=False, + custom_llm_provider="anthropic", + kwargs={ + key: call_kwargs[key] + for key in ("_agentic_loop_depth", "max_agentic_loops", "_agentic_loop_fingerprints") + if key in call_kwargs + }, + ) + + monkeypatch.setattr("litellm.anthropic_interface.messages.acreate", fake_acreate) + + result = await _run_hooks( + handler, + callback, + kwargs={"_agentic_loop_depth": 0, "max_agentic_loops": 1}, + ) + + assert callback.plan_calls == 1 + assert callback.post_hook_calls == 1 + assert _block_types(result)[:2] == ["server_tool_use", "web_search_tool_result"] + assert INTERNAL_TOOL_NAME not in _tool_use_names(result) + assert result["stop_reason"] == "end_turn" + + +class TestMaxAgenticLoopsConfigKnob: + def test_from_config_yaml_reads_the_knob(self): + logger = WebSearchInterceptionLogger.from_config_yaml( + {"enabled_providers": ["bedrock"], "max_agentic_loops": 7} + ) + + assert logger.max_agentic_loops == 7 + + def test_from_config_yaml_leaves_it_unset_by_default(self): + logger = WebSearchInterceptionLogger.from_config_yaml({"enabled_providers": ["bedrock"]}) + + assert logger.max_agentic_loops is None + + @pytest.mark.parametrize("bad_value", [0, -1]) + def test_out_of_range_ceilings_are_rejected_at_config_load(self, bad_value): + with pytest.raises(ValueError, match="max_agentic_loops"): + WebSearchInterceptionLogger.from_config_yaml( + {"enabled_providers": ["bedrock"], "max_agentic_loops": bad_value} + ) + + @pytest.mark.parametrize("bad_value", ["three", True, 2.5]) + def test_non_integer_ceilings_are_rejected_at_config_load(self, bad_value): + with pytest.raises(TypeError, match="max_agentic_loops"): + WebSearchInterceptionLogger.from_config_yaml( + {"enabled_providers": ["bedrock"], "max_agentic_loops": bad_value} + ) + + def test_a_ceiling_spelled_as_a_string_is_read_at_config_load(self): + """ + `max_agentic_loops: os.environ/MAX_AGENTIC_LOOPS` resolves to a string + before it reaches the knob, so refusing "5" would break a config that + works today. + """ + logger = WebSearchInterceptionLogger.from_config_yaml( + {"enabled_providers": ["bedrock"], "max_agentic_loops": "5"} + ) + + assert logger.max_agentic_loops == 5 + + @pytest.mark.asyncio + async def test_knob_reaches_the_loop_settings(self): + logger = WebSearchInterceptionLogger.from_config_yaml( + {"enabled_providers": ["bedrock"], "max_agentic_loops": 7} + ) + kwargs = { + "tools": [{"type": "web_search_20250305", "name": "web_search", "max_uses": 5}], + "litellm_params": {"custom_llm_provider": "bedrock"}, + } + + updated = await logger.async_pre_request_hook(model="claude-sonnet-4-5", messages=[], kwargs=kwargs) + + _, max_loops, _ = BaseLLMHTTPHandler._get_agentic_loop_settings(kwargs=updated) + assert max_loops == 7 + + @pytest.mark.asyncio + async def test_deployment_setting_wins_over_the_feature_setting(self): + logger = WebSearchInterceptionLogger.from_config_yaml( + {"enabled_providers": ["bedrock"], "max_agentic_loops": 7} + ) + kwargs = { + "tools": [{"type": "web_search_20250305", "name": "web_search", "max_uses": 5}], + "litellm_params": {"custom_llm_provider": "bedrock"}, + "max_agentic_loops": 2, + } + + updated = await logger.async_pre_request_hook(model="claude-sonnet-4-5", messages=[], kwargs=kwargs) + + _, max_loops, _ = BaseLLMHTTPHandler._get_agentic_loop_settings(kwargs=updated) + assert max_loops == 2 + + @pytest.mark.asyncio + async def test_default_ceiling_applies_when_the_knob_is_unset(self): + logger = WebSearchInterceptionLogger.from_config_yaml({"enabled_providers": ["bedrock"]}) + kwargs = { + "tools": [{"type": "web_search_20250305", "name": "web_search", "max_uses": 5}], + "litellm_params": {"custom_llm_provider": "bedrock"}, + } + + updated = await logger.async_pre_request_hook(model="claude-sonnet-4-5", messages=[], kwargs=kwargs) + + assert "max_agentic_loops" not in updated + _, max_loops, _ = BaseLLMHTTPHandler._get_agentic_loop_settings(kwargs=updated) + assert max_loops == 3 + + +def _stream_events(response: dict) -> list[dict]: + events: list[dict] = [] + for chunk in FakeAnthropicMessagesStreamIterator(response=response): + for line in chunk.decode().splitlines(): + if line.startswith("data: "): + events.append(json.loads(line[len("data: ") :])) + return events + + +class TestBothCeilingKnobsAreValidated: + """ + ``max_agentic_loops`` is settable per deployment and feature-wide, and the + per-deployment one wins. Only the feature-wide one used to be checked, so a + per-deployment ``0`` was swallowed by an ``or 3`` and read as the default 3, + handing the loosest ceiling to whoever asked for the tightest. + """ + + def test_a_per_deployment_zero_is_rejected_not_read_as_the_default(self): + with pytest.raises(ValueError, match="must be at least 1, got 0"): + BaseLLMHTTPHandler._get_agentic_loop_settings(kwargs={"max_agentic_loops": 0}) + + def test_a_per_deployment_non_integer_names_the_field_it_came_from(self): + with pytest.raises(TypeError, match=r"litellm_params\.max_agentic_loops must be an integer"): + BaseLLMHTTPHandler._get_agentic_loop_settings(kwargs={"max_agentic_loops": "three"}) + + def test_a_per_deployment_true_is_not_read_as_a_ceiling_of_one(self): + with pytest.raises(TypeError, match="must be an integer"): + BaseLLMHTTPHandler._get_agentic_loop_settings(kwargs={"max_agentic_loops": True}) + + def test_an_absent_ceiling_falls_back_to_the_shared_default(self): + _, max_loops, _ = BaseLLMHTTPHandler._get_agentic_loop_settings(kwargs={}) + + assert max_loops == DEFAULT_MAX_AGENTIC_LOOPS + + def test_an_explicit_none_falls_back_to_the_shared_default(self): + _, max_loops, _ = BaseLLMHTTPHandler._get_agentic_loop_settings(kwargs={"max_agentic_loops": None}) + + assert max_loops == DEFAULT_MAX_AGENTIC_LOOPS + + def test_a_valid_per_deployment_ceiling_is_passed_through(self): + _, max_loops, _ = BaseLLMHTTPHandler._get_agentic_loop_settings(kwargs={"max_agentic_loops": 6}) + + assert max_loops == 6 + + @pytest.mark.parametrize("rejected", [0, -1, "three", True]) + def test_the_two_knobs_reject_the_same_values(self, rejected): + with pytest.raises((TypeError, ValueError)): + WebSearchInterceptionLogger(max_agentic_loops=rejected) + with pytest.raises((TypeError, ValueError)): + BaseLLMHTTPHandler._get_agentic_loop_settings(kwargs={"max_agentic_loops": rejected}) + + def test_each_knob_names_its_own_config_field(self): + with pytest.raises(ValueError, match=r"websearch_interception_params\.max_agentic_loops"): + WebSearchInterceptionLogger(max_agentic_loops=0) + with pytest.raises(ValueError, match=r"litellm_params\.max_agentic_loops"): + BaseLLMHTTPHandler._get_agentic_loop_settings(kwargs={"max_agentic_loops": 0}) + + +class TestACeilingThatSpellsAWholeNumberStillWorks: + """ + The ceiling used to go through ``int(... or 3)``, which accepted anything + ``int()`` accepted. A ceiling is routinely parameterized as + ``max_agentic_loops: os.environ/MAX_AGENTIC_LOOPS``, and ``get_secret`` + hands that back as the string ``"5"``, so tightening the check to + ``isinstance(int)`` would stop such a proxy from booting on upgrade. + """ + + @pytest.mark.parametrize("spelled", ["5", " 5 ", 5.0]) + def test_a_ceiling_that_spells_five_is_accepted_by_both_knobs(self, spelled): + _, max_loops, _ = BaseLLMHTTPHandler._get_agentic_loop_settings(kwargs={"max_agentic_loops": spelled}) + + assert max_loops == 5 + assert WebSearchInterceptionLogger(max_agentic_loops=spelled).max_agentic_loops == 5 + + def test_an_env_var_sourced_ceiling_survives_secret_resolution(self, monkeypatch): + monkeypatch.setenv("MAX_AGENTIC_LOOPS_UNDER_TEST", "7") + resolved = get_secret("os.environ/MAX_AGENTIC_LOOPS_UNDER_TEST") + + assert isinstance(resolved, str) + _, max_loops, _ = BaseLLMHTTPHandler._get_agentic_loop_settings(kwargs={"max_agentic_loops": resolved}) + assert max_loops == 7 + + def test_a_spelled_zero_is_still_refused_and_reports_the_number(self): + with pytest.raises(ValueError, match="must be at least 1, got 0"): + BaseLLMHTTPHandler._get_agentic_loop_settings(kwargs={"max_agentic_loops": "0"}) + + def test_a_word_is_still_refused(self): + with pytest.raises(TypeError, match=r"litellm_params\.max_agentic_loops must be an integer"): + BaseLLMHTTPHandler._get_agentic_loop_settings(kwargs={"max_agentic_loops": "three"}) + + def test_a_fractional_ceiling_is_refused_rather_than_truncated(self): + with pytest.raises(TypeError, match="must be an integer"): + BaseLLMHTTPHandler._get_agentic_loop_settings(kwargs={"max_agentic_loops": 5.5}) + + +class TestRebuiltStreamIsWellFormed: + """ + A capped turn is rebuilt into SSE by FakeAnthropicMessagesStreamIterator. + + Anthropic's SDK accumulator appends on content_block_start and then indexes + content[event.index] on content_block_delta, so a block that stops without + ever starting shifts every later index and the accumulator raises + IndexError. A web search turn carries server_tool_use and + web_search_tool_result blocks, which is exactly where that used to happen. + """ + + @staticmethod + def _capped_search_turn() -> dict: + return { + "id": "msg_01", + "type": "message", + "role": "assistant", + "model": "claude-sonnet-4-5", + "stop_reason": "end_turn", + "content": [ + { + "type": "server_tool_use", + "id": "srvtoolu_01", + "name": "web_search", + "input": {"query": "on-demand H100 hourly price"}, + }, + { + "type": "web_search_tool_result", + "tool_use_id": "srvtoolu_01", + "content": [ + { + "type": "web_search_result", + "url": "https://example.com/h100", + "title": "H100 pricing", + } + ], + }, + {"type": "text", "text": "AWS lists the H100 at $12.29 an hour."}, + ], + "usage": {"input_tokens": 100, "output_tokens": 20}, + } + + def test_every_content_block_stop_has_a_matching_start(self): + events = _stream_events(self._capped_search_turn()) + + started = [event["index"] for event in events if event["type"] == "content_block_start"] + stopped = [event["index"] for event in events if event["type"] == "content_block_stop"] + + assert started == [0, 1, 2] + assert stopped == [0, 1, 2] + + def test_no_delta_indexes_past_the_blocks_started_before_it(self): + events = _stream_events(self._capped_search_turn()) + + blocks_started = 0 + for event in events: + if event["type"] == "content_block_start": + blocks_started += 1 + elif event["type"] == "content_block_delta": + assert event["index"] < blocks_started + + def test_search_blocks_reach_the_client(self): + events = _stream_events(self._capped_search_turn()) + + started_types = [ + event["content_block"]["type"] for event in events if event["type"] == "content_block_start" + ] + + assert started_types == ["server_tool_use", "web_search_tool_result", "text"] + + def test_the_search_result_survives_the_rebuild_intact(self): + events = _stream_events(self._capped_search_turn()) + + result_block = next( + event["content_block"] + for event in events + if event["type"] == "content_block_start" + and event["content_block"]["type"] == "web_search_tool_result" + ) + + assert result_block["tool_use_id"] == "srvtoolu_01" + assert result_block["content"][0]["url"] == "https://example.com/h100" diff --git a/tests/test_litellm/interactions/test_agents_http_handler.py b/tests/test_litellm/interactions/test_agents_http_handler.py index 6947503e0bb..31b78d7a360 100644 --- a/tests/test_litellm/interactions/test_agents_http_handler.py +++ b/tests/test_litellm/interactions/test_agents_http_handler.py @@ -8,14 +8,11 @@ branches, error mapping, and pre/post logging hooks. No real HTTP traffic is made. """ -import os -import sys from unittest.mock import AsyncMock, MagicMock import httpx import pytest -sys.path.insert(0, os.path.abspath("../../..")) from litellm.interactions.agents.http_handler import ( AgentsHTTPHandler, diff --git a/tests/test_litellm/interactions/test_agents_main_and_utils.py b/tests/test_litellm/interactions/test_agents_main_and_utils.py index f5523cf1cf8..395801ff059 100644 --- a/tests/test_litellm/interactions/test_agents_main_and_utils.py +++ b/tests/test_litellm/interactions/test_agents_main_and_utils.py @@ -9,13 +9,10 @@ small helper utilities without touching the network. """ import asyncio -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import pytest -sys.path.insert(0, os.path.abspath("../../..")) import litellm from litellm.interactions.agents import ( diff --git a/tests/test_litellm/interactions/test_gemini_interactions_transformation.py b/tests/test_litellm/interactions/test_gemini_interactions_transformation.py index 05b0bde16bb..d9b7cc790e6 100644 --- a/tests/test_litellm/interactions/test_gemini_interactions_transformation.py +++ b/tests/test_litellm/interactions/test_gemini_interactions_transformation.py @@ -8,13 +8,10 @@ Covers: - transform_request: response_mime_type coalescing, image_config migration """ -import os -import sys from unittest.mock import MagicMock, patch import pytest -sys.path.insert(0, os.path.abspath("../../..")) import litellm from litellm.interactions.litellm_responses_transformation.streaming_iterator import ( diff --git a/tests/test_litellm/interactions/test_google_interactions_integration.py b/tests/test_litellm/interactions/test_google_interactions_integration.py index 49cd978c683..93429d64789 100644 --- a/tests/test_litellm/interactions/test_google_interactions_integration.py +++ b/tests/test_litellm/interactions/test_google_interactions_integration.py @@ -10,11 +10,9 @@ Run with: pytest tests/test_litellm/interactions/test_google_interactions_integr import asyncio import os -import sys import pytest -sys.path.insert(0, os.path.abspath("../../..")) import litellm import litellm.interactions as interactions diff --git a/tests/test_litellm/litellm_core_utils/llm_cost_calc/test_tool_call_cost_tracking.py b/tests/test_litellm/litellm_core_utils/llm_cost_calc/test_tool_call_cost_tracking.py index a5128228742..9bdded94513 100644 --- a/tests/test_litellm/litellm_core_utils/llm_cost_calc/test_tool_call_cost_tracking.py +++ b/tests/test_litellm/litellm_core_utils/llm_cost_calc/test_tool_call_cost_tracking.py @@ -1,5 +1,4 @@ import os -import sys import pytest @@ -10,9 +9,6 @@ from litellm.litellm_core_utils.llm_cost_calc.tool_call_cost_tracking import ( from litellm.types.llms.openai import FileSearchTool, WebSearchOptions from litellm.types.utils import ModelResponse, StandardBuiltInToolsParams -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path diff --git a/tests/test_litellm/litellm_core_utils/llm_cost_calc/test_tool_call_cost_tracking_dict_safety.py b/tests/test_litellm/litellm_core_utils/llm_cost_calc/test_tool_call_cost_tracking_dict_safety.py index 4eee6b59d34..61b94139bb8 100644 --- a/tests/test_litellm/litellm_core_utils/llm_cost_calc/test_tool_call_cost_tracking_dict_safety.py +++ b/tests/test_litellm/litellm_core_utils/llm_cost_calc/test_tool_call_cost_tracking_dict_safety.py @@ -5,12 +5,9 @@ either a ``dict`` or a ``ServerToolUse`` pydantic instance. See https://github.com/BerriAI/litellm/issues/26153. """ -import os -import sys import pytest -sys.path.insert(0, os.path.abspath("../../../..")) from litellm.litellm_core_utils.llm_cost_calc.tool_call_cost_tracking import ( StandardBuiltInToolCostTracking, diff --git a/tests/test_litellm/litellm_core_utils/llm_response_utils/test_convert_dict_to_response.py b/tests/test_litellm/litellm_core_utils/llm_response_utils/test_convert_dict_to_response.py index 293e5de304f..304d732c518 100644 --- a/tests/test_litellm/litellm_core_utils/llm_response_utils/test_convert_dict_to_response.py +++ b/tests/test_litellm/litellm_core_utils/llm_response_utils/test_convert_dict_to_response.py @@ -1,7 +1,4 @@ -import os -import sys -sys.path.insert(0, os.path.abspath("../../../..")) from litellm.constants import RESPONSE_FORMAT_TOOL_NAME from litellm.litellm_core_utils.llm_response_utils.convert_dict_to_response import ( diff --git a/tests/test_litellm/litellm_core_utils/prompt_templates/test_litellm_core_utils_prompt_templates_common_utils.py b/tests/test_litellm/litellm_core_utils/prompt_templates/test_litellm_core_utils_prompt_templates_common_utils.py index f9311497729..44fa8fc8ae0 100644 --- a/tests/test_litellm/litellm_core_utils/prompt_templates/test_litellm_core_utils_prompt_templates_common_utils.py +++ b/tests/test_litellm/litellm_core_utils/prompt_templates/test_litellm_core_utils_prompt_templates_common_utils.py @@ -1,13 +1,9 @@ import json import os -import sys from unittest.mock import MagicMock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from litellm.litellm_core_utils.prompt_templates.common_utils import ( TOOL_RESULT_IMAGE_BOUNDARY, diff --git a/tests/test_litellm/litellm_core_utils/specialty_caches/test_dynamic_logging_cache.py b/tests/test_litellm/litellm_core_utils/specialty_caches/test_dynamic_logging_cache.py index f21cd56750b..5ed9dca68fd 100644 --- a/tests/test_litellm/litellm_core_utils/specialty_caches/test_dynamic_logging_cache.py +++ b/tests/test_litellm/litellm_core_utils/specialty_caches/test_dynamic_logging_cache.py @@ -1,14 +1,9 @@ import json -import os -import sys import time from unittest.mock import MagicMock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path import litellm from litellm.litellm_core_utils.specialty_caches.dynamic_logging_cache import ( diff --git a/tests/test_litellm/litellm_core_utils/test_anthropic_dedup_factory.py b/tests/test_litellm/litellm_core_utils/test_anthropic_dedup_factory.py index df1458b0f95..bafca04ad38 100644 --- a/tests/test_litellm/litellm_core_utils/test_anthropic_dedup_factory.py +++ b/tests/test_litellm/litellm_core_utils/test_anthropic_dedup_factory.py @@ -1,8 +1,5 @@ -import sys -import os import pytest -sys.path.insert(0, os.path.abspath(".")) from litellm.litellm_core_utils.prompt_templates.factory import anthropic_messages_pt diff --git a/tests/test_litellm/litellm_core_utils/test_bedrock_converse_dedup_factory.py b/tests/test_litellm/litellm_core_utils/test_bedrock_converse_dedup_factory.py index c32917efe87..73fa1a07d63 100644 --- a/tests/test_litellm/litellm_core_utils/test_bedrock_converse_dedup_factory.py +++ b/tests/test_litellm/litellm_core_utils/test_bedrock_converse_dedup_factory.py @@ -1,8 +1,5 @@ -import sys -import os import pytest -sys.path.insert(0, os.path.abspath(".")) from litellm.litellm_core_utils.prompt_templates.factory import ( _bedrock_converse_messages_pt, diff --git a/tests/test_litellm/litellm_core_utils/test_chat_completion_agentic_loop.py b/tests/test_litellm/litellm_core_utils/test_chat_completion_agentic_loop.py index cc16ad558e4..434daab6ab5 100644 --- a/tests/test_litellm/litellm_core_utils/test_chat_completion_agentic_loop.py +++ b/tests/test_litellm/litellm_core_utils/test_chat_completion_agentic_loop.py @@ -20,14 +20,11 @@ removed, so `test_internal_control_fields_never_leak_into_provider_body` proves they stay out of the body even without it. """ -import os -import sys from typing import Any, Dict, List, Optional, Tuple from unittest.mock import AsyncMock, MagicMock, patch import pytest -sys.path.insert(0, os.path.abspath("../../../..")) import litellm from litellm.integrations.custom_logger import CustomLogger diff --git a/tests/test_litellm/litellm_core_utils/test_dd_tracing.py b/tests/test_litellm/litellm_core_utils/test_dd_tracing.py index 455ad033afd..b55ade5225d 100644 --- a/tests/test_litellm/litellm_core_utils/test_dd_tracing.py +++ b/tests/test_litellm/litellm_core_utils/test_dd_tracing.py @@ -1,13 +1,8 @@ import json -import os -import sys from unittest.mock import MagicMock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from litellm.litellm_core_utils.dd_tracing import ( _should_use_dd_profiler, diff --git a/tests/test_litellm/litellm_core_utils/test_exception_mapping_utils.py b/tests/test_litellm/litellm_core_utils/test_exception_mapping_utils.py index 38f46b26eea..cc0a52247a4 100644 --- a/tests/test_litellm/litellm_core_utils/test_exception_mapping_utils.py +++ b/tests/test_litellm/litellm_core_utils/test_exception_mapping_utils.py @@ -1,14 +1,9 @@ -import os -import sys import httpx import pytest import litellm -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from litellm.litellm_core_utils.exception_mapping_utils import ( ExceptionCheckers, diff --git a/tests/test_litellm/litellm_core_utils/test_fallback_generalizations.py b/tests/test_litellm/litellm_core_utils/test_fallback_generalizations.py index e97e977c88f..101cfc1d511 100644 --- a/tests/test_litellm/litellm_core_utils/test_fallback_generalizations.py +++ b/tests/test_litellm/litellm_core_utils/test_fallback_generalizations.py @@ -8,12 +8,9 @@ resolution (get_model_info) including the shipped rules in the bundled cost map. """ import logging -import os -import sys import pytest -sys.path.insert(0, os.path.abspath("../../..")) import litellm from litellm._logging import verbose_logger diff --git a/tests/test_litellm/litellm_core_utils/test_get_llm_provider_endpoint_match.py b/tests/test_litellm/litellm_core_utils/test_get_llm_provider_endpoint_match.py index fc5b39a2fd7..bda7ab4afc6 100644 --- a/tests/test_litellm/litellm_core_utils/test_get_llm_provider_endpoint_match.py +++ b/tests/test_litellm/litellm_core_utils/test_get_llm_provider_endpoint_match.py @@ -10,13 +10,10 @@ server's real provider key to an attacker-controlled host on the outbound request. """ -import os -import sys from unittest.mock import patch import pytest -sys.path.insert(0, os.path.abspath("../../..")) from litellm.litellm_core_utils.get_llm_provider_logic import ( _endpoint_matches_api_base, diff --git a/tests/test_litellm/litellm_core_utils/test_get_model_cost_map.py b/tests/test_litellm/litellm_core_utils/test_get_model_cost_map.py index 94798d77348..8c0e8ee5d02 100644 --- a/tests/test_litellm/litellm_core_utils/test_get_model_cost_map.py +++ b/tests/test_litellm/litellm_core_utils/test_get_model_cost_map.py @@ -6,11 +6,9 @@ count actual model entries, not reserved meta keys) and the extraction of the import json import os -import sys import pytest -sys.path.insert(0, os.path.abspath("../../..")) from litellm.litellm_core_utils.fallback_generalizations import ( get_fallback_generalization_rules, diff --git a/tests/test_litellm/litellm_core_utils/test_get_supported_openai_params.py b/tests/test_litellm/litellm_core_utils/test_get_supported_openai_params.py index 8587ad1ab01..2285cc83cad 100644 --- a/tests/test_litellm/litellm_core_utils/test_get_supported_openai_params.py +++ b/tests/test_litellm/litellm_core_utils/test_get_supported_openai_params.py @@ -1,9 +1,6 @@ -import os -import sys import pytest -sys.path.insert(0, os.path.abspath("../../..")) from litellm.litellm_core_utils.get_supported_openai_params import ( get_supported_openai_params, diff --git a/tests/test_litellm/litellm_core_utils/test_health_check_helpers.py b/tests/test_litellm/litellm_core_utils/test_health_check_helpers.py index f0d91224614..8f4799e3e7d 100644 --- a/tests/test_litellm/litellm_core_utils/test_health_check_helpers.py +++ b/tests/test_litellm/litellm_core_utils/test_health_check_helpers.py @@ -1,14 +1,9 @@ """Test health check helper functions""" -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from litellm.constants import LITTELM_INTERNAL_HEALTH_SERVICE_ACCOUNT_NAME from litellm.litellm_core_utils.health_check_helpers import HealthCheckHelpers diff --git a/tests/test_litellm/litellm_core_utils/test_initialize_dynamic_callback_params.py b/tests/test_litellm/litellm_core_utils/test_initialize_dynamic_callback_params.py index 956f86a9292..f9ddc47cc7c 100644 --- a/tests/test_litellm/litellm_core_utils/test_initialize_dynamic_callback_params.py +++ b/tests/test_litellm/litellm_core_utils/test_initialize_dynamic_callback_params.py @@ -1,9 +1,6 @@ -import os -import sys import pytest -sys.path.insert(0, os.path.abspath("../../..")) from litellm.litellm_core_utils.initialize_dynamic_callback_params import ( initialize_standard_callback_dynamic_params, diff --git a/tests/test_litellm/litellm_core_utils/test_litellm_logging.py b/tests/test_litellm/litellm_core_utils/test_litellm_logging.py index a3dcdaf1737..873da28fc34 100644 --- a/tests/test_litellm/litellm_core_utils/test_litellm_logging.py +++ b/tests/test_litellm/litellm_core_utils/test_litellm_logging.py @@ -6,9 +6,6 @@ from unittest.mock import AsyncMock, MagicMock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path import time diff --git a/tests/test_litellm/litellm_core_utils/test_max_streaming_duration.py b/tests/test_litellm/litellm_core_utils/test_max_streaming_duration.py index 1eb49f4859f..c768be22a9e 100644 --- a/tests/test_litellm/litellm_core_utils/test_max_streaming_duration.py +++ b/tests/test_litellm/litellm_core_utils/test_max_streaming_duration.py @@ -6,14 +6,11 @@ Covers: - BaseResponsesAPIStreamingIterator (responses) sync + async """ -import os -import sys import time from unittest.mock import AsyncMock, MagicMock, patch import pytest -sys.path.insert(0, os.path.abspath("../../..")) import litellm from litellm.litellm_core_utils.streaming_handler import CustomStreamWrapper diff --git a/tests/test_litellm/litellm_core_utils/test_model_param_helper.py b/tests/test_litellm/litellm_core_utils/test_model_param_helper.py index df01bd636b8..2c45b333817 100644 --- a/tests/test_litellm/litellm_core_utils/test_model_param_helper.py +++ b/tests/test_litellm/litellm_core_utils/test_model_param_helper.py @@ -1,9 +1,4 @@ -import os -import sys -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from litellm.litellm_core_utils.model_param_helper import ModelParamHelper diff --git a/tests/test_litellm/litellm_core_utils/test_provider_specific_headers.py b/tests/test_litellm/litellm_core_utils/test_provider_specific_headers.py index 293d6268eba..be7aadd4cfa 100644 --- a/tests/test_litellm/litellm_core_utils/test_provider_specific_headers.py +++ b/tests/test_litellm/litellm_core_utils/test_provider_specific_headers.py @@ -112,3 +112,37 @@ class TestProviderSpecificHeaderUtils: provider_specific_header, None ) assert result == {} + + def test_get_provider_specific_headers_scopes_each_entry_independently(self): + """Entries in a list each carry their own provider scope.""" + scoped_headers: list[ProviderSpecificHeader] = [ + { + "custom_llm_provider": "anthropic,bedrock,vertex_ai", + "extra_headers": {"anthropic-beta": "context-1m-2025-08-07"}, + }, + { + "custom_llm_provider": "anthropic", + "extra_headers": {"authorization": "Bearer sk-ant-oat01-fake-token"}, + }, + ] + + assert ProviderSpecificHeaderUtils.get_provider_specific_headers( + scoped_headers, "anthropic" + ) == { + "anthropic-beta": "context-1m-2025-08-07", + "authorization": "Bearer sk-ant-oat01-fake-token", + } + assert ProviderSpecificHeaderUtils.get_provider_specific_headers( + scoped_headers, "bedrock" + ) == {"anthropic-beta": "context-1m-2025-08-07"} + assert ( + ProviderSpecificHeaderUtils.get_provider_specific_headers( + scoped_headers, "openai" + ) + == {} + ) + + def test_get_provider_specific_headers_empty_list(self): + """An empty list of scoped entries contributes nothing.""" + result = ProviderSpecificHeaderUtils.get_provider_specific_headers([], "anthropic") + assert result == {} diff --git a/tests/test_litellm/litellm_core_utils/test_realtime_errors.py b/tests/test_litellm/litellm_core_utils/test_realtime_errors.py index 263d1654f65..494d16b0b9b 100644 --- a/tests/test_litellm/litellm_core_utils/test_realtime_errors.py +++ b/tests/test_litellm/litellm_core_utils/test_realtime_errors.py @@ -1,8 +1,5 @@ import json -import os -import sys -sys.path.insert(0, os.path.abspath("../../..")) from litellm.litellm_core_utils.realtime_errors import ( WEBSOCKET_CLOSE_REASON_MAX_BYTES, diff --git a/tests/test_litellm/litellm_core_utils/test_safe_json_dumps.py b/tests/test_litellm/litellm_core_utils/test_safe_json_dumps.py index ad24105588d..30385ba758d 100644 --- a/tests/test_litellm/litellm_core_utils/test_safe_json_dumps.py +++ b/tests/test_litellm/litellm_core_utils/test_safe_json_dumps.py @@ -1,12 +1,7 @@ import json -import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from litellm.litellm_core_utils.safe_json_dumps import safe_dumps, strip_null_bytes diff --git a/tests/test_litellm/litellm_core_utils/test_sensitive_data_masker.py b/tests/test_litellm/litellm_core_utils/test_sensitive_data_masker.py index ba8540f81e3..f6b8a93c472 100644 --- a/tests/test_litellm/litellm_core_utils/test_sensitive_data_masker.py +++ b/tests/test_litellm/litellm_core_utils/test_sensitive_data_masker.py @@ -2,13 +2,10 @@ Unit tests for SensitiveDataMasker - List Preservation """ -import os -import sys import pytest # Add the parent directory to the system path -sys.path.insert(0, os.path.abspath("../../..")) from litellm.litellm_core_utils.sensitive_data_masker import SensitiveDataMasker diff --git a/tests/test_litellm/litellm_core_utils/test_streaming_chunk_builder_cursor.py b/tests/test_litellm/litellm_core_utils/test_streaming_chunk_builder_cursor.py index 453c7490d98..3d9971034ae 100644 --- a/tests/test_litellm/litellm_core_utils/test_streaming_chunk_builder_cursor.py +++ b/tests/test_litellm/litellm_core_utils/test_streaming_chunk_builder_cursor.py @@ -19,12 +19,9 @@ to 0 when the only update we saw was the cursor, allowing the text-based fallback to estimate from the real completion text. """ -import os -import sys import pytest -sys.path.insert(0, os.path.abspath("../../..")) from litellm.litellm_core_utils.streaming_chunk_builder_utils import ChunkProcessor from litellm.types.utils import ( diff --git a/tests/test_litellm/litellm_core_utils/test_streaming_chunk_builder_server_tool_use.py b/tests/test_litellm/litellm_core_utils/test_streaming_chunk_builder_server_tool_use.py index 4e28d5ba7d2..75508917a1e 100644 --- a/tests/test_litellm/litellm_core_utils/test_streaming_chunk_builder_server_tool_use.py +++ b/tests/test_litellm/litellm_core_utils/test_streaming_chunk_builder_server_tool_use.py @@ -17,12 +17,9 @@ response and assert: raising ``AttributeError``. """ -import os -import sys import pytest -sys.path.insert(0, os.path.abspath("../../..")) from litellm import completion_cost, stream_chunk_builder from litellm.types.utils import ( diff --git a/tests/test_litellm/litellm_core_utils/test_streaming_chunk_builder_utils.py b/tests/test_litellm/litellm_core_utils/test_streaming_chunk_builder_utils.py index 0f21cce476b..44e77506b3f 100644 --- a/tests/test_litellm/litellm_core_utils/test_streaming_chunk_builder_utils.py +++ b/tests/test_litellm/litellm_core_utils/test_streaming_chunk_builder_utils.py @@ -1,12 +1,7 @@ import json -import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from litellm import ChatCompletionUsageBlock, stream_chunk_builder from litellm.types.utils import GenericStreamingChunk diff --git a/tests/test_litellm/litellm_core_utils/test_streaming_handler.py b/tests/test_litellm/litellm_core_utils/test_streaming_handler.py index fbdfcac1adc..b5e33a4e421 100644 --- a/tests/test_litellm/litellm_core_utils/test_streaming_handler.py +++ b/tests/test_litellm/litellm_core_utils/test_streaming_handler.py @@ -1,14 +1,9 @@ import json -import os -import sys import time from unittest.mock import AsyncMock, MagicMock, Mock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path import asyncio import traceback from typing import Optional diff --git a/tests/test_litellm/litellm_core_utils/test_token_counter.py b/tests/test_litellm/litellm_core_utils/test_token_counter.py index ee3e7719d52..a2590dbca2d 100644 --- a/tests/test_litellm/litellm_core_utils/test_token_counter.py +++ b/tests/test_litellm/litellm_core_utils/test_token_counter.py @@ -1,8 +1,6 @@ #### What this tests #### # This tests litellm.token_counter.token_counter() function import importlib -import os -import sys import time import traceback from unittest.mock import MagicMock @@ -10,9 +8,6 @@ from unittest.mock import MagicMock import pytest import tiktoken -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from unittest.mock import AsyncMock, patch import litellm diff --git a/tests/test_litellm/litellm_core_utils/test_token_counter_tool.py b/tests/test_litellm/litellm_core_utils/test_token_counter_tool.py index e8836bab2b9..9f8c1070a47 100644 --- a/tests/test_litellm/litellm_core_utils/test_token_counter_tool.py +++ b/tests/test_litellm/litellm_core_utils/test_token_counter_tool.py @@ -1,13 +1,8 @@ #### What this tests #### # This tests litellm.token_counter() function -import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path # Use the same token_counter as the main test. from tests.test_litellm.litellm_core_utils.test_token_counter import token_counter diff --git a/tests/test_litellm/litellm_core_utils/test_tool_search_spend_logging.py b/tests/test_litellm/litellm_core_utils/test_tool_search_spend_logging.py index 813b4a5701f..3d6c7e6b8d8 100644 --- a/tests/test_litellm/litellm_core_utils/test_tool_search_spend_logging.py +++ b/tests/test_litellm/litellm_core_utils/test_tool_search_spend_logging.py @@ -26,10 +26,7 @@ These tests exercise the real public entry points (not the private ``_count_content_list`` helper) so the whole chain is covered end to end. """ -import os -import sys -sys.path.insert(0, os.path.abspath("../../..")) import litellm from litellm import stream_chunk_builder diff --git a/tests/test_litellm/litellm_core_utils/test_xai_oauth_routing.py b/tests/test_litellm/litellm_core_utils/test_xai_oauth_routing.py index 03790b220eb..ca25ee80c23 100644 --- a/tests/test_litellm/litellm_core_utils/test_xai_oauth_routing.py +++ b/tests/test_litellm/litellm_core_utils/test_xai_oauth_routing.py @@ -1,7 +1,4 @@ -import os -import sys -sys.path.insert(0, os.path.abspath("../../..")) import litellm from litellm import LlmProviders diff --git a/tests/test_litellm/llms/aiml/image_generation/test_aiml_image_generation_transformation.py b/tests/test_litellm/llms/aiml/image_generation/test_aiml_image_generation_transformation.py index dd74379a883..8d6c61b890c 100644 --- a/tests/test_litellm/llms/aiml/image_generation/test_aiml_image_generation_transformation.py +++ b/tests/test_litellm/llms/aiml/image_generation/test_aiml_image_generation_transformation.py @@ -1,9 +1,7 @@ import os -import sys import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) os.environ["LITELLM_LOCAL_MODEL_COST_MAP"] = "True" diff --git a/tests/test_litellm/llms/amazon_nova/chat/test_amazon_nova_chat_completion.py b/tests/test_litellm/llms/amazon_nova/chat/test_amazon_nova_chat_completion.py index d7f464e4052..ecdd1b36333 100644 --- a/tests/test_litellm/llms/amazon_nova/chat/test_amazon_nova_chat_completion.py +++ b/tests/test_litellm/llms/amazon_nova/chat/test_amazon_nova_chat_completion.py @@ -1,9 +1,7 @@ import os -import sys import pytest # Ensure the project root is on the import path -sys.path.insert(0, os.path.abspath("../../../../../..")) from litellm import completion from litellm.types.utils import ModelResponse, Usage, Choices, Message diff --git a/tests/test_litellm/llms/anthropic/batches/test_handler.py b/tests/test_litellm/llms/anthropic/batches/test_handler.py index 0a472d86257..6fde6350127 100644 --- a/tests/test_litellm/llms/anthropic/batches/test_handler.py +++ b/tests/test_litellm/llms/anthropic/batches/test_handler.py @@ -14,14 +14,11 @@ asyncio.run) is exercised directly, mirroring the dispatch-contract discipline i tests/test_litellm/batches/test_main.py. """ -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import httpx import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm.llms.anthropic.batches.handler import AnthropicBatchesHandler from litellm.types.utils import LiteLLMBatch diff --git a/tests/test_litellm/llms/anthropic/batches/test_transformation.py b/tests/test_litellm/llms/anthropic/batches/test_transformation.py index 1635abcefd8..eacd2c9d03b 100644 --- a/tests/test_litellm/llms/anthropic/batches/test_transformation.py +++ b/tests/test_litellm/llms/anthropic/batches/test_transformation.py @@ -14,15 +14,12 @@ otherwise read process env / secret managers - mocking them keeps the URL/header assertions deterministic without touching production transform logic. """ -import os -import sys import time from unittest.mock import MagicMock, patch import httpx import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm.llms.anthropic.batches.transformation import AnthropicBatchesConfig from litellm.types.utils import LiteLLMBatch, LlmProviders diff --git a/tests/test_litellm/llms/anthropic/chat/guardrail_translation/test_anthropic_guardrail_handler.py b/tests/test_litellm/llms/anthropic/chat/guardrail_translation/test_anthropic_guardrail_handler.py index b219dcba491..2b392456763 100644 --- a/tests/test_litellm/llms/anthropic/chat/guardrail_translation/test_anthropic_guardrail_handler.py +++ b/tests/test_litellm/llms/anthropic/chat/guardrail_translation/test_anthropic_guardrail_handler.py @@ -6,16 +6,11 @@ with guardrail transformations, specifically testing edge cases with empty choic """ import json -import os -import sys from typing import Any, Literal, Optional from unittest.mock import MagicMock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../../../../../../..") -) # Adds the parent directory to the system path from litellm.integrations.custom_guardrail import CustomGuardrail from litellm.llms.anthropic.chat.guardrail_translation.handler import ( diff --git a/tests/test_litellm/llms/anthropic/chat/test_anthropic_chat_transformation.py b/tests/test_litellm/llms/anthropic/chat/test_anthropic_chat_transformation.py index 43f27cc85f9..4f340ee0f3f 100644 --- a/tests/test_litellm/llms/anthropic/chat/test_anthropic_chat_transformation.py +++ b/tests/test_litellm/llms/anthropic/chat/test_anthropic_chat_transformation.py @@ -1,11 +1,6 @@ -import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path from unittest.mock import MagicMock, patch import litellm diff --git a/tests/test_litellm/llms/anthropic/experimental_pass_through/adapters/test_anthropic_experimental_pass_through_adapters_transformation.py b/tests/test_litellm/llms/anthropic/experimental_pass_through/adapters/test_anthropic_experimental_pass_through_adapters_transformation.py index b216e8eef6d..e4dacc308dc 100644 --- a/tests/test_litellm/llms/anthropic/experimental_pass_through/adapters/test_anthropic_experimental_pass_through_adapters_transformation.py +++ b/tests/test_litellm/llms/anthropic/experimental_pass_through/adapters/test_anthropic_experimental_pass_through_adapters_transformation.py @@ -1,12 +1,9 @@ -import os -import sys from typing import Any, cast import pytest import litellm -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm.litellm_core_utils.prompt_templates.common_utils import ( diff --git a/tests/test_litellm/llms/anthropic/experimental_pass_through/adapters/test_streaming_iterator_compaction.py b/tests/test_litellm/llms/anthropic/experimental_pass_through/adapters/test_streaming_iterator_compaction.py index 076d4392f05..5c53a8fc317 100644 --- a/tests/test_litellm/llms/anthropic/experimental_pass_through/adapters/test_streaming_iterator_compaction.py +++ b/tests/test_litellm/llms/anthropic/experimental_pass_through/adapters/test_streaming_iterator_compaction.py @@ -1,13 +1,10 @@ """Compaction block SSE events from AnthropicStreamWrapper (compact_20260112 polyfill).""" -import os -import sys from typing import List from unittest.mock import MagicMock import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm.llms.anthropic.experimental_pass_through.adapters.streaming_iterator import ( AnthropicStreamWrapper, diff --git a/tests/test_litellm/llms/anthropic/experimental_pass_through/adapters/test_streaming_iterator_first_delta.py b/tests/test_litellm/llms/anthropic/experimental_pass_through/adapters/test_streaming_iterator_first_delta.py index bd02c61752e..f64ffb6d233 100644 --- a/tests/test_litellm/llms/anthropic/experimental_pass_through/adapters/test_streaming_iterator_first_delta.py +++ b/tests/test_litellm/llms/anthropic/experimental_pass_through/adapters/test_streaming_iterator_first_delta.py @@ -21,14 +21,11 @@ into an open ``thinking`` block, crashing Anthropic SDK clients (Claude Code) with "Content block is not a text block". """ -import os -import sys from typing import List, Optional from unittest.mock import MagicMock import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm.llms.anthropic.experimental_pass_through.adapters.streaming_iterator import ( AnthropicStreamWrapper, diff --git a/tests/test_litellm/llms/anthropic/experimental_pass_through/adapters/test_streaming_iterator_tool_args.py b/tests/test_litellm/llms/anthropic/experimental_pass_through/adapters/test_streaming_iterator_tool_args.py index bd39e420607..29e9279731d 100644 --- a/tests/test_litellm/llms/anthropic/experimental_pass_through/adapters/test_streaming_iterator_tool_args.py +++ b/tests/test_litellm/llms/anthropic/experimental_pass_through/adapters/test_streaming_iterator_tool_args.py @@ -8,14 +8,11 @@ Without the fix, the AnthropicStreamWrapper silently dropped these arguments, causing tool_use blocks to arrive with empty input {}. """ -import os -import sys from typing import List from unittest.mock import MagicMock import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm.llms.anthropic.experimental_pass_through.adapters.streaming_iterator import ( AnthropicStreamWrapper, diff --git a/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_agentic_streaming_iterator.py b/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_agentic_streaming_iterator.py index b9bda07336f..db8aae6702f 100644 --- a/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_agentic_streaming_iterator.py +++ b/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_agentic_streaming_iterator.py @@ -3,14 +3,11 @@ Tests for AgenticAnthropicStreamingIterator and SSE rebuild helpers. """ import json -import os -import sys from typing import Any, Dict, List, Optional, Tuple from unittest.mock import AsyncMock, MagicMock import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm.llms.anthropic.experimental_pass_through.messages.agentic_streaming_iterator import ( AgenticAnthropicStreamingIterator, diff --git a/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_anthropic_experimental_pass_through_messages_handler.py b/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_anthropic_experimental_pass_through_messages_handler.py index 1ce683d76fc..570ce152714 100644 --- a/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_anthropic_experimental_pass_through_messages_handler.py +++ b/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_anthropic_experimental_pass_through_messages_handler.py @@ -1,12 +1,10 @@ import json import os -import sys import httpx import pytest from fastapi.testclient import TestClient -sys.path.insert(0, os.path.abspath("../../../../..")) from unittest.mock import AsyncMock, MagicMock, patch diff --git a/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_content_after_stop_reason.py b/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_content_after_stop_reason.py index eadc0da2f1f..a0d1f9de6ec 100644 --- a/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_content_after_stop_reason.py +++ b/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_content_after_stop_reason.py @@ -12,13 +12,10 @@ The wrapper should properly handle this by: - Properly managing content_block_stop/start events for subsequent content """ -import os -import sys from typing import List import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm.llms.anthropic.experimental_pass_through.adapters.streaming_iterator import ( AnthropicStreamWrapper, diff --git a/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_mcp_handler.py b/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_mcp_handler.py index f3cb2956aeb..b6914809263 100644 --- a/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_mcp_handler.py +++ b/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_mcp_handler.py @@ -1,10 +1,7 @@ -import os -import sys from unittest.mock import AsyncMock, patch import pytest -sys.path.insert(0, os.path.abspath("../../../../../..")) from litellm.llms.anthropic.experimental_pass_through.messages.handler import ( anthropic_messages_handler, diff --git a/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_parallel_tool_calls.py b/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_parallel_tool_calls.py index 6d7cd2f88be..137286a18c4 100644 --- a/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_parallel_tool_calls.py +++ b/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_parallel_tool_calls.py @@ -1,9 +1,6 @@ -import os -import sys from typing import List -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm.llms.anthropic.experimental_pass_through.adapters.streaming_iterator import ( AnthropicStreamWrapper, diff --git a/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_reasoning_auto_summary_messages.py b/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_reasoning_auto_summary_messages.py index 07c0012b04d..f478bbb9b50 100644 --- a/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_reasoning_auto_summary_messages.py +++ b/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_reasoning_auto_summary_messages.py @@ -8,12 +8,10 @@ modes (type="enabled" or type="adaptive"). """ import os -import sys import pytest from unittest.mock import MagicMock, patch -sys.path.insert(0, os.path.abspath("../../../../..")) import litellm from litellm.llms.anthropic.experimental_pass_through.messages.handler import ( diff --git a/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_response_cache.py b/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_response_cache.py index 3fe1b6b0e38..fe0bcfa4f30 100644 --- a/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_response_cache.py +++ b/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_response_cache.py @@ -1,11 +1,8 @@ import asyncio -import os -import sys from typing import Any, AsyncIterator, Dict, List import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) import litellm from litellm.caching.caching import Cache, LiteLLMCacheType diff --git a/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_sse_wrapper.py b/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_sse_wrapper.py index 63fed907c3c..bebdbe9f512 100644 --- a/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_sse_wrapper.py +++ b/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_sse_wrapper.py @@ -1,10 +1,7 @@ -import os -import sys import pytest from fastapi.testclient import TestClient -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm.llms.anthropic.experimental_pass_through.adapters.streaming_iterator import ( AnthropicStreamWrapper, diff --git a/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_streaming_iterator.py b/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_streaming_iterator.py index 5c1cd88835f..f33bb3dda8b 100644 --- a/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_streaming_iterator.py +++ b/tests/test_litellm/llms/anthropic/experimental_pass_through/messages/test_streaming_iterator.py @@ -1,12 +1,9 @@ import asyncio import json -import os -import sys from datetime import datetime import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj from litellm.llms.anthropic.experimental_pass_through.messages.streaming_iterator import ( diff --git a/tests/test_litellm/llms/anthropic/experimental_pass_through/responses_adapters/test_responses_adapters_transformation.py b/tests/test_litellm/llms/anthropic/experimental_pass_through/responses_adapters/test_responses_adapters_transformation.py index 17bab9bf6a5..964f4b9f68b 100644 --- a/tests/test_litellm/llms/anthropic/experimental_pass_through/responses_adapters/test_responses_adapters_transformation.py +++ b/tests/test_litellm/llms/anthropic/experimental_pass_through/responses_adapters/test_responses_adapters_transformation.py @@ -5,13 +5,11 @@ Tests for LiteLLMAnthropicToResponsesAPIAdapter import json import os -import sys from typing import Any, Dict, List from unittest.mock import MagicMock import pytest -sys.path.insert(0, os.path.abspath("../../../../../../..")) from litellm.constants import ( DEFAULT_REASONING_EFFORT_HIGH_THINKING_BUDGET, diff --git a/tests/test_litellm/llms/anthropic/test_anthropic_common_utils.py b/tests/test_litellm/llms/anthropic/test_anthropic_common_utils.py index e519fab896a..c27362bf49f 100644 --- a/tests/test_litellm/llms/anthropic/test_anthropic_common_utils.py +++ b/tests/test_litellm/llms/anthropic/test_anthropic_common_utils.py @@ -554,7 +554,7 @@ class TestProxyOAuthHeaderForwarding: def test_add_provider_specific_headers_forwards_oauth(self): """add_provider_specific_headers_to_request should forward OAuth Authorization - as a ProviderSpecificHeader scoped to Anthropic-compatible providers.""" + as a ProviderSpecificHeader scoped to Anthropic and nothing else.""" from litellm.proxy.litellm_pre_call_utils import ( add_provider_specific_headers_to_request, ) @@ -569,9 +569,7 @@ class TestProxyOAuthHeaderForwarding: assert "provider_specific_header" in data psh = data["provider_specific_header"] - assert "anthropic" in psh["custom_llm_provider"] - assert "bedrock" in psh["custom_llm_provider"] - assert "vertex_ai" in psh["custom_llm_provider"] + assert psh["custom_llm_provider"] == "anthropic" assert psh["extra_headers"]["authorization"] == f"Bearer {FAKE_OAUTH_TOKEN}" def test_add_provider_specific_headers_ignores_non_oauth(self): @@ -593,7 +591,10 @@ class TestProxyOAuthHeaderForwarding: def test_add_provider_specific_headers_combines_anthropic_and_oauth(self): """When both anthropic-beta and OAuth Authorization are present, both - should be included in the ProviderSpecificHeader.""" + reach Anthropic.""" + from litellm.litellm_core_utils.get_provider_specific_headers import ( + ProviderSpecificHeaderUtils, + ) from litellm.proxy.litellm_pre_call_utils import ( add_provider_specific_headers_to_request, ) @@ -608,9 +609,12 @@ class TestProxyOAuthHeaderForwarding: add_provider_specific_headers_to_request(data=data, headers=headers) assert "provider_specific_header" in data - psh = data["provider_specific_header"] - assert psh["extra_headers"]["authorization"] == f"Bearer {FAKE_OAUTH_TOKEN}" - assert psh["extra_headers"]["anthropic-beta"] == "oauth-2025-04-20" + anthropic_headers = ProviderSpecificHeaderUtils.get_provider_specific_headers( + provider_specific_header=data["provider_specific_header"], + custom_llm_provider="anthropic", + ) + assert anthropic_headers["authorization"] == f"Bearer {FAKE_OAUTH_TOKEN}" + assert anthropic_headers["anthropic-beta"] == "oauth-2025-04-20" def test_clean_headers_forwards_x_api_key_when_authenticated_with_litellm_key(self): """clean_headers should forward x-api-key when user authenticated with x-litellm-api-key and forward_llm_provider_auth_headers=True.""" diff --git a/tests/test_litellm/llms/anthropic/test_anthropic_count_tokens_transformation.py b/tests/test_litellm/llms/anthropic/test_anthropic_count_tokens_transformation.py index 889809140f8..ddac561f337 100644 --- a/tests/test_litellm/llms/anthropic/test_anthropic_count_tokens_transformation.py +++ b/tests/test_litellm/llms/anthropic/test_anthropic_count_tokens_transformation.py @@ -1,9 +1,4 @@ -import os -import sys -sys.path.insert( - 0, os.path.abspath("../../../..") -) # Adds the parent directory to the system path from litellm.llms.anthropic.count_tokens.transformation import ( AnthropicCountTokensConfig, ) diff --git a/tests/test_litellm/llms/anthropic/test_anthropic_files_and_batches.py b/tests/test_litellm/llms/anthropic/test_anthropic_files_and_batches.py index fecc34694d5..2728ba03ae4 100644 --- a/tests/test_litellm/llms/anthropic/test_anthropic_files_and_batches.py +++ b/tests/test_litellm/llms/anthropic/test_anthropic_files_and_batches.py @@ -8,11 +8,8 @@ Tests for: """ import json -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch -sys.path.insert(0, os.path.abspath("../../../../")) import httpx import pytest diff --git a/tests/test_litellm/llms/anthropic/test_azure_ai_cache_pricing.py b/tests/test_litellm/llms/anthropic/test_azure_ai_cache_pricing.py index 97b8ab92a8e..69738118d7a 100644 --- a/tests/test_litellm/llms/anthropic/test_azure_ai_cache_pricing.py +++ b/tests/test_litellm/llms/anthropic/test_azure_ai_cache_pricing.py @@ -3,10 +3,7 @@ Test that Azure AI Anthropic models have cache pricing configured. Verifies the fix for issue #19532. """ -import sys -import os -sys.path.insert(0, os.path.abspath("../../../../../")) import litellm from litellm import get_model_info diff --git a/tests/test_litellm/llms/anthropic/test_cost_calculation_dict_safety.py b/tests/test_litellm/llms/anthropic/test_cost_calculation_dict_safety.py index 70fef0162e6..5c88ae17679 100644 --- a/tests/test_litellm/llms/anthropic/test_cost_calculation_dict_safety.py +++ b/tests/test_litellm/llms/anthropic/test_cost_calculation_dict_safety.py @@ -5,12 +5,9 @@ being either a ``dict`` or a ``ServerToolUse`` pydantic instance. See https://github.com/BerriAI/litellm/issues/26153. """ -import os -import sys import pytest -sys.path.insert(0, os.path.abspath("../../../..")) from litellm.llms.anthropic.cost_calculation import ( _get_web_search_requests, diff --git a/tests/test_litellm/llms/azure/batches/test_handler.py b/tests/test_litellm/llms/azure/batches/test_handler.py index f2332a7de7c..27876405781 100644 --- a/tests/test_litellm/llms/azure/batches/test_handler.py +++ b/tests/test_litellm/llms/azure/batches/test_handler.py @@ -21,13 +21,10 @@ runs for real. from __future__ import annotations import asyncio -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) from openai import AsyncOpenAI, OpenAI # noqa: E402 diff --git a/tests/test_litellm/llms/azure/chat/test_azure_chat_o_series_transformation.py b/tests/test_litellm/llms/azure/chat/test_azure_chat_o_series_transformation.py index 31c76c42599..fc7e94a77ba 100644 --- a/tests/test_litellm/llms/azure/chat/test_azure_chat_o_series_transformation.py +++ b/tests/test_litellm/llms/azure/chat/test_azure_chat_o_series_transformation.py @@ -1,15 +1,10 @@ import json -import os -import sys import traceback from typing import Callable, Optional from unittest.mock import MagicMock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path import litellm from litellm.llms.azure.chat.o_series_transformation import AzureOpenAIO1Config diff --git a/tests/test_litellm/llms/azure/image_generation/test_azure_image_generation_init.py b/tests/test_litellm/llms/azure/image_generation/test_azure_image_generation_init.py index 857ed9d22a6..560fee17328 100644 --- a/tests/test_litellm/llms/azure/image_generation/test_azure_image_generation_init.py +++ b/tests/test_litellm/llms/azure/image_generation/test_azure_image_generation_init.py @@ -1,15 +1,10 @@ import json -import os -import sys import traceback from typing import Callable, Optional from unittest.mock import AsyncMock, MagicMock, Mock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path import litellm from litellm.llms.azure.azure import AzureChatCompletion from litellm.llms.azure.image_generation.http_utils import ( diff --git a/tests/test_litellm/llms/azure/passthrough/test_azure_passthrough_transformation.py b/tests/test_litellm/llms/azure/passthrough/test_azure_passthrough_transformation.py index 529a7453d74..29b74c2ee4a 100644 --- a/tests/test_litellm/llms/azure/passthrough/test_azure_passthrough_transformation.py +++ b/tests/test_litellm/llms/azure/passthrough/test_azure_passthrough_transformation.py @@ -1,11 +1,8 @@ import json -import os -import sys from unittest.mock import MagicMock import httpx -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm.llms.azure.passthrough.transformation import AzurePassthroughConfig from litellm.types.utils import ModelResponse diff --git a/tests/test_litellm/llms/azure/realtime/test_azure_realtime_handler.py b/tests/test_litellm/llms/azure/realtime/test_azure_realtime_handler.py index 4638bc4df0f..c14a1cfdda3 100644 --- a/tests/test_litellm/llms/azure/realtime/test_azure_realtime_handler.py +++ b/tests/test_litellm/llms/azure/realtime/test_azure_realtime_handler.py @@ -1,14 +1,10 @@ import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import pytest from litellm.llms.custom_httpx.http_handler import get_shared_realtime_ssl_context -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path @pytest.mark.asyncio diff --git a/tests/test_litellm/llms/azure/response/test_azure_transformation.py b/tests/test_litellm/llms/azure/response/test_azure_transformation.py index 24ae563fb76..da44394d11d 100644 --- a/tests/test_litellm/llms/azure/response/test_azure_transformation.py +++ b/tests/test_litellm/llms/azure/response/test_azure_transformation.py @@ -1,13 +1,8 @@ -import os -import sys from copy import deepcopy from unittest.mock import patch import pytest -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path from unittest.mock import MagicMock diff --git a/tests/test_litellm/llms/azure/test_azure_common_utils.py b/tests/test_litellm/llms/azure/test_azure_common_utils.py index 99826c14069..f2c852e9509 100644 --- a/tests/test_litellm/llms/azure/test_azure_common_utils.py +++ b/tests/test_litellm/llms/azure/test_azure_common_utils.py @@ -1,15 +1,11 @@ import json import os -import sys import traceback from typing import Callable, Optional from unittest.mock import MagicMock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../../../..") -) # Adds the parent directory to the system path import litellm from litellm.llms.azure.common_utils import BaseAzureLLM, get_azure_ad_token from litellm.secret_managers.get_azure_ad_token_provider import ( @@ -812,7 +808,6 @@ async def test_azure_client_reuse(function_name, is_async, args): """ Test that multiple Azure API calls reuse the same Azure OpenAI client """ - litellm.set_verbose = True # Determine which client class to mock based on whether the test is async client_path = ( diff --git a/tests/test_litellm/llms/azure/test_azure_exception_mapping.py b/tests/test_litellm/llms/azure/test_azure_exception_mapping.py index b172c401e2f..16560c7a1fa 100644 --- a/tests/test_litellm/llms/azure/test_azure_exception_mapping.py +++ b/tests/test_litellm/llms/azure/test_azure_exception_mapping.py @@ -1,13 +1,8 @@ import json -import os -import sys from unittest.mock import MagicMock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../../../..") -) # Adds the parent directory to the system path import litellm from litellm.exceptions import ContentPolicyViolationError diff --git a/tests/test_litellm/llms/azure_ai/chat/test_azure_ai_transformation.py b/tests/test_litellm/llms/azure_ai/chat/test_azure_ai_transformation.py index 900372f3e54..0fd9a381a5a 100644 --- a/tests/test_litellm/llms/azure_ai/chat/test_azure_ai_transformation.py +++ b/tests/test_litellm/llms/azure_ai/chat/test_azure_ai_transformation.py @@ -1,13 +1,8 @@ import json -import os -import sys from unittest.mock import MagicMock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path from litellm.llms.azure_ai.azure_model_router.transformation import ( AzureModelRouterConfig, ) diff --git a/tests/test_litellm/llms/azure_ai/claude/test_azure_anthropic_count_tokens_transformation.py b/tests/test_litellm/llms/azure_ai/claude/test_azure_anthropic_count_tokens_transformation.py index d66798a5725..4b317cff975 100644 --- a/tests/test_litellm/llms/azure_ai/claude/test_azure_anthropic_count_tokens_transformation.py +++ b/tests/test_litellm/llms/azure_ai/claude/test_azure_anthropic_count_tokens_transformation.py @@ -4,12 +4,7 @@ Tests for Azure AI Anthropic CountTokens transformation. Verifies that the CountTokens API uses the correct authentication headers. """ -import os -import sys -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path from litellm.llms.azure_ai.anthropic.count_tokens.transformation import ( diff --git a/tests/test_litellm/llms/azure_ai/image_edit/test_azure_ai_image_edit_transformation.py b/tests/test_litellm/llms/azure_ai/image_edit/test_azure_ai_image_edit_transformation.py index da1041f3d60..667552dcf60 100644 --- a/tests/test_litellm/llms/azure_ai/image_edit/test_azure_ai_image_edit_transformation.py +++ b/tests/test_litellm/llms/azure_ai/image_edit/test_azure_ai_image_edit_transformation.py @@ -1,9 +1,4 @@ -import os -import sys -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path from litellm.llms.azure_ai.image_edit.transformation import ( AzureFoundryFluxImageEditConfig, diff --git a/tests/test_litellm/llms/azure_ai/image_edit/test_mai_image_edit_transformation.py b/tests/test_litellm/llms/azure_ai/image_edit/test_mai_image_edit_transformation.py index d5256be02d7..b948e46093a 100644 --- a/tests/test_litellm/llms/azure_ai/image_edit/test_mai_image_edit_transformation.py +++ b/tests/test_litellm/llms/azure_ai/image_edit/test_mai_image_edit_transformation.py @@ -1,12 +1,9 @@ import io -import os -import sys from unittest.mock import MagicMock import httpx import pytest -sys.path.insert(0, os.path.abspath("../../../../../..")) from litellm.llms.azure_ai.image_edit import ( AzureFoundryMAIImageEditConfig, diff --git a/tests/test_litellm/llms/azure_ai/image_generation/test_mai_image_generation.py b/tests/test_litellm/llms/azure_ai/image_generation/test_mai_image_generation.py index 30f479bd7ff..2a44e77ce09 100644 --- a/tests/test_litellm/llms/azure_ai/image_generation/test_mai_image_generation.py +++ b/tests/test_litellm/llms/azure_ai/image_generation/test_mai_image_generation.py @@ -1,11 +1,9 @@ import os -import sys from unittest.mock import MagicMock import httpx import pytest -sys.path.insert(0, os.path.abspath("../../../../../..")) import litellm from litellm.llms.azure.azure import AzureChatCompletion diff --git a/tests/test_litellm/llms/azure_ai/rerank/test_azure_ai_rerank_transformation.py b/tests/test_litellm/llms/azure_ai/rerank/test_azure_ai_rerank_transformation.py index 602cbf68f3f..ab497d06ca7 100644 --- a/tests/test_litellm/llms/azure_ai/rerank/test_azure_ai_rerank_transformation.py +++ b/tests/test_litellm/llms/azure_ai/rerank/test_azure_ai_rerank_transformation.py @@ -1,11 +1,6 @@ -import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path from litellm.llms.azure_ai.rerank.transformation import AzureAIRerankConfig diff --git a/tests/test_litellm/llms/base_llm/batches/base_batches_config_test.py b/tests/test_litellm/llms/base_llm/batches/base_batches_config_test.py index fd526c55de4..5195dd8ba44 100644 --- a/tests/test_litellm/llms/base_llm/batches/base_batches_config_test.py +++ b/tests/test_litellm/llms/base_llm/batches/base_batches_config_test.py @@ -19,14 +19,11 @@ transformation is a standalone class with a different shape) cannot use this and keep fully standalone tests. """ -import os -import sys from unittest.mock import MagicMock import httpx import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm.types.utils import LiteLLMBatch, LlmProviders diff --git a/tests/test_litellm/llms/base_llm/batches/test_transformation.py b/tests/test_litellm/llms/base_llm/batches/test_transformation.py index cfb9f278f80..d84c820228f 100644 --- a/tests/test_litellm/llms/base_llm/batches/test_transformation.py +++ b/tests/test_litellm/llms/base_llm/batches/test_transformation.py @@ -18,12 +18,9 @@ filter, dropping the staticmethod/classmethod filter, or widening the prefix filter to all single-underscore names) makes a test fail. """ -import os -import sys import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm.llms.base_llm.batches.transformation import BaseBatchesConfig from litellm.types.utils import LlmProviders diff --git a/tests/test_litellm/llms/bedrock/batches/test_batch_metadata_sanitization.py b/tests/test_litellm/llms/bedrock/batches/test_batch_metadata_sanitization.py index 8de47331614..a34e4f5d5c9 100644 --- a/tests/test_litellm/llms/bedrock/batches/test_batch_metadata_sanitization.py +++ b/tests/test_litellm/llms/bedrock/batches/test_batch_metadata_sanitization.py @@ -9,12 +9,9 @@ when constructing LiteLLMBatch. This test suite verifies the sanitization layer prevents that. """ -import os -import sys import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm.llms.bedrock.batches.transformation import BedrockBatchesConfig diff --git a/tests/test_litellm/llms/bedrock/batches/test_handler.py b/tests/test_litellm/llms/bedrock/batches/test_handler.py index 1436ad2f383..d2dc89a7492 100644 --- a/tests/test_litellm/llms/bedrock/batches/test_handler.py +++ b/tests/test_litellm/llms/bedrock/batches/test_handler.py @@ -8,14 +8,11 @@ the tests don't hit AWS. from __future__ import annotations -import os -import sys from datetime import datetime, timezone from unittest.mock import MagicMock, patch import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm.llms.bedrock.batches.handler import ( # noqa: E402 BedrockBatchesHandler, diff --git a/tests/test_litellm/llms/bedrock/batches/test_transformation.py b/tests/test_litellm/llms/bedrock/batches/test_transformation.py index 01420eb10df..87f9c506857 100644 --- a/tests/test_litellm/llms/bedrock/batches/test_transformation.py +++ b/tests/test_litellm/llms/bedrock/batches/test_transformation.py @@ -14,14 +14,11 @@ URL/ARN handling, and the error class. AWS auth/sigv4 is the only external seam we mock; everything else runs for real. """ -import os -import sys from unittest.mock import MagicMock, patch import httpx import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm.llms.bedrock.batches.transformation import BedrockBatchesConfig from litellm.types.utils import LiteLLMBatch, LlmProviders diff --git a/tests/test_litellm/llms/bedrock/chat/agentcore/test_agentcore_transformation.py b/tests/test_litellm/llms/bedrock/chat/agentcore/test_agentcore_transformation.py index e5a2ea9b28f..ed8aab8d3d0 100644 --- a/tests/test_litellm/llms/bedrock/chat/agentcore/test_agentcore_transformation.py +++ b/tests/test_litellm/llms/bedrock/chat/agentcore/test_agentcore_transformation.py @@ -9,13 +9,10 @@ Tests: """ import json -import os -import sys import httpx import pytest -sys.path.insert(0, os.path.abspath("../../../../../..")) from unittest.mock import MagicMock, Mock, patch diff --git a/tests/test_litellm/llms/bedrock/chat/invoke_transformations/test_amazon_qwen2_transformation.py b/tests/test_litellm/llms/bedrock/chat/invoke_transformations/test_amazon_qwen2_transformation.py index 5f5a6512eac..4db786668b8 100644 --- a/tests/test_litellm/llms/bedrock/chat/invoke_transformations/test_amazon_qwen2_transformation.py +++ b/tests/test_litellm/llms/bedrock/chat/invoke_transformations/test_amazon_qwen2_transformation.py @@ -1,14 +1,11 @@ import asyncio import json -import os -import sys from unittest.mock import Mock import pytest # Ensure the project root is on the import path so `litellm` can be imported when # tests are executed from any working directory. -sys.path.insert(0, os.path.abspath("../../../../../..")) from litellm.llms.bedrock.chat.invoke_transformations.amazon_qwen2_transformation import ( AmazonQwen2Config, diff --git a/tests/test_litellm/llms/bedrock/chat/invoke_transformations/test_amazon_qwen3_transformation.py b/tests/test_litellm/llms/bedrock/chat/invoke_transformations/test_amazon_qwen3_transformation.py index fea210b6c47..e011b1fca2b 100644 --- a/tests/test_litellm/llms/bedrock/chat/invoke_transformations/test_amazon_qwen3_transformation.py +++ b/tests/test_litellm/llms/bedrock/chat/invoke_transformations/test_amazon_qwen3_transformation.py @@ -1,14 +1,11 @@ import asyncio import json -import os -import sys from unittest.mock import Mock import pytest # Ensure the project root is on the import path so `litellm` can be imported when # tests are executed from any working directory. -sys.path.insert(0, os.path.abspath("../../../../../..")) from litellm.llms.bedrock.chat.invoke_transformations.amazon_qwen3_transformation import ( AmazonQwen3Config, diff --git a/tests/test_litellm/llms/bedrock/chat/invoke_transformations/test_base_invoke_transformation.py b/tests/test_litellm/llms/bedrock/chat/invoke_transformations/test_base_invoke_transformation.py index 5fefae7e411..aba51689094 100644 --- a/tests/test_litellm/llms/bedrock/chat/invoke_transformations/test_base_invoke_transformation.py +++ b/tests/test_litellm/llms/bedrock/chat/invoke_transformations/test_base_invoke_transformation.py @@ -1,12 +1,7 @@ import json -import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../../../../../..") -) # Adds the parent directory to the system path from litellm.llms.bedrock.chat.invoke_transformations.anthropic_claude3_transformation import ( AmazonAnthropicClaudeConfig, diff --git a/tests/test_litellm/llms/bedrock/chat/invoke_transformations/test_bedrock_chat_invoke_transformations_anthropic_claude3_transformation.py b/tests/test_litellm/llms/bedrock/chat/invoke_transformations/test_bedrock_chat_invoke_transformations_anthropic_claude3_transformation.py index 4c4c0e17a38..cea299280f8 100644 --- a/tests/test_litellm/llms/bedrock/chat/invoke_transformations/test_bedrock_chat_invoke_transformations_anthropic_claude3_transformation.py +++ b/tests/test_litellm/llms/bedrock/chat/invoke_transformations/test_bedrock_chat_invoke_transformations_anthropic_claude3_transformation.py @@ -1,14 +1,11 @@ import asyncio import json -import os -import sys from unittest.mock import patch import pytest # Ensure the project root is on the import path so `litellm` can be imported when # tests are executed from any working directory. -sys.path.insert(0, os.path.abspath("../../../../../..")) from litellm.llms.bedrock.chat.invoke_transformations.anthropic_claude3_transformation import ( AmazonAnthropicClaudeConfig, diff --git a/tests/test_litellm/llms/bedrock/chat/test_converse_transformation.py b/tests/test_litellm/llms/bedrock/chat/test_converse_transformation.py index 2d6e938ea1f..604f3414775 100644 --- a/tests/test_litellm/llms/bedrock/chat/test_converse_transformation.py +++ b/tests/test_litellm/llms/bedrock/chat/test_converse_transformation.py @@ -1,14 +1,10 @@ import asyncio import json import os -import sys import pytest from fastapi.testclient import TestClient -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path from unittest.mock import MagicMock, patch import litellm diff --git a/tests/test_litellm/llms/bedrock/chat/test_converse_transformation_nova_2.py b/tests/test_litellm/llms/bedrock/chat/test_converse_transformation_nova_2.py index bac7aa08a04..58058a2e1d4 100644 --- a/tests/test_litellm/llms/bedrock/chat/test_converse_transformation_nova_2.py +++ b/tests/test_litellm/llms/bedrock/chat/test_converse_transformation_nova_2.py @@ -8,12 +8,7 @@ Reference: https://docs.aws.amazon.com/nova/latest/nova2-userguide/using-convers """ import pytest -import sys -import os -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import httpx import litellm diff --git a/tests/test_litellm/llms/bedrock/chat/test_invoke_handler.py b/tests/test_litellm/llms/bedrock/chat/test_invoke_handler.py index e8964910c69..e2892a6ccee 100644 --- a/tests/test_litellm/llms/bedrock/chat/test_invoke_handler.py +++ b/tests/test_litellm/llms/bedrock/chat/test_invoke_handler.py @@ -1,13 +1,8 @@ -import os -import sys from unittest.mock import AsyncMock, MagicMock import httpx import pytest -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path import litellm from litellm.llms.bedrock.chat.invoke_handler import ( diff --git a/tests/test_litellm/llms/bedrock/chat/test_service_tier.py b/tests/test_litellm/llms/bedrock/chat/test_service_tier.py index a625aae23df..ce9dc4d745e 100644 --- a/tests/test_litellm/llms/bedrock/chat/test_service_tier.py +++ b/tests/test_litellm/llms/bedrock/chat/test_service_tier.py @@ -3,14 +3,9 @@ Tests for Bedrock Converse API serviceTier support. """ import json -import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path from litellm.llms.bedrock.chat.converse_transformation import AmazonConverseConfig from litellm.types.llms.bedrock import ServiceTierBlock diff --git a/tests/test_litellm/llms/bedrock/chat/test_writer_palmyra.py b/tests/test_litellm/llms/bedrock/chat/test_writer_palmyra.py index 9bc6724867f..4acfa3f637f 100644 --- a/tests/test_litellm/llms/bedrock/chat/test_writer_palmyra.py +++ b/tests/test_litellm/llms/bedrock/chat/test_writer_palmyra.py @@ -2,14 +2,9 @@ Tests for Writer Palmyra X5 and X4 models on Bedrock Converse. """ -import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path from litellm.llms.bedrock.common_utils import BedrockModelInfo diff --git a/tests/test_litellm/llms/bedrock/count_tokens/test_bedrock_count_tokens_transformation.py b/tests/test_litellm/llms/bedrock/count_tokens/test_bedrock_count_tokens_transformation.py index 6812f40829a..b357c5ac126 100644 --- a/tests/test_litellm/llms/bedrock/count_tokens/test_bedrock_count_tokens_transformation.py +++ b/tests/test_litellm/llms/bedrock/count_tokens/test_bedrock_count_tokens_transformation.py @@ -1,11 +1,6 @@ import base64 import json -import os -import sys -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path from litellm.llms.bedrock.count_tokens.transformation import ( DEFAULT_ANTHROPIC_INVOKE_MODEL_MAX_TOKENS, BedrockCountTokensConfig, diff --git a/tests/test_litellm/llms/bedrock/embed/test_bedrock_async_invoke_embedding.py b/tests/test_litellm/llms/bedrock/embed/test_bedrock_async_invoke_embedding.py index 8b6034d1133..74a55cc1ef2 100644 --- a/tests/test_litellm/llms/bedrock/embed/test_bedrock_async_invoke_embedding.py +++ b/tests/test_litellm/llms/bedrock/embed/test_bedrock_async_invoke_embedding.py @@ -1,13 +1,8 @@ import json -import os -import sys from unittest.mock import Mock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path import litellm from litellm.llms.custom_httpx.http_handler import AsyncHTTPHandler, HTTPHandler from litellm.types.llms.base import HiddenParams @@ -153,7 +148,6 @@ class TestBedrockAsyncInvokeEmbedding: def test_async_invoke_twelvelabs_embedding_with_mock(self): """Test async invoke embedding with mocked HTTP calls.""" - litellm.set_verbose = True client = HTTPHandler() test_api_key = "test-bearer-token-12345" model = "bedrock/async_invoke/twelvelabs.marengo-embed-2-7-v1:0" @@ -193,7 +187,6 @@ class TestBedrockAsyncInvokeEmbedding: @pytest.mark.asyncio async def test_async_invoke_twelvelabs_embedding_async_with_mock(self): """Test async invoke embedding with async calls.""" - litellm.set_verbose = True client = AsyncHTTPHandler() test_api_key = "test-bearer-token-12345" model = "bedrock/async_invoke/twelvelabs.marengo-embed-2-7-v1:0" diff --git a/tests/test_litellm/llms/bedrock/embed/test_bedrock_embedding.py b/tests/test_litellm/llms/bedrock/embed/test_bedrock_embedding.py index e35365cd609..114e473be98 100644 --- a/tests/test_litellm/llms/bedrock/embed/test_bedrock_embedding.py +++ b/tests/test_litellm/llms/bedrock/embed/test_bedrock_embedding.py @@ -1,13 +1,9 @@ import json import os -import sys from unittest.mock import Mock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path import litellm from litellm.llms.custom_httpx.http_handler import AsyncHTTPHandler, HTTPHandler diff --git a/tests/test_litellm/llms/bedrock/embed/test_embedding.py b/tests/test_litellm/llms/bedrock/embed/test_embedding.py index 261448842f4..a6cf54a7870 100644 --- a/tests/test_litellm/llms/bedrock/embed/test_embedding.py +++ b/tests/test_litellm/llms/bedrock/embed/test_embedding.py @@ -1,9 +1,4 @@ -import os -import sys -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path from unittest.mock import patch import pytest diff --git a/tests/test_litellm/llms/bedrock/image/test_amazon_stability3_transformation.py b/tests/test_litellm/llms/bedrock/image/test_amazon_stability3_transformation.py index a758202d74f..dbde8565e13 100644 --- a/tests/test_litellm/llms/bedrock/image/test_amazon_stability3_transformation.py +++ b/tests/test_litellm/llms/bedrock/image/test_amazon_stability3_transformation.py @@ -1,13 +1,8 @@ import json -import os -import sys import pytest from fastapi.testclient import TestClient -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path from unittest.mock import MagicMock, patch from litellm.llms.bedrock.image_generation.amazon_stability3_transformation import ( diff --git a/tests/test_litellm/llms/bedrock/image/test_bedrock_image_bearer_token.py b/tests/test_litellm/llms/bedrock/image/test_bedrock_image_bearer_token.py index 41ac030ff07..7c36b2aa75f 100644 --- a/tests/test_litellm/llms/bedrock/image/test_bedrock_image_bearer_token.py +++ b/tests/test_litellm/llms/bedrock/image/test_bedrock_image_bearer_token.py @@ -1,12 +1,8 @@ import json import os -import sys from unittest.mock import Mock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path import litellm from litellm.llms.custom_httpx.http_handler import HTTPHandler, AsyncHTTPHandler @@ -18,7 +14,6 @@ mock_image_response = {"images": ["base64_encoded_image_data"], "error": None} class TestBedrockImageGeneration: def test_image_generation_with_api_key_bearer_token(self): """Test image generation with bearer token authentication""" - litellm.set_verbose = True test_api_key = "test-bearer-token-12345" model = "bedrock/stability.sd3-large-v1:0" prompt = "A cute baby sea otter" @@ -53,7 +48,6 @@ class TestBedrockImageGeneration: def test_image_generation_with_env_variable_bearer_token(self, monkeypatch): """Test image generation with bearer token from environment variable""" - litellm.set_verbose = True test_api_key = "env-bearer-token-12345" model = "bedrock/stability.sd3-large-v1:0" prompt = "A cute baby sea otter" @@ -90,7 +84,6 @@ class TestBedrockImageGeneration: @pytest.mark.asyncio async def test_async_image_generation_with_bearer_token(self): """Test async image generation with bearer token authentication""" - litellm.set_verbose = True test_api_key = "async-bearer-token-12345" model = "bedrock/stability.sd3-large-v1:0" prompt = "A cute baby sea otter" @@ -125,7 +118,6 @@ class TestBedrockImageGeneration: def test_image_generation_with_sigv4(self): """Test image generation falls back to SigV4 auth when no bearer token is provided""" - litellm.set_verbose = True model = "bedrock/stability.sd3-large-v1:0" prompt = "A cute baby sea otter" diff --git a/tests/test_litellm/llms/bedrock/invoke_agent/test_bedrock_agent_transformation.py b/tests/test_litellm/llms/bedrock/invoke_agent/test_bedrock_agent_transformation.py index 9e526e47784..3eb85449985 100644 --- a/tests/test_litellm/llms/bedrock/invoke_agent/test_bedrock_agent_transformation.py +++ b/tests/test_litellm/llms/bedrock/invoke_agent/test_bedrock_agent_transformation.py @@ -1,13 +1,8 @@ import base64 -import os -import sys from unittest.mock import patch import pytest -sys.path.insert( - 0, os.path.abspath("../../../..") -) # Adds the parent directory to the system path from litellm.llms.bedrock.chat.invoke_agent.transformation import ( AmazonInvokeAgentConfig, diff --git a/tests/test_litellm/llms/bedrock/messages/invoke_transformations/test_anthropic_claude3_transformation.py b/tests/test_litellm/llms/bedrock/messages/invoke_transformations/test_anthropic_claude3_transformation.py index 604388ce91a..d3c28302bf9 100644 --- a/tests/test_litellm/llms/bedrock/messages/invoke_transformations/test_anthropic_claude3_transformation.py +++ b/tests/test_litellm/llms/bedrock/messages/invoke_transformations/test_anthropic_claude3_transformation.py @@ -2,7 +2,6 @@ import asyncio import copy import json import os -import sys from datetime import datetime from types import SimpleNamespace from unittest.mock import Mock @@ -11,7 +10,6 @@ import pytest # Ensure the project root is on the import path so `litellm` can be imported when # tests are executed from any working directory. -sys.path.insert(0, os.path.abspath("../../../../../..")) from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj from litellm.llms.bedrock.common_utils import ( diff --git a/tests/test_litellm/llms/bedrock/passthrough/test_bedrock_passthrough_transformation.py b/tests/test_litellm/llms/bedrock/passthrough/test_bedrock_passthrough_transformation.py index 1c90b7c8c87..b005d77ac8b 100644 --- a/tests/test_litellm/llms/bedrock/passthrough/test_bedrock_passthrough_transformation.py +++ b/tests/test_litellm/llms/bedrock/passthrough/test_bedrock_passthrough_transformation.py @@ -1,10 +1,5 @@ -import os -import sys from unittest.mock import patch -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path from litellm.llms.bedrock.passthrough.transformation import BedrockPassthroughConfig diff --git a/tests/test_litellm/llms/bedrock/realtime/test_bedrock_realtime_handler.py b/tests/test_litellm/llms/bedrock/realtime/test_bedrock_realtime_handler.py index ffe21b91ab2..9efcee192b1 100644 --- a/tests/test_litellm/llms/bedrock/realtime/test_bedrock_realtime_handler.py +++ b/tests/test_litellm/llms/bedrock/realtime/test_bedrock_realtime_handler.py @@ -1,5 +1,4 @@ import json -import os import sys import types from types import SimpleNamespace @@ -7,7 +6,6 @@ from unittest.mock import MagicMock import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) # Adds the parent directory to the system path from litellm.llms.bedrock.common_utils import BedrockError from litellm.llms.bedrock.realtime.handler import BedrockRealtime diff --git a/tests/test_litellm/llms/bedrock/realtime/test_bedrock_realtime_transformation.py b/tests/test_litellm/llms/bedrock/realtime/test_bedrock_realtime_transformation.py index aa002b6e302..ae6b1febd6b 100644 --- a/tests/test_litellm/llms/bedrock/realtime/test_bedrock_realtime_transformation.py +++ b/tests/test_litellm/llms/bedrock/realtime/test_bedrock_realtime_transformation.py @@ -1,11 +1,8 @@ import json -import os -import sys from unittest.mock import MagicMock import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) # Adds the parent directory to the system path import base64 diff --git a/tests/test_litellm/llms/bedrock/rerank/test_bedrock_rerank_header_forwarding.py b/tests/test_litellm/llms/bedrock/rerank/test_bedrock_rerank_header_forwarding.py index 17443ca899e..b2a2046b131 100644 --- a/tests/test_litellm/llms/bedrock/rerank/test_bedrock_rerank_header_forwarding.py +++ b/tests/test_litellm/llms/bedrock/rerank/test_bedrock_rerank_header_forwarding.py @@ -6,15 +6,10 @@ forward_client_headers_to_llm_api were not being passed to Bedrock rerank provid """ import json -import os -import sys from unittest.mock import AsyncMock, MagicMock, Mock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path import litellm from litellm.llms.bedrock.base_aws_llm import Boto3CredentialsInfo from litellm.llms.custom_httpx.http_handler import AsyncHTTPHandler, HTTPHandler @@ -66,7 +61,6 @@ def test_bedrock_rerank_header_forwarding_sync(model): This test verifies the fix for the issue where headers configured via forward_client_headers_to_llm_api were not being passed to Bedrock rerank provider. """ - litellm.set_verbose = True client = HTTPHandler() test_api_key = "test-bearer-token-12345" @@ -160,7 +154,6 @@ async def test_bedrock_rerank_header_forwarding_async(model): This test verifies the fix for the issue where headers configured via forward_client_headers_to_llm_api were not being passed to Bedrock rerank provider. """ - litellm.set_verbose = True client = AsyncHTTPHandler() test_api_key = "test-bearer-token-12345" @@ -332,7 +325,6 @@ def test_bedrock_rerank_extra_headers_and_headers_merge(): This ensures that headers from kwargs (forwarded by proxy) and extra_headers (passed explicitly) are both included in the final headers sent to the provider. """ - litellm.set_verbose = True client = HTTPHandler() test_api_key = "test-bearer-token-12345" model = "bedrock/arn:aws:bedrock:us-east-1::foundation-model/cohere.rerank-v3-5:0" diff --git a/tests/test_litellm/llms/bedrock/rerank/transformation.py b/tests/test_litellm/llms/bedrock/rerank/transformation.py index 870a7cb1f1e..b45042d1f6a 100644 --- a/tests/test_litellm/llms/bedrock/rerank/transformation.py +++ b/tests/test_litellm/llms/bedrock/rerank/transformation.py @@ -1,13 +1,8 @@ import json -import os -import sys import pytest from fastapi.testclient import TestClient -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from unittest.mock import MagicMock, patch from litellm import rerank diff --git a/tests/test_litellm/llms/bedrock/test_base_aws_llm.py b/tests/test_litellm/llms/bedrock/test_base_aws_llm.py index b9f8283b78e..50e2b53c2b3 100644 --- a/tests/test_litellm/llms/bedrock/test_base_aws_llm.py +++ b/tests/test_litellm/llms/bedrock/test_base_aws_llm.py @@ -1,15 +1,11 @@ import json import os -import sys import threading import time import pytest from fastapi.testclient import TestClient -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from datetime import datetime, timedelta, timezone diff --git a/tests/test_litellm/llms/bedrock/test_bedrock_common_utils.py b/tests/test_litellm/llms/bedrock/test_bedrock_common_utils.py index 83f3d73015d..389bf4a8e40 100644 --- a/tests/test_litellm/llms/bedrock/test_bedrock_common_utils.py +++ b/tests/test_litellm/llms/bedrock/test_bedrock_common_utils.py @@ -1,11 +1,6 @@ -import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../../../..") -) # Adds the parent directory to the system path from litellm.llms.bedrock.common_utils import BedrockModelInfo diff --git a/tests/test_litellm/llms/bedrock/test_bedrock_ssl_verify.py b/tests/test_litellm/llms/bedrock/test_bedrock_ssl_verify.py index 962933aba28..75e9a8afcb6 100644 --- a/tests/test_litellm/llms/bedrock/test_bedrock_ssl_verify.py +++ b/tests/test_litellm/llms/bedrock/test_bedrock_ssl_verify.py @@ -10,13 +10,11 @@ being applied to boto3 clients, causing "certificate verify failed" errors. """ import os -import sys import tempfile from unittest.mock import MagicMock, Mock, patch import pytest -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm.llms.bedrock.base_aws_llm import BaseAWSLLM diff --git a/tests/test_litellm/llms/bedrock/test_cross_region_inference_profile_mapping.py b/tests/test_litellm/llms/bedrock/test_cross_region_inference_profile_mapping.py index 22aba59fb5d..dbd31c7e81b 100644 --- a/tests/test_litellm/llms/bedrock/test_cross_region_inference_profile_mapping.py +++ b/tests/test_litellm/llms/bedrock/test_cross_region_inference_profile_mapping.py @@ -1,15 +1,12 @@ """Test Bedrock cross-region inference profile model mapping""" import json -import os -import sys from functools import lru_cache from pathlib import Path from typing import NamedTuple import pytest -sys.path.insert(0, os.path.abspath("../../../..")) import litellm from litellm.llms.bedrock.chat.converse_transformation import AmazonConverseConfig diff --git a/tests/test_litellm/llms/bedrock/test_request_metadata.py b/tests/test_litellm/llms/bedrock/test_request_metadata.py index 79b8990a3af..5a14bbea9f2 100644 --- a/tests/test_litellm/llms/bedrock/test_request_metadata.py +++ b/tests/test_litellm/llms/bedrock/test_request_metadata.py @@ -1,11 +1,8 @@ import asyncio import json -import os -import sys import pytest -sys.path.insert(0, os.path.abspath("../../../..")) import litellm from litellm.llms.bedrock.base_aws_llm import BaseAWSLLM diff --git a/tests/test_litellm/llms/bedrock_mantle/test_bedrock_mantle_responses_transformation.py b/tests/test_litellm/llms/bedrock_mantle/test_bedrock_mantle_responses_transformation.py index 28c8e5c7ed6..9e05d48a18f 100644 --- a/tests/test_litellm/llms/bedrock_mantle/test_bedrock_mantle_responses_transformation.py +++ b/tests/test_litellm/llms/bedrock_mantle/test_bedrock_mantle_responses_transformation.py @@ -8,10 +8,7 @@ gate, the URL construction for both paths, and the shared Bearer auth. """ import copy -import os -import sys -sys.path.insert(0, os.path.abspath("../../../../..")) import pytest from botocore.exceptions import ( diff --git a/tests/test_litellm/llms/bedrock_mantle/test_bedrock_mantle_transformation.py b/tests/test_litellm/llms/bedrock_mantle/test_bedrock_mantle_transformation.py index 07910b0b56f..cd775abf136 100644 --- a/tests/test_litellm/llms/bedrock_mantle/test_bedrock_mantle_transformation.py +++ b/tests/test_litellm/llms/bedrock_mantle/test_bedrock_mantle_transformation.py @@ -6,11 +6,8 @@ API docs: https://docs.aws.amazon.com/bedrock/latest/userguide/bedrock-mantle.ht """ import json -import os -import sys from unittest.mock import patch -sys.path.insert(0, os.path.abspath("../../../../..")) import httpx import pytest diff --git a/tests/test_litellm/llms/black_forest_labs/image_edit/test_bfl_image_edit_transformation.py b/tests/test_litellm/llms/black_forest_labs/image_edit/test_bfl_image_edit_transformation.py index 17decaf8257..ec243b7058d 100644 --- a/tests/test_litellm/llms/black_forest_labs/image_edit/test_bfl_image_edit_transformation.py +++ b/tests/test_litellm/llms/black_forest_labs/image_edit/test_bfl_image_edit_transformation.py @@ -7,8 +7,6 @@ since polling logic was moved to the handler. import base64 import json -import os -import sys import time from io import BytesIO from typing import Dict, List @@ -17,9 +15,6 @@ from unittest.mock import MagicMock, patch import httpx import pytest -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path from litellm.llms.black_forest_labs.image_edit.transformation import ( BlackForestLabsImageEditConfig, diff --git a/tests/test_litellm/llms/black_forest_labs/image_generation/test_bfl_image_generation_transformation.py b/tests/test_litellm/llms/black_forest_labs/image_generation/test_bfl_image_generation_transformation.py index 153df5305a7..d6e2c4a3e06 100644 --- a/tests/test_litellm/llms/black_forest_labs/image_generation/test_bfl_image_generation_transformation.py +++ b/tests/test_litellm/llms/black_forest_labs/image_generation/test_bfl_image_generation_transformation.py @@ -6,16 +6,11 @@ since polling logic was moved to the handler. """ import json -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import httpx import pytest -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path from litellm.llms.black_forest_labs.image_generation.transformation import ( BlackForestLabsImageGenerationConfig, diff --git a/tests/test_litellm/llms/bytez/chat/test_bytez_chat_transformation.py b/tests/test_litellm/llms/bytez/chat/test_bytez_chat_transformation.py index 94b8c51dd52..440304aeac1 100644 --- a/tests/test_litellm/llms/bytez/chat/test_bytez_chat_transformation.py +++ b/tests/test_litellm/llms/bytez/chat/test_bytez_chat_transformation.py @@ -1,10 +1,7 @@ -import os -import sys import pytest import json # Adds the parent directory to the system path -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm.llms.bytez.chat.transformation import BytezChatConfig, API_BASE, version diff --git a/tests/test_litellm/llms/chat/test_converse_handler.py b/tests/test_litellm/llms/chat/test_converse_handler.py index 6f8a2788c38..ca79c8d7025 100644 --- a/tests/test_litellm/llms/chat/test_converse_handler.py +++ b/tests/test_litellm/llms/chat/test_converse_handler.py @@ -1,6 +1,4 @@ import json -import os -import sys from unittest.mock import AsyncMock, MagicMock import httpx @@ -12,9 +10,6 @@ from litellm.llms.bedrock.chat.converse_handler import make_sync_call from litellm.llms.bedrock.common_utils import _get_all_bedrock_regions from litellm.llms.custom_httpx.http_handler import AsyncHTTPHandler, HTTPHandler -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path def test_encode_model_id_with_inference_profile(): diff --git a/tests/test_litellm/llms/chatgpt/responses/test_chatgpt_responses_transformation.py b/tests/test_litellm/llms/chatgpt/responses/test_chatgpt_responses_transformation.py index 90a1c24bada..8e0415d50de 100644 --- a/tests/test_litellm/llms/chatgpt/responses/test_chatgpt_responses_transformation.py +++ b/tests/test_litellm/llms/chatgpt/responses/test_chatgpt_responses_transformation.py @@ -5,14 +5,11 @@ Source: litellm/llms/chatgpt/responses/transformation.py """ import json -import os -import sys from unittest.mock import MagicMock, patch import httpx import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm.llms.openai.common_utils import OpenAIError from litellm.types.router import GenericLiteLLMParams diff --git a/tests/test_litellm/llms/cohere/chat/test_cohere_transformation.py b/tests/test_litellm/llms/cohere/chat/test_cohere_transformation.py index c208f4c5489..61334b6ff63 100644 --- a/tests/test_litellm/llms/cohere/chat/test_cohere_transformation.py +++ b/tests/test_litellm/llms/cohere/chat/test_cohere_transformation.py @@ -1,10 +1,5 @@ -import os -import sys from unittest.mock import MagicMock -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path import litellm from litellm.llms.cohere.chat.transformation import CohereChatConfig diff --git a/tests/test_litellm/llms/cohere/embed/test_v1_transformation.py b/tests/test_litellm/llms/cohere/embed/test_v1_transformation.py index 77b500a7e8c..66129b64a2c 100644 --- a/tests/test_litellm/llms/cohere/embed/test_v1_transformation.py +++ b/tests/test_litellm/llms/cohere/embed/test_v1_transformation.py @@ -1,10 +1,5 @@ -import os -import sys from unittest.mock import MagicMock -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path from litellm.llms.cohere.embed.v1_transformation import CohereEmbeddingConfig from litellm.types.utils import EmbeddingResponse diff --git a/tests/test_litellm/llms/cohere/rerank/test_rerank_guardrail_handler.py b/tests/test_litellm/llms/cohere/rerank/test_rerank_guardrail_handler.py index 46c37e6af6c..cd3ac57c7e8 100644 --- a/tests/test_litellm/llms/cohere/rerank/test_rerank_guardrail_handler.py +++ b/tests/test_litellm/llms/cohere/rerank/test_rerank_guardrail_handler.py @@ -2,12 +2,9 @@ Unit tests for Cohere Rerank Guardrail Translation Handler """ -import os -import sys import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm.integrations.custom_guardrail import CustomGuardrail from litellm.llms import get_guardrail_translation_mapping diff --git a/tests/test_litellm/llms/cometapi/chat/test_cometapi_chat_transformation.py b/tests/test_litellm/llms/cometapi/chat/test_cometapi_chat_transformation.py index 0b3348c1b7f..7a69b676667 100644 --- a/tests/test_litellm/llms/cometapi/chat/test_cometapi_chat_transformation.py +++ b/tests/test_litellm/llms/cometapi/chat/test_cometapi_chat_transformation.py @@ -5,13 +5,9 @@ Tests the CometAPIChatConfig class methods using mocks """ import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path from litellm.llms.cometapi.chat.transformation import ( CometAPIChatCompletionStreamingHandler, @@ -187,7 +183,6 @@ def test_cometapi_integration(): Integration test - requires real API key Run with: pytest -k test_cometapi_integration -s """ - import os from litellm import completion # Try to get API key from multiple environment variables @@ -221,7 +216,6 @@ def test_cometapi_streaming_integration(): Integration test for streaming - requires real API key Run with: pytest -k test_cometapi_streaming_integration -s """ - import os from litellm import completion # Try to get API key from multiple environment variables @@ -285,7 +279,6 @@ def test_cometapi_with_custom_base_url(): """ Test CometAPI with custom base URL """ - import os from litellm import completion api_key = ( diff --git a/tests/test_litellm/llms/custom_httpx/test_aiohttp_handler.py b/tests/test_litellm/llms/custom_httpx/test_aiohttp_handler.py index 789c88d66f8..763647aa463 100644 --- a/tests/test_litellm/llms/custom_httpx/test_aiohttp_handler.py +++ b/tests/test_litellm/llms/custom_httpx/test_aiohttp_handler.py @@ -1,13 +1,8 @@ -import os -import sys from unittest.mock import AsyncMock, Mock, patch import aiohttp import pytest -sys.path.insert( - 0, os.path.abspath("../../../..") -) # Adds the parent directory to the system path from litellm.llms.custom_httpx.aiohttp_handler import BaseLLMAIOHTTPHandler from litellm.llms.custom_httpx.aiohttp_transport import LiteLLMAiohttpTransport diff --git a/tests/test_litellm/llms/custom_httpx/test_aiohttp_transport.py b/tests/test_litellm/llms/custom_httpx/test_aiohttp_transport.py index 2dc7fbfd62a..4c92c52d556 100644 --- a/tests/test_litellm/llms/custom_httpx/test_aiohttp_transport.py +++ b/tests/test_litellm/llms/custom_httpx/test_aiohttp_transport.py @@ -1,7 +1,5 @@ import asyncio import concurrent.futures -import os -import sys import aiohttp import aiohttp.client_exceptions @@ -9,9 +7,6 @@ import aiohttp.http_exceptions import httpx import pytest -sys.path.insert( - 0, os.path.abspath("../../../..") -) # Adds the parent directory to the system path from litellm.llms.custom_httpx.aiohttp_transport import ( AiohttpResponseStream, diff --git a/tests/test_litellm/llms/custom_httpx/test_credential_leak_prevention.py b/tests/test_litellm/llms/custom_httpx/test_credential_leak_prevention.py index bd9db87a765..32c555f205a 100644 --- a/tests/test_litellm/llms/custom_httpx/test_credential_leak_prevention.py +++ b/tests/test_litellm/llms/custom_httpx/test_credential_leak_prevention.py @@ -7,14 +7,11 @@ Covers: - _raise_masked_sync_error and _raise_masked_async_error """ -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import httpx import pytest -sys.path.insert(0, os.path.abspath("../../../..")) from litellm.llms.custom_httpx.http_handler import ( AsyncHTTPHandler, diff --git a/tests/test_litellm/llms/custom_httpx/test_http_handler.py b/tests/test_litellm/llms/custom_httpx/test_http_handler.py index 641fae12bc2..f7f89cd1d8d 100644 --- a/tests/test_litellm/llms/custom_httpx/test_http_handler.py +++ b/tests/test_litellm/llms/custom_httpx/test_http_handler.py @@ -4,7 +4,6 @@ import io import os import pathlib import ssl -import sys import threading import weakref from unittest.mock import MagicMock, patch @@ -14,9 +13,6 @@ import httpx import pytest from aiohttp import ClientSession, TCPConnector -sys.path.insert( - 0, os.path.abspath("../../../..") -) # Adds the parent directory to the system path import litellm from litellm.llms.custom_httpx.aiohttp_transport import LiteLLMAiohttpTransport from litellm.llms.custom_httpx.http_handler import ( diff --git a/tests/test_litellm/llms/custom_httpx/test_llm_http_handler.py b/tests/test_litellm/llms/custom_httpx/test_llm_http_handler.py index 3c972ae9c84..9faa77d6dce 100644 --- a/tests/test_litellm/llms/custom_httpx/test_llm_http_handler.py +++ b/tests/test_litellm/llms/custom_httpx/test_llm_http_handler.py @@ -1,15 +1,12 @@ import asyncio import json import logging -import os -import sys import time from unittest.mock import AsyncMock, Mock, patch import httpx import pytest -sys.path.insert(0, os.path.abspath("../../../..")) # Adds the parent directory to the system path import litellm from litellm._logging import verbose_logger from litellm.integrations.code_interpreter_interception.handler import ( diff --git a/tests/test_litellm/llms/dashscope/test_dashscope_chat_transformation.py b/tests/test_litellm/llms/dashscope/test_dashscope_chat_transformation.py index 8dbc197d4b5..d2a90baf6b2 100644 --- a/tests/test_litellm/llms/dashscope/test_dashscope_chat_transformation.py +++ b/tests/test_litellm/llms/dashscope/test_dashscope_chat_transformation.py @@ -5,12 +5,7 @@ These tests validate the DashScopeConfig class which extends OpenAIGPTConfig. DashScope is an OpenAI-compatible provider with minor customizations. """ -import os -import sys -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path from litellm.types.llms.openai import AllMessageValues import pytest diff --git a/tests/test_litellm/llms/dashscope/test_dashscope_cost_calculator.py b/tests/test_litellm/llms/dashscope/test_dashscope_cost_calculator.py index 510776ddfdf..8dc4620dd1b 100644 --- a/tests/test_litellm/llms/dashscope/test_dashscope_cost_calculator.py +++ b/tests/test_litellm/llms/dashscope/test_dashscope_cost_calculator.py @@ -10,12 +10,10 @@ Tests the cost calculation for Dashscope models including: import math import os -import sys import pytest # Add the project root to Python path -sys.path.insert(0, os.path.abspath("../../../..")) import litellm from litellm.llms.dashscope.cost_calculator import ( diff --git a/tests/test_litellm/llms/dashscope/test_dashscope_embedding_transformation.py b/tests/test_litellm/llms/dashscope/test_dashscope_embedding_transformation.py index 5e4d0177e8d..1b6eea0e4c8 100644 --- a/tests/test_litellm/llms/dashscope/test_dashscope_embedding_transformation.py +++ b/tests/test_litellm/llms/dashscope/test_dashscope_embedding_transformation.py @@ -3,14 +3,11 @@ Unit tests for DashScope embedding transformation. """ import json -import os -import sys from unittest.mock import MagicMock import httpx import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm.llms.dashscope.common_utils import DashScopeError from litellm.llms.dashscope.embed.transformation import ( diff --git a/tests/test_litellm/llms/dashscope/test_dashscope_rerank_transformation.py b/tests/test_litellm/llms/dashscope/test_dashscope_rerank_transformation.py index 0e8d58b6530..936de812bc6 100644 --- a/tests/test_litellm/llms/dashscope/test_dashscope_rerank_transformation.py +++ b/tests/test_litellm/llms/dashscope/test_dashscope_rerank_transformation.py @@ -3,14 +3,11 @@ Unit tests for DashScope rerank transformation. """ import json -import os -import sys from unittest.mock import MagicMock import httpx import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm.llms.dashscope.common_utils import DashScopeError from litellm.llms.dashscope.rerank.transformation import ( diff --git a/tests/test_litellm/llms/databricks/chat/test_databricks_chat_transformation.py b/tests/test_litellm/llms/databricks/chat/test_databricks_chat_transformation.py index 165046a2298..41fb2589655 100644 --- a/tests/test_litellm/llms/databricks/chat/test_databricks_chat_transformation.py +++ b/tests/test_litellm/llms/databricks/chat/test_databricks_chat_transformation.py @@ -1,11 +1,8 @@ import json -import os -import sys import pytest from fastapi.testclient import TestClient -sys.path.insert(0, os.path.abspath("../../../../..")) # Adds the parent directory to the system path from unittest.mock import MagicMock, patch from litellm.llms.databricks.chat.transformation import ( diff --git a/tests/test_litellm/llms/databricks/responses/test_databricks_responses_transformation.py b/tests/test_litellm/llms/databricks/responses/test_databricks_responses_transformation.py index b4a368be81f..4420506bf91 100644 --- a/tests/test_litellm/llms/databricks/responses/test_databricks_responses_transformation.py +++ b/tests/test_litellm/llms/databricks/responses/test_databricks_responses_transformation.py @@ -1,11 +1,6 @@ -import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path from unittest.mock import patch import litellm diff --git a/tests/test_litellm/llms/databricks/test_databricks_common_utils.py b/tests/test_litellm/llms/databricks/test_databricks_common_utils.py index 7f7ec8e9000..ee50ffdabdc 100644 --- a/tests/test_litellm/llms/databricks/test_databricks_common_utils.py +++ b/tests/test_litellm/llms/databricks/test_databricks_common_utils.py @@ -1,13 +1,8 @@ import json -import os -import sys import pytest from fastapi.testclient import TestClient -sys.path.insert( - 0, os.path.abspath("../../../..") -) # Adds the parent directory to the system path from unittest.mock import MagicMock, patch from litellm.llms.databricks.common_utils import DatabricksBase diff --git a/tests/test_litellm/llms/databricks/test_databricks_partner_integration.py b/tests/test_litellm/llms/databricks/test_databricks_partner_integration.py index 139990021b4..86fdd89acf6 100644 --- a/tests/test_litellm/llms/databricks/test_databricks_partner_integration.py +++ b/tests/test_litellm/llms/databricks/test_databricks_partner_integration.py @@ -23,15 +23,11 @@ These tests align with Databricks Partner Architecture best practices: """ import json -import os import sys import pytest from unittest.mock import MagicMock, patch, Mock -sys.path.insert( - 0, os.path.abspath("../../../..") -) # Adds the parent directory to the system path from litellm.llms.databricks.common_utils import DatabricksBase, DatabricksException diff --git a/tests/test_litellm/llms/deepgram/audio_transcription/test_deepgram_audio_transcription_transformation.py b/tests/test_litellm/llms/deepgram/audio_transcription/test_deepgram_audio_transcription_transformation.py index d59ab975ef2..7c1f5256deb 100644 --- a/tests/test_litellm/llms/deepgram/audio_transcription/test_deepgram_audio_transcription_transformation.py +++ b/tests/test_litellm/llms/deepgram/audio_transcription/test_deepgram_audio_transcription_transformation.py @@ -1,14 +1,10 @@ import io import os import pathlib -import sys from unittest.mock import MagicMock import pytest -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path import litellm from litellm.llms.base_llm.audio_transcription.transformation import ( diff --git a/tests/test_litellm/llms/deepgram/test_deepgram_mock_transcription.py b/tests/test_litellm/llms/deepgram/test_deepgram_mock_transcription.py index 1f209004be8..e12b3982b13 100644 --- a/tests/test_litellm/llms/deepgram/test_deepgram_mock_transcription.py +++ b/tests/test_litellm/llms/deepgram/test_deepgram_mock_transcription.py @@ -1,15 +1,10 @@ import io import json -import os -import sys from typing import Any from unittest.mock import MagicMock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../../../..") -) # Adds the parent directory to the system path import litellm from litellm.types.utils import TranscriptionResponse diff --git a/tests/test_litellm/llms/deepinfra/test_deepinfra_chat_transformation.py b/tests/test_litellm/llms/deepinfra/test_deepinfra_chat_transformation.py index ff309bc44ed..0865a14fbd9 100644 --- a/tests/test_litellm/llms/deepinfra/test_deepinfra_chat_transformation.py +++ b/tests/test_litellm/llms/deepinfra/test_deepinfra_chat_transformation.py @@ -1,13 +1,11 @@ import asyncio import json import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import pytest # Add litellm to path -sys.path.insert(0, os.path.abspath("../../../..")) import litellm diff --git a/tests/test_litellm/llms/deepinfra/test_deepinfra_rerank.py b/tests/test_litellm/llms/deepinfra/test_deepinfra_rerank.py index a1e47f815e7..02161b38fb6 100644 --- a/tests/test_litellm/llms/deepinfra/test_deepinfra_rerank.py +++ b/tests/test_litellm/llms/deepinfra/test_deepinfra_rerank.py @@ -4,14 +4,11 @@ Tests for DeepInfra rerank functionality following repository patterns. import asyncio import json -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import pytest # Add litellm to path -sys.path.insert(0, os.path.abspath("../../../..")) import litellm diff --git a/tests/test_litellm/llms/docker_model_runner/test_docker_model_runner_chat_transformation.py b/tests/test_litellm/llms/docker_model_runner/test_docker_model_runner_chat_transformation.py index 0b4a2a5de8c..8ab24c16f14 100644 --- a/tests/test_litellm/llms/docker_model_runner/test_docker_model_runner_chat_transformation.py +++ b/tests/test_litellm/llms/docker_model_runner/test_docker_model_runner_chat_transformation.py @@ -5,10 +5,7 @@ This test validates that the DockerModelRunnerChatConfig correctly transforms requests to the proper URL, headers, and body format. """ -import os -import sys -sys.path.insert(0, os.path.abspath("../../../../..")) import json from typing import cast diff --git a/tests/test_litellm/llms/fal_ai/image_generation/test_fal_ai_nano_banana_transformation.py b/tests/test_litellm/llms/fal_ai/image_generation/test_fal_ai_nano_banana_transformation.py index c0f74eff51b..f26a6aeafda 100644 --- a/tests/test_litellm/llms/fal_ai/image_generation/test_fal_ai_nano_banana_transformation.py +++ b/tests/test_litellm/llms/fal_ai/image_generation/test_fal_ai_nano_banana_transformation.py @@ -1,9 +1,7 @@ import os -import sys import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) os.environ["LITELLM_LOCAL_MODEL_COST_MAP"] = "True" diff --git a/tests/test_litellm/llms/featherless_ai/chat/test_featherless_chat_transformation.py b/tests/test_litellm/llms/featherless_ai/chat/test_featherless_chat_transformation.py index bf40abd7016..560eaf4f06b 100644 --- a/tests/test_litellm/llms/featherless_ai/chat/test_featherless_chat_transformation.py +++ b/tests/test_litellm/llms/featherless_ai/chat/test_featherless_chat_transformation.py @@ -5,14 +5,9 @@ These tests validate the FeatherlessAIConfig class which extends OpenAIGPTConfig Featherless AI is an OpenAI-compatible provider with a few customizations. """ -import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path from litellm.llms.featherless_ai.chat.transformation import FeatherlessAIConfig diff --git a/tests/test_litellm/llms/fireworks_ai/chat/test_fireworks_ai_chat_transformation.py b/tests/test_litellm/llms/fireworks_ai/chat/test_fireworks_ai_chat_transformation.py index b46ba081f6f..e728fc4bc40 100644 --- a/tests/test_litellm/llms/fireworks_ai/chat/test_fireworks_ai_chat_transformation.py +++ b/tests/test_litellm/llms/fireworks_ai/chat/test_fireworks_ai_chat_transformation.py @@ -1,15 +1,10 @@ import json -import os -import sys from unittest.mock import MagicMock, patch import pytest import litellm -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path from litellm import get_model_info, supports_reasoning, supports_vision from litellm.llms.fireworks_ai.chat.transformation import FireworksAIConfig diff --git a/tests/test_litellm/llms/fireworks_ai/completion/test_fireworks_ai_completion_transformation.py b/tests/test_litellm/llms/fireworks_ai/completion/test_fireworks_ai_completion_transformation.py index 996f1fd975b..e1b88a9c78e 100644 --- a/tests/test_litellm/llms/fireworks_ai/completion/test_fireworks_ai_completion_transformation.py +++ b/tests/test_litellm/llms/fireworks_ai/completion/test_fireworks_ai_completion_transformation.py @@ -1,7 +1,4 @@ -import os -import sys -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm.llms.fireworks_ai.completion.transformation import ( FireworksAITextCompletionConfig, diff --git a/tests/test_litellm/llms/fireworks_ai/completion/test_fireworks_ai_text_completion_transformation.py b/tests/test_litellm/llms/fireworks_ai/completion/test_fireworks_ai_text_completion_transformation.py index 4f76a39684a..e5a77aa8d41 100644 --- a/tests/test_litellm/llms/fireworks_ai/completion/test_fireworks_ai_text_completion_transformation.py +++ b/tests/test_litellm/llms/fireworks_ai/completion/test_fireworks_ai_text_completion_transformation.py @@ -1,13 +1,8 @@ -import os -import sys import pytest import litellm -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path from litellm.llms.fireworks_ai.completion.transformation import ( FireworksAITextCompletionConfig, diff --git a/tests/test_litellm/llms/fireworks_ai/test_fireworks_ai_common_utils.py b/tests/test_litellm/llms/fireworks_ai/test_fireworks_ai_common_utils.py index b52c910d5a6..16226a3ce74 100644 --- a/tests/test_litellm/llms/fireworks_ai/test_fireworks_ai_common_utils.py +++ b/tests/test_litellm/llms/fireworks_ai/test_fireworks_ai_common_utils.py @@ -1,9 +1,6 @@ -import os -import sys import pytest -sys.path.insert(0, os.path.abspath("../../../..")) from litellm.llms.fireworks_ai.common_utils import resolve_fireworks_resource_name diff --git a/tests/test_litellm/llms/fireworks_ai/test_fireworks_ai_cost_calculator.py b/tests/test_litellm/llms/fireworks_ai/test_fireworks_ai_cost_calculator.py index 3297750fa6e..f1664dabf48 100644 --- a/tests/test_litellm/llms/fireworks_ai/test_fireworks_ai_cost_calculator.py +++ b/tests/test_litellm/llms/fireworks_ai/test_fireworks_ai_cost_calculator.py @@ -1,9 +1,6 @@ -import os -import sys import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) import litellm from litellm.llms.fireworks_ai.cost_calculator import cost_per_token diff --git a/tests/test_litellm/llms/gdc/chat/test_gdc_chat_transformation.py b/tests/test_litellm/llms/gdc/chat/test_gdc_chat_transformation.py index d106cf7ea21..3153c12aa94 100644 --- a/tests/test_litellm/llms/gdc/chat/test_gdc_chat_transformation.py +++ b/tests/test_litellm/llms/gdc/chat/test_gdc_chat_transformation.py @@ -1,11 +1,8 @@ -import os -import sys from unittest.mock import MagicMock, patch import pytest # Adds the parent directory to the system path -sys.path.insert(0, os.path.abspath("../../../../..")) import litellm from litellm.llms.gdc.chat.transformation import GDCGeminiConfig diff --git a/tests/test_litellm/llms/gemini/realtime/test_gemini_realtime_transformation.py b/tests/test_litellm/llms/gemini/realtime/test_gemini_realtime_transformation.py index 02004d5c8a8..deb148a07c0 100644 --- a/tests/test_litellm/llms/gemini/realtime/test_gemini_realtime_transformation.py +++ b/tests/test_litellm/llms/gemini/realtime/test_gemini_realtime_transformation.py @@ -1,12 +1,9 @@ import json -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import httpx import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) # Adds the parent directory to the system path import litellm from litellm.llms.gemini.realtime.transformation import GeminiRealtimeConfig diff --git a/tests/test_litellm/llms/gemini/test_gemini_tts.py b/tests/test_litellm/llms/gemini/test_gemini_tts.py index 98f3ac0f4e5..4893825373a 100644 --- a/tests/test_litellm/llms/gemini/test_gemini_tts.py +++ b/tests/test_litellm/llms/gemini/test_gemini_tts.py @@ -2,14 +2,9 @@ Test Gemini TTS (Text-to-Speech) functionality """ -import os -import sys import pytest from unittest.mock import patch, MagicMock -sys.path.insert( - 0, os.path.abspath("../../../..") -) # Adds the parent directory to the system path import litellm from litellm.llms.gemini.chat.transformation import GoogleAIStudioGeminiConfig diff --git a/tests/test_litellm/llms/github_copilot/embedding/test_github_copilot_embedding_transformation.py b/tests/test_litellm/llms/github_copilot/embedding/test_github_copilot_embedding_transformation.py index 90cf5a17398..f43e2e4d1cb 100644 --- a/tests/test_litellm/llms/github_copilot/embedding/test_github_copilot_embedding_transformation.py +++ b/tests/test_litellm/llms/github_copilot/embedding/test_github_copilot_embedding_transformation.py @@ -1,10 +1,7 @@ -import os -import sys from unittest.mock import MagicMock, patch import pytest -sys.path.insert(0, os.path.abspath("../../../..")) from litellm.exceptions import AuthenticationError from litellm.llms.github_copilot.embedding.transformation import ( diff --git a/tests/test_litellm/llms/github_copilot/messages/test_github_copilot_messages_transformation.py b/tests/test_litellm/llms/github_copilot/messages/test_github_copilot_messages_transformation.py index 8ed84b3ed8d..8039e744f46 100644 --- a/tests/test_litellm/llms/github_copilot/messages/test_github_copilot_messages_transformation.py +++ b/tests/test_litellm/llms/github_copilot/messages/test_github_copilot_messages_transformation.py @@ -1,10 +1,7 @@ -import os -import sys from unittest.mock import MagicMock import pytest -sys.path.insert(0, os.path.abspath("../..")) from litellm.exceptions import AuthenticationError from litellm.llms.github_copilot.common_utils import GetAPIKeyError diff --git a/tests/test_litellm/llms/github_copilot/responses/test_github_copilot_responses_transformation.py b/tests/test_litellm/llms/github_copilot/responses/test_github_copilot_responses_transformation.py index 174efceb499..c761d084da8 100644 --- a/tests/test_litellm/llms/github_copilot/responses/test_github_copilot_responses_transformation.py +++ b/tests/test_litellm/llms/github_copilot/responses/test_github_copilot_responses_transformation.py @@ -7,11 +7,8 @@ transformations for the Responses API. Source: litellm/llms/github_copilot/responses/transformation.py """ -import sys -import os from unittest.mock import patch, MagicMock -sys.path.insert(0, os.path.abspath("../../../../..")) import pytest import litellm diff --git a/tests/test_litellm/llms/github_copilot/test_github_copilot_transformation.py b/tests/test_litellm/llms/github_copilot/test_github_copilot_transformation.py index 51cffd5e51a..f1f1978b06f 100644 --- a/tests/test_litellm/llms/github_copilot/test_github_copilot_transformation.py +++ b/tests/test_litellm/llms/github_copilot/test_github_copilot_transformation.py @@ -1,14 +1,11 @@ import asyncio import json -import os -import sys from datetime import datetime, timedelta from typing import AsyncGenerator from unittest.mock import AsyncMock, MagicMock, mock_open, patch import pytest -sys.path.insert(0, os.path.abspath("../..")) import httpx from respx import MockRouter diff --git a/tests/test_litellm/llms/gradient_ai/chat/test_gradient_ai_chat_transformation.py b/tests/test_litellm/llms/gradient_ai/chat/test_gradient_ai_chat_transformation.py index 6eabf2472ea..6586f970b80 100644 --- a/tests/test_litellm/llms/gradient_ai/chat/test_gradient_ai_chat_transformation.py +++ b/tests/test_litellm/llms/gradient_ai/chat/test_gradient_ai_chat_transformation.py @@ -1,10 +1,5 @@ -import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path from litellm.llms.gradient_ai.chat.transformation import ( GradientAIConfig, diff --git a/tests/test_litellm/llms/hosted_vllm/chat/test_hosted_vllm_chat_transformation.py b/tests/test_litellm/llms/hosted_vllm/chat/test_hosted_vllm_chat_transformation.py index 3ddb67b9f8d..e316cd14dd4 100644 --- a/tests/test_litellm/llms/hosted_vllm/chat/test_hosted_vllm_chat_transformation.py +++ b/tests/test_litellm/llms/hosted_vllm/chat/test_hosted_vllm_chat_transformation.py @@ -1,11 +1,6 @@ import json -import os -import sys from unittest.mock import MagicMock, patch -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path from litellm.constants import ( DEFAULT_REASONING_EFFORT_HIGH_THINKING_BUDGET, diff --git a/tests/test_litellm/llms/hosted_vllm/chat/test_hosted_vllm_ssl_verify.py b/tests/test_litellm/llms/hosted_vllm/chat/test_hosted_vllm_ssl_verify.py index 8f98b3ca8f1..2364468efe1 100644 --- a/tests/test_litellm/llms/hosted_vllm/chat/test_hosted_vllm_ssl_verify.py +++ b/tests/test_litellm/llms/hosted_vllm/chat/test_hosted_vllm_ssl_verify.py @@ -8,15 +8,10 @@ Issue: ssl_verify parameter was being ignored because hosted_vllm fell through to the OpenAI catch-all path in main.py, which doesn't pass ssl_verify to the HTTP client. """ -import os -import sys from unittest.mock import MagicMock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path import litellm diff --git a/tests/test_litellm/llms/hosted_vllm/embedding/test_hosted_vllm_embedding_ssl_verify.py b/tests/test_litellm/llms/hosted_vllm/embedding/test_hosted_vllm_embedding_ssl_verify.py index bb911814c23..de94da49384 100644 --- a/tests/test_litellm/llms/hosted_vllm/embedding/test_hosted_vllm_embedding_ssl_verify.py +++ b/tests/test_litellm/llms/hosted_vllm/embedding/test_hosted_vllm_embedding_ssl_verify.py @@ -8,15 +8,10 @@ Issue: ssl_verify parameter was being ignored because hosted_vllm fell through to the openai_like catch-all path in main.py, which doesn't pass ssl_verify to the HTTP client. """ -import os -import sys from unittest.mock import MagicMock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path import litellm diff --git a/tests/test_litellm/llms/hosted_vllm/embedding/test_hosted_vllm_embedding_transformation.py b/tests/test_litellm/llms/hosted_vllm/embedding/test_hosted_vllm_embedding_transformation.py index 93c518599d6..34be3e12abd 100644 --- a/tests/test_litellm/llms/hosted_vllm/embedding/test_hosted_vllm_embedding_transformation.py +++ b/tests/test_litellm/llms/hosted_vllm/embedding/test_hosted_vllm_embedding_transformation.py @@ -6,15 +6,10 @@ especially ensuring that encoding_format is not included when not provided. """ import json -import os -import sys from unittest.mock import Mock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path import litellm from litellm.llms.hosted_vllm.embedding.transformation import ( diff --git a/tests/test_litellm/llms/hosted_vllm/responses/test_hosted_vllm_responses.py b/tests/test_litellm/llms/hosted_vllm/responses/test_hosted_vllm_responses.py index eb578b86af0..e81bf0c4f1f 100644 --- a/tests/test_litellm/llms/hosted_vllm/responses/test_hosted_vllm_responses.py +++ b/tests/test_litellm/llms/hosted_vllm/responses/test_hosted_vllm_responses.py @@ -8,15 +8,10 @@ hosted_vllm (and any OpenAI-compatible provider using add_provider_specific_para """ import json -import os -import sys from unittest.mock import MagicMock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path import litellm from litellm.llms.hosted_vllm.responses.transformation import ( diff --git a/tests/test_litellm/llms/huggingface/embedding/test_huggingface_embedding_handler.py b/tests/test_litellm/llms/huggingface/embedding/test_huggingface_embedding_handler.py index c907e3249d1..f1226311b5e 100644 --- a/tests/test_litellm/llms/huggingface/embedding/test_huggingface_embedding_handler.py +++ b/tests/test_litellm/llms/huggingface/embedding/test_huggingface_embedding_handler.py @@ -1,11 +1,6 @@ import json -import os -import sys from unittest.mock import patch, MagicMock, AsyncMock -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path import litellm import pytest diff --git a/tests/test_litellm/llms/jina_ai/embedding/test_jina_embedding_transformation.py b/tests/test_litellm/llms/jina_ai/embedding/test_jina_embedding_transformation.py index 9e761817ef5..38355f32da1 100644 --- a/tests/test_litellm/llms/jina_ai/embedding/test_jina_embedding_transformation.py +++ b/tests/test_litellm/llms/jina_ai/embedding/test_jina_embedding_transformation.py @@ -1,10 +1,7 @@ -import os -import sys from unittest.mock import MagicMock import pytest -sys.path.insert(0, os.path.abspath("../../../../../..")) # Adds the parent directory to the system path from litellm.llms.jina_ai.embedding.transformation import JinaAIEmbeddingConfig diff --git a/tests/test_litellm/llms/lemonade/test_lemonade.py b/tests/test_litellm/llms/lemonade/test_lemonade.py index cb70e7794a8..fa0d9d279a7 100644 --- a/tests/test_litellm/llms/lemonade/test_lemonade.py +++ b/tests/test_litellm/llms/lemonade/test_lemonade.py @@ -1,9 +1,4 @@ -import os -import sys -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path from unittest.mock import MagicMock, patch import litellm diff --git a/tests/test_litellm/llms/manus/responses/test_manus_responses_transformation.py b/tests/test_litellm/llms/manus/responses/test_manus_responses_transformation.py index 43ce030323b..d6f76a16a9a 100644 --- a/tests/test_litellm/llms/manus/responses/test_manus_responses_transformation.py +++ b/tests/test_litellm/llms/manus/responses/test_manus_responses_transformation.py @@ -7,10 +7,7 @@ transformations for the Responses API. Source: litellm/llms/manus/responses/transformation.py """ -import os -import sys -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm.llms.manus.responses.transformation import ManusResponsesAPIConfig from litellm.types.llms.openai import ResponsesAPIOptionalRequestParams diff --git a/tests/test_litellm/llms/meta_llama/test_meta_llama_chat_transformation.py b/tests/test_litellm/llms/meta_llama/test_meta_llama_chat_transformation.py index 7b974aba35c..15995d873c2 100644 --- a/tests/test_litellm/llms/meta_llama/test_meta_llama_chat_transformation.py +++ b/tests/test_litellm/llms/meta_llama/test_meta_llama_chat_transformation.py @@ -1,11 +1,6 @@ -import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm.llms.meta_llama.chat.transformation import LlamaAPIConfig diff --git a/tests/test_litellm/llms/minimax/chat/test_transformation.py b/tests/test_litellm/llms/minimax/chat/test_transformation.py index 286498830c5..9d51b556500 100644 --- a/tests/test_litellm/llms/minimax/chat/test_transformation.py +++ b/tests/test_litellm/llms/minimax/chat/test_transformation.py @@ -3,14 +3,10 @@ Test MiniMax OpenAI-compatible API support """ import os -import sys from unittest.mock import MagicMock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../") -) # Adds the parent directory to the system path import litellm from litellm import completion diff --git a/tests/test_litellm/llms/minimax/messages/test_transformation.py b/tests/test_litellm/llms/minimax/messages/test_transformation.py index 6e4b0428bb9..01d32221fe5 100644 --- a/tests/test_litellm/llms/minimax/messages/test_transformation.py +++ b/tests/test_litellm/llms/minimax/messages/test_transformation.py @@ -3,14 +3,10 @@ Test MiniMax Anthropic-compatible API support """ import os -import sys from unittest.mock import MagicMock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../") -) # Adds the parent directory to the system path import litellm from litellm import completion diff --git a/tests/test_litellm/llms/mistral/test_mistral_chat_transformation.py b/tests/test_litellm/llms/mistral/test_mistral_chat_transformation.py index 55c5d05cdc0..15694d9f218 100644 --- a/tests/test_litellm/llms/mistral/test_mistral_chat_transformation.py +++ b/tests/test_litellm/llms/mistral/test_mistral_chat_transformation.py @@ -1,5 +1,3 @@ -import os -import sys from typing import List, cast from unittest.mock import MagicMock, patch @@ -8,9 +6,6 @@ import pytest from litellm.litellm_core_utils.prompt_templates.common_utils import TOOL_RESULT_IMAGE_BOUNDARY from litellm.types.llms.openai import AllMessageValues -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path from litellm.llms.mistral.chat.transformation import ( MistralChatResponseIterator, diff --git a/tests/test_litellm/llms/modelscope/chat/test_modelscope_chat_transformation.py b/tests/test_litellm/llms/modelscope/chat/test_modelscope_chat_transformation.py index 2767deae176..6fe39798f4f 100644 --- a/tests/test_litellm/llms/modelscope/chat/test_modelscope_chat_transformation.py +++ b/tests/test_litellm/llms/modelscope/chat/test_modelscope_chat_transformation.py @@ -7,11 +7,7 @@ ModelScope is an OpenAI-compatible provider with minor customizations. import json import os -import sys -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path from unittest.mock import patch diff --git a/tests/test_litellm/llms/modelscope/image_generation/test_modelscope_image_gen_transformation.py b/tests/test_litellm/llms/modelscope/image_generation/test_modelscope_image_gen_transformation.py index fbcec3d4d2e..2ffe7c3e686 100644 --- a/tests/test_litellm/llms/modelscope/image_generation/test_modelscope_image_gen_transformation.py +++ b/tests/test_litellm/llms/modelscope/image_generation/test_modelscope_image_gen_transformation.py @@ -5,15 +5,10 @@ These tests validate the ModelScopeImageGenerationConfig class which handles transformation between OpenAI-compatible format and ModelScope API format. """ -import os -import sys from unittest.mock import MagicMock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path from litellm.llms.modelscope.image_generation.transformation import ( ModelScopeImageGenerationConfig, diff --git a/tests/test_litellm/llms/moonshot/test_moonshot_chat_transformation.py b/tests/test_litellm/llms/moonshot/test_moonshot_chat_transformation.py index 417dd4a767c..50f476eaaaa 100644 --- a/tests/test_litellm/llms/moonshot/test_moonshot_chat_transformation.py +++ b/tests/test_litellm/llms/moonshot/test_moonshot_chat_transformation.py @@ -5,11 +5,8 @@ These tests validate the MoonshotChatConfig class which extends OpenAIGPTConfig. Moonshot AI is an OpenAI-compatible provider with minor customizations. """ -import os -import sys from unittest.mock import patch -sys.path.insert(0, os.path.abspath("../../../../..")) # Adds the parent directory to the system path import pytest diff --git a/tests/test_litellm/llms/nebius/test_nebius_chat_transformation.py b/tests/test_litellm/llms/nebius/test_nebius_chat_transformation.py index cb15dd3fa3e..6d77e81b767 100644 --- a/tests/test_litellm/llms/nebius/test_nebius_chat_transformation.py +++ b/tests/test_litellm/llms/nebius/test_nebius_chat_transformation.py @@ -5,12 +5,7 @@ These tests validate the NebiusConfig class which extends OpenAIGPTConfig. Nebius AI Studio is an OpenAI-compatible provider with minor customizations. """ -import os -import sys -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path import pytest diff --git a/tests/test_litellm/llms/novita/chat/test_novita_chat_transformation.py b/tests/test_litellm/llms/novita/chat/test_novita_chat_transformation.py index ade5e4176e8..3f2a3f77c41 100644 --- a/tests/test_litellm/llms/novita/chat/test_novita_chat_transformation.py +++ b/tests/test_litellm/llms/novita/chat/test_novita_chat_transformation.py @@ -5,16 +5,11 @@ These tests validate the NovitaConfig class which extends OpenAIGPTConfig. Novita AI is an OpenAI-compatible provider with a few customizations. """ -import os -import sys from typing import Dict, List, Optional from unittest.mock import patch import pytest -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path from litellm.llms.novita.chat.transformation import NovitaConfig diff --git a/tests/test_litellm/llms/nscale/chat/test_nscale_chat_transformation.py b/tests/test_litellm/llms/nscale/chat/test_nscale_chat_transformation.py index 4fcd79ae2a1..415ce9ce9c9 100644 --- a/tests/test_litellm/llms/nscale/chat/test_nscale_chat_transformation.py +++ b/tests/test_litellm/llms/nscale/chat/test_nscale_chat_transformation.py @@ -1,10 +1,6 @@ import os -import sys from unittest.mock import patch -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path from litellm.llms.nscale.chat.transformation import NscaleConfig diff --git a/tests/test_litellm/llms/nvidia_riva/audio_transcription/test_audio_utils.py b/tests/test_litellm/llms/nvidia_riva/audio_transcription/test_audio_utils.py index 0e355b91ca8..63a53c2c97b 100644 --- a/tests/test_litellm/llms/nvidia_riva/audio_transcription/test_audio_utils.py +++ b/tests/test_litellm/llms/nvidia_riva/audio_transcription/test_audio_utils.py @@ -15,7 +15,6 @@ import numpy as np import pytest import soundfile as sf -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm.llms.nvidia_riva.audio_transcription.audio_utils import ( resample_to_riva_pcm, diff --git a/tests/test_litellm/llms/nvidia_riva/audio_transcription/test_handler.py b/tests/test_litellm/llms/nvidia_riva/audio_transcription/test_handler.py index 341a0e77ce0..7ecc0b47d9f 100644 --- a/tests/test_litellm/llms/nvidia_riva/audio_transcription/test_handler.py +++ b/tests/test_litellm/llms/nvidia_riva/audio_transcription/test_handler.py @@ -9,8 +9,6 @@ is aggregated. import asyncio import io -import os -import sys from types import SimpleNamespace from unittest.mock import MagicMock @@ -18,7 +16,6 @@ import numpy as np import pytest import soundfile as sf -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm.llms.nvidia_riva.audio_transcription import handler as handler_mod from litellm.llms.nvidia_riva.audio_transcription.handler import ( diff --git a/tests/test_litellm/llms/nvidia_riva/audio_transcription/test_transformation.py b/tests/test_litellm/llms/nvidia_riva/audio_transcription/test_transformation.py index c4cca8490bf..38489328e30 100644 --- a/tests/test_litellm/llms/nvidia_riva/audio_transcription/test_transformation.py +++ b/tests/test_litellm/llms/nvidia_riva/audio_transcription/test_transformation.py @@ -5,12 +5,9 @@ These tests do not require ``nvidia-riva-client`` or any audio libs to be installed; the transformation layer is intentionally pure-Python on dicts. """ -import os -import sys import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm.llms.base_llm.audio_transcription.transformation import ( AudioTranscriptionRequestData, diff --git a/tests/test_litellm/llms/oci/chat/test_oci_chat_transformation.py b/tests/test_litellm/llms/oci/chat/test_oci_chat_transformation.py index 5aa96a66d2d..86c534c73c2 100644 --- a/tests/test_litellm/llms/oci/chat/test_oci_chat_transformation.py +++ b/tests/test_litellm/llms/oci/chat/test_oci_chat_transformation.py @@ -1,6 +1,4 @@ import datetime -import os -import sys import httpx import pytest import json @@ -8,7 +6,6 @@ import json import litellm # Adds the parent directory to the system path -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm import ModelResponse from litellm.constants import DEFAULT_OCI_CHAT_MAX_TOKENS diff --git a/tests/test_litellm/llms/oci/chat/test_oci_streaming_tool_calls.py b/tests/test_litellm/llms/oci/chat/test_oci_streaming_tool_calls.py index acad5da93e2..002def9196d 100644 --- a/tests/test_litellm/llms/oci/chat/test_oci_streaming_tool_calls.py +++ b/tests/test_litellm/llms/oci/chat/test_oci_streaming_tool_calls.py @@ -9,10 +9,7 @@ Issue: OCI API returns tool calls with incomplete structures during streaming Error: ValidationError: 1 validation error for OCIStreamChunk message.toolCalls.0.arguments Field required """ -import os -import sys -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm.llms.oci.chat.generic import handle_generic_stream_chunk from litellm.types.utils import ModelResponseStream diff --git a/tests/test_litellm/llms/oci/embed/test_oci_embed_transformation.py b/tests/test_litellm/llms/oci/embed/test_oci_embed_transformation.py index 30f49bea344..363c0b46809 100644 --- a/tests/test_litellm/llms/oci/embed/test_oci_embed_transformation.py +++ b/tests/test_litellm/llms/oci/embed/test_oci_embed_transformation.py @@ -5,15 +5,12 @@ These tests exercise the transformation layer only — no real OCI calls are mad """ import json -import os -import sys from typing import Any from unittest.mock import MagicMock import httpx import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm.llms.oci.common_utils import OCIError from litellm.llms.oci.embed.transformation import OCI_EMBED_BATCH_LIMIT, OCIEmbedConfig diff --git a/tests/test_litellm/llms/oci/embed/test_oci_embedding.py b/tests/test_litellm/llms/oci/embed/test_oci_embedding.py index 61c13ad62a1..46a91520ab0 100644 --- a/tests/test_litellm/llms/oci/embed/test_oci_embedding.py +++ b/tests/test_litellm/llms/oci/embed/test_oci_embedding.py @@ -1,12 +1,10 @@ import json import os -import sys from unittest.mock import MagicMock, patch import httpx import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm.llms.oci.embed.transformation import OCIEmbeddingConfig from litellm.types.utils import EmbeddingResponse diff --git a/tests/test_litellm/llms/ocr/guardrail_translation/test_ocr_guardrail_handler.py b/tests/test_litellm/llms/ocr/guardrail_translation/test_ocr_guardrail_handler.py index f6151497e1c..525788c158a 100644 --- a/tests/test_litellm/llms/ocr/guardrail_translation/test_ocr_guardrail_handler.py +++ b/tests/test_litellm/llms/ocr/guardrail_translation/test_ocr_guardrail_handler.py @@ -2,13 +2,10 @@ Unit tests for OCR Guardrail Translation Handler """ -import os import re -import sys import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm.integrations.custom_guardrail import CustomGuardrail from litellm.llms import get_guardrail_translation_mapping diff --git a/tests/test_litellm/llms/ollama/test_ollama_completion_transformation.py b/tests/test_litellm/llms/ollama/test_ollama_completion_transformation.py index dd59cdcac1c..acd69b94d02 100644 --- a/tests/test_litellm/llms/ollama/test_ollama_completion_transformation.py +++ b/tests/test_litellm/llms/ollama/test_ollama_completion_transformation.py @@ -1,14 +1,9 @@ import json -import os -import sys from litellm._uuid import uuid from unittest.mock import MagicMock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path from litellm.llms.ollama.completion.transformation import ( OllamaConfig, diff --git a/tests/test_litellm/llms/ollama/test_ollama_model_info.py b/tests/test_litellm/llms/ollama/test_ollama_model_info.py index 8d46151ecce..053d4da035f 100644 --- a/tests/test_litellm/llms/ollama/test_ollama_model_info.py +++ b/tests/test_litellm/llms/ollama/test_ollama_model_info.py @@ -3,15 +3,11 @@ import sys import pytest -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path """ Unit tests for OllamaModelInfo.get_models functionality. """ # Ensure a dummy httpx module is available for import in tests -import sys import types # Provide a dummy httpx module for import in get_models diff --git a/tests/test_litellm/llms/oobabooga/chat/test_oobabooga.py b/tests/test_litellm/llms/oobabooga/chat/test_oobabooga.py index 91ebb2bd9d4..395a4fb5715 100644 --- a/tests/test_litellm/llms/oobabooga/chat/test_oobabooga.py +++ b/tests/test_litellm/llms/oobabooga/chat/test_oobabooga.py @@ -1,8 +1,5 @@ -import os -import sys from unittest.mock import MagicMock, patch -sys.path.insert(0, os.path.abspath("../../../../..")) import litellm diff --git a/tests/test_litellm/llms/openai/chat/guardrail_translation/test_openai_guardrail_handler.py b/tests/test_litellm/llms/openai/chat/guardrail_translation/test_openai_guardrail_handler.py index 2e75f29b1c5..a29e0be4655 100644 --- a/tests/test_litellm/llms/openai/chat/guardrail_translation/test_openai_guardrail_handler.py +++ b/tests/test_litellm/llms/openai/chat/guardrail_translation/test_openai_guardrail_handler.py @@ -6,15 +6,10 @@ with guardrail transformations, including tool calls. """ import json -import os -import sys from typing import Any, Literal, Optional import pytest -sys.path.insert( - 0, os.path.abspath("../../../../../../..") -) # Adds the parent directory to the system path from litellm.integrations.custom_guardrail import CustomGuardrail from litellm.llms.openai.chat.guardrail_translation.handler import ( diff --git a/tests/test_litellm/llms/openai/chat/test_openai_gpt_transformation.py b/tests/test_litellm/llms/openai/chat/test_openai_gpt_transformation.py index 101c5363bf7..f4c38f8f797 100644 --- a/tests/test_litellm/llms/openai/chat/test_openai_gpt_transformation.py +++ b/tests/test_litellm/llms/openai/chat/test_openai_gpt_transformation.py @@ -2,12 +2,9 @@ Tests for OpenAI GPT transformation (litellm/llms/openai/chat/gpt_transformation.py) """ -import os -import sys import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) import litellm from litellm.litellm_core_utils.prompt_templates.common_utils import TOOL_RESULT_IMAGE_BOUNDARY diff --git a/tests/test_litellm/llms/openai/completion/test_completion_handler.py b/tests/test_litellm/llms/openai/completion/test_completion_handler.py index c6af96fa375..329956605ab 100644 --- a/tests/test_litellm/llms/openai/completion/test_completion_handler.py +++ b/tests/test_litellm/llms/openai/completion/test_completion_handler.py @@ -5,14 +5,11 @@ text completion path. Regression tests for https://github.com/BerriAI/litellm/issues/27410 """ -import os -import sys import pytest import respx from httpx import Response -sys.path.insert(0, os.path.abspath("../../../../..")) import litellm from litellm import atext_completion, text_completion diff --git a/tests/test_litellm/llms/openai/completion/test_text_completion_guardrail_handler.py b/tests/test_litellm/llms/openai/completion/test_text_completion_guardrail_handler.py index 257db89d073..c96fbf34fe1 100644 --- a/tests/test_litellm/llms/openai/completion/test_text_completion_guardrail_handler.py +++ b/tests/test_litellm/llms/openai/completion/test_text_completion_guardrail_handler.py @@ -2,14 +2,11 @@ Unit tests for OpenAI Text Completion Guardrail Translation Handler """ -import os -import sys from typing import List, Optional, Tuple from unittest.mock import MagicMock import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm.integrations.custom_guardrail import CustomGuardrail from litellm.llms import get_guardrail_translation_mapping diff --git a/tests/test_litellm/llms/openai/completion/test_text_completion_token_ids.py b/tests/test_litellm/llms/openai/completion/test_text_completion_token_ids.py index 9c612af3898..35faeeb268a 100644 --- a/tests/test_litellm/llms/openai/completion/test_text_completion_token_ids.py +++ b/tests/test_litellm/llms/openai/completion/test_text_completion_token_ids.py @@ -3,14 +3,11 @@ Unit tests for text_completion with token IDs (list of integers) as prompt. Tests the fix for https://github.com/BerriAI/litellm/issues/17118 """ -import os -import sys import pytest import respx from httpx import Response -sys.path.insert(0, os.path.abspath("../../../../..")) import litellm from litellm import text_completion diff --git a/tests/test_litellm/llms/openai/image_generation/test_image_generation_guardrail_handler.py b/tests/test_litellm/llms/openai/image_generation/test_image_generation_guardrail_handler.py index cfccd6f3bbe..0d699b1ec95 100644 --- a/tests/test_litellm/llms/openai/image_generation/test_image_generation_guardrail_handler.py +++ b/tests/test_litellm/llms/openai/image_generation/test_image_generation_guardrail_handler.py @@ -2,13 +2,10 @@ Unit tests for OpenAI Image Generation Guardrail Translation Handler """ -import os -import sys from typing import List, Optional, Tuple import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm.integrations.custom_guardrail import CustomGuardrail from litellm.llms import get_guardrail_translation_mapping diff --git a/tests/test_litellm/llms/openai/image_generation/test_openai_image_generation_extra_headers.py b/tests/test_litellm/llms/openai/image_generation/test_openai_image_generation_extra_headers.py index 33db9d33c1c..55ef74abd7b 100644 --- a/tests/test_litellm/llms/openai/image_generation/test_openai_image_generation_extra_headers.py +++ b/tests/test_litellm/llms/openai/image_generation/test_openai_image_generation_extra_headers.py @@ -6,13 +6,10 @@ litellm.aimage_generation() are forwarded to the OpenAI API client as extra_headers in the images.generate() call. """ -import os -import sys from unittest.mock import MagicMock, AsyncMock, patch import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm.llms.openai.openai import OpenAIChatCompletion @@ -151,6 +148,58 @@ class TestImageGenerationExtraHeaders: _, kwargs = mock_openai_client.images.generate.call_args assert "extra_headers" not in kwargs + @pytest.mark.parametrize("is_async", [False, True]) + @pytest.mark.asyncio + async def test_caller_headers_never_reach_the_logged_request_body( + self, openai_chat_completions, mock_logging_obj, is_async + ): + """The body handed to pre_call is also what telemetry reads at close time, so + merging caller headers into that same dict would publish a customer's auth + header as a span attribute. The upstream call still gets them.""" + mock_image_data = MagicMock() + mock_image_data.model_dump.return_value = { + "created": 1700000000, + "data": [{"url": "https://example.com/image.png"}], + } + + mock_openai_client = MagicMock() + mock_openai_client.api_key = "test-key" + mock_openai_client._base_url._uri_reference = "https://api.openai.com" + + test_headers = {"cf-aig-authorization": "Bearer custom-token"} + + if is_async: + mock_openai_client.images.generate = AsyncMock(return_value=mock_image_data) + await openai_chat_completions.aimage_generation( + prompt="A white cat", + data={"model": "dall-e-3", "prompt": "A white cat"}, + model_response=MagicMock(), + timeout=60.0, + logging_obj=mock_logging_obj, + api_key="test-key", + headers=test_headers, + client=mock_openai_client, + ) + else: + mock_openai_client.images.generate.return_value = mock_image_data + openai_chat_completions.image_generation( + model="dall-e-3", + prompt="A white cat", + timeout=60.0, + optional_params={}, + logging_obj=mock_logging_obj, + api_key="test-key", + headers=test_headers, + client=mock_openai_client, + ) + + logged_body = mock_logging_obj.pre_call.call_args[1]["additional_args"][ + "complete_input_dict" + ] + assert "extra_headers" not in logged_body + _, kwargs = mock_openai_client.images.generate.call_args + assert kwargs.get("extra_headers") == test_headers + def test_sync_image_generation_forwards_headers_to_async( self, openai_chat_completions, mock_logging_obj ): diff --git a/tests/test_litellm/llms/openai/realtime/test_openai_realtime_handler.py b/tests/test_litellm/llms/openai/realtime/test_openai_realtime_handler.py index 2633e76b0f3..4221954d787 100644 --- a/tests/test_litellm/llms/openai/realtime/test_openai_realtime_handler.py +++ b/tests/test_litellm/llms/openai/realtime/test_openai_realtime_handler.py @@ -1,6 +1,4 @@ import json -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import httpx @@ -8,9 +6,6 @@ import pytest from litellm.llms.custom_httpx.http_handler import get_shared_realtime_ssl_context -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path @pytest.mark.parametrize( diff --git a/tests/test_litellm/llms/openai/realtime/test_transcription_sessions.py b/tests/test_litellm/llms/openai/realtime/test_transcription_sessions.py index 62fc3a8d0aa..54f206d098d 100644 --- a/tests/test_litellm/llms/openai/realtime/test_transcription_sessions.py +++ b/tests/test_litellm/llms/openai/realtime/test_transcription_sessions.py @@ -5,14 +5,11 @@ Tests for the Realtime transcription_sessions surface used by gpt-realtime-whisp - BaseLLMHTTPHandler.async_realtime_transcription_session_handler targeting """ -import os -import sys from unittest.mock import AsyncMock, MagicMock import httpx import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm.llms.azure.realtime.http_transformation import AzureRealtimeHTTPConfig from litellm.llms.custom_httpx.http_handler import AsyncHTTPHandler diff --git a/tests/test_litellm/llms/openai/responses/test_openai_count_tokens_transformation.py b/tests/test_litellm/llms/openai/responses/test_openai_count_tokens_transformation.py index 195fba69010..e1cc6a92927 100644 --- a/tests/test_litellm/llms/openai/responses/test_openai_count_tokens_transformation.py +++ b/tests/test_litellm/llms/openai/responses/test_openai_count_tokens_transformation.py @@ -1,11 +1,6 @@ -import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path from litellm.llms.openai.responses.count_tokens.transformation import ( OpenAICountTokensConfig, ) diff --git a/tests/test_litellm/llms/openai/responses/test_openai_responses_guardrail_handler.py b/tests/test_litellm/llms/openai/responses/test_openai_responses_guardrail_handler.py index 4c45eaac7b9..447175b09a6 100644 --- a/tests/test_litellm/llms/openai/responses/test_openai_responses_guardrail_handler.py +++ b/tests/test_litellm/llms/openai/responses/test_openai_responses_guardrail_handler.py @@ -5,16 +5,11 @@ Tests the handler's ability to process input/output for the Responses API with guardrail transformations. """ -import os -import sys from typing import Any, List, Literal, Optional, Tuple from unittest.mock import AsyncMock, MagicMock import pytest -sys.path.insert( - 0, os.path.abspath("../../../../../..") -) # Adds the parent directory to the system path from fastapi import HTTPException from openai.types.responses import ResponseFunctionToolCall diff --git a/tests/test_litellm/llms/openai/responses/test_openai_responses_transformation.py b/tests/test_litellm/llms/openai/responses/test_openai_responses_transformation.py index 13b96dc9943..c03c632363d 100644 --- a/tests/test_litellm/llms/openai/responses/test_openai_responses_transformation.py +++ b/tests/test_litellm/llms/openai/responses/test_openai_responses_transformation.py @@ -1,14 +1,9 @@ import json -import os -import sys from unittest.mock import AsyncMock, MagicMock, Mock, patch import httpx import pytest -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path import litellm from litellm.llms.base_llm.responses.transformation import BaseResponsesAPIConfig diff --git a/tests/test_litellm/llms/openai/speech/test_text_to_speech_guardrail_handler.py b/tests/test_litellm/llms/openai/speech/test_text_to_speech_guardrail_handler.py index 5b6387cb100..88149d82c52 100644 --- a/tests/test_litellm/llms/openai/speech/test_text_to_speech_guardrail_handler.py +++ b/tests/test_litellm/llms/openai/speech/test_text_to_speech_guardrail_handler.py @@ -2,13 +2,10 @@ Unit tests for OpenAI Text-to-Speech Guardrail Translation Handler """ -import os -import sys from typing import List, Optional, Tuple import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm.integrations.custom_guardrail import CustomGuardrail from litellm.llms import get_guardrail_translation_mapping diff --git a/tests/test_litellm/llms/openai/test_openai_common_utils.py b/tests/test_litellm/llms/openai/test_openai_common_utils.py index bfd681cc06e..3ae29e411e8 100644 --- a/tests/test_litellm/llms/openai/test_openai_common_utils.py +++ b/tests/test_litellm/llms/openai/test_openai_common_utils.py @@ -1,14 +1,9 @@ -import os -import sys from unittest.mock import MagicMock, call, patch import httpx import openai import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path import litellm from litellm.litellm_core_utils.token_counter import token_counter @@ -86,7 +81,6 @@ async def test_openai_client_reuse(function_name, is_async, args): """ Test that multiple API calls reuse the same OpenAI client """ - litellm.set_verbose = True # Determine which client class to mock based on whether the test is async client_path = ( diff --git a/tests/test_litellm/llms/openai/test_openai_empty_response.py b/tests/test_litellm/llms/openai/test_openai_empty_response.py index 8a0ff237869..26b28f967db 100644 --- a/tests/test_litellm/llms/openai/test_openai_empty_response.py +++ b/tests/test_litellm/llms/openai/test_openai_empty_response.py @@ -2,13 +2,10 @@ Test for issue #17209: Clearer error when LLM endpoint returns empty response """ -import os -import sys from unittest.mock import MagicMock, patch import pytest -sys.path.insert(0, os.path.abspath("../../../..")) from litellm.llms.openai.openai import OpenAIChatCompletion from litellm.llms.openai.common_utils import OpenAIError diff --git a/tests/test_litellm/llms/openai/test_use_chat_completions_api_no_leak.py b/tests/test_litellm/llms/openai/test_use_chat_completions_api_no_leak.py index 9a266fca81f..7013afc7a5f 100644 --- a/tests/test_litellm/llms/openai/test_use_chat_completions_api_no_leak.py +++ b/tests/test_litellm/llms/openai/test_use_chat_completions_api_no_leak.py @@ -7,11 +7,8 @@ proxy config, it must never be forwarded to the upstream provider's request body. OpenAI/Anthropic reject unknown body params with HTTP 400. """ -import os -import sys from unittest.mock import MagicMock -sys.path.insert(0, os.path.abspath("../../../..")) import litellm from litellm.types.utils import all_litellm_params diff --git a/tests/test_litellm/llms/openai/transcriptions/test_audio_transcription_guardrail_handler.py b/tests/test_litellm/llms/openai/transcriptions/test_audio_transcription_guardrail_handler.py index 307972ff477..269cbc7855d 100644 --- a/tests/test_litellm/llms/openai/transcriptions/test_audio_transcription_guardrail_handler.py +++ b/tests/test_litellm/llms/openai/transcriptions/test_audio_transcription_guardrail_handler.py @@ -2,13 +2,10 @@ Unit tests for OpenAI Audio Transcription Guardrail Translation Handler """ -import os -import sys from typing import List, Optional, Tuple import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm.integrations.custom_guardrail import CustomGuardrail from litellm.llms import get_guardrail_translation_mapping diff --git a/tests/test_litellm/llms/openrouter/chat/test_openrouter_chat_transformation.py b/tests/test_litellm/llms/openrouter/chat/test_openrouter_chat_transformation.py index 8d1129cc5da..b177b80aed1 100644 --- a/tests/test_litellm/llms/openrouter/chat/test_openrouter_chat_transformation.py +++ b/tests/test_litellm/llms/openrouter/chat/test_openrouter_chat_transformation.py @@ -1,12 +1,7 @@ -import os -import sys import httpx import pytest -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path from litellm.llms.openai.chat.gpt_transformation import OpenAIGPTConfig from litellm.llms.openrouter.chat.transformation import ( diff --git a/tests/test_litellm/llms/openrouter/image_edit/test_openrouter_image_edit_transformation.py b/tests/test_litellm/llms/openrouter/image_edit/test_openrouter_image_edit_transformation.py index f352c077fc4..5a78560f61b 100644 --- a/tests/test_litellm/llms/openrouter/image_edit/test_openrouter_image_edit_transformation.py +++ b/tests/test_litellm/llms/openrouter/image_edit/test_openrouter_image_edit_transformation.py @@ -1,16 +1,11 @@ import base64 import json -import os -import sys from io import BytesIO from unittest.mock import MagicMock, patch import httpx import pytest -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path from litellm.llms.openrouter.common_utils import OpenRouterException from litellm.llms.openrouter.image_edit.transformation import ( diff --git a/tests/test_litellm/llms/openrouter/image_generation/test_openrouter_image_gen_transformation.py b/tests/test_litellm/llms/openrouter/image_generation/test_openrouter_image_gen_transformation.py index 52a4fabaed7..e45270fb5e3 100644 --- a/tests/test_litellm/llms/openrouter/image_generation/test_openrouter_image_gen_transformation.py +++ b/tests/test_litellm/llms/openrouter/image_generation/test_openrouter_image_gen_transformation.py @@ -1,14 +1,9 @@ import json -import os -import sys from unittest.mock import MagicMock, patch import httpx import pytest -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path from litellm.llms.openrouter.image_generation.transformation import ( OpenRouterImageGenerationConfig, diff --git a/tests/test_litellm/llms/openrouter/test_openrouter_provider_routing.py b/tests/test_litellm/llms/openrouter/test_openrouter_provider_routing.py index 0815b15c873..d2e4e88e77f 100644 --- a/tests/test_litellm/llms/openrouter/test_openrouter_provider_routing.py +++ b/tests/test_litellm/llms/openrouter/test_openrouter_provider_routing.py @@ -11,12 +11,9 @@ so the correct model ID is sent to the OpenRouter API. See: https://github.com/BerriAI/litellm/issues/16353 """ -import os -import sys import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) import litellm diff --git a/tests/test_litellm/llms/ovhcloud/test_ovhcloud_chat_transformation.py b/tests/test_litellm/llms/ovhcloud/test_ovhcloud_chat_transformation.py index 40d57c76d02..057ab9ede9a 100644 --- a/tests/test_litellm/llms/ovhcloud/test_ovhcloud_chat_transformation.py +++ b/tests/test_litellm/llms/ovhcloud/test_ovhcloud_chat_transformation.py @@ -3,16 +3,12 @@ Unit tests for OVHCloud AI Endpoints chat integration. """ import os -import sys import pytest from litellm.llms.ovhcloud.utils import OVHCloudException from litellm.utils import get_optional_params -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path from litellm.llms.ovhcloud.chat.transformation import ( OVHCloudChatCompletionStreamingHandler, @@ -179,7 +175,6 @@ class TestOVHCloudConfig: def test_ovhcloud_integration(): - import os from litellm import completion api_key = os.getenv("OVHCLOUD_API_KEY") @@ -207,7 +202,6 @@ def test_OVHCloud_streaming_integration(): Integration test for streaming - requires real API key Run with: pytest -k test_OVHCloud_streaming_integration -s """ - import os from litellm import completion api_key = os.getenv("OVHCLOUD_API_KEY") @@ -262,7 +256,6 @@ def test_ovhcloud_with_custom_base_url(): """ Test OVHCloud with custom base URL """ - import os from litellm import completion api_key = os.getenv("OVHCLOUD_API_KEY") diff --git a/tests/test_litellm/llms/parallel_ai/test_parallel_ai_search.py b/tests/test_litellm/llms/parallel_ai/test_parallel_ai_search.py index 7be295826e3..8a9ae4dae6d 100644 --- a/tests/test_litellm/llms/parallel_ai/test_parallel_ai_search.py +++ b/tests/test_litellm/llms/parallel_ai/test_parallel_ai_search.py @@ -2,13 +2,10 @@ Tests for Parallel AI Search API integration (v1 endpoint). """ -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import pytest -sys.path.insert(0, os.path.abspath("../../../..")) import litellm diff --git a/tests/test_litellm/llms/perplexity/chat/test_perplexity_chat_transformation.py b/tests/test_litellm/llms/perplexity/chat/test_perplexity_chat_transformation.py index af441313d58..29d185b686d 100644 --- a/tests/test_litellm/llms/perplexity/chat/test_perplexity_chat_transformation.py +++ b/tests/test_litellm/llms/perplexity/chat/test_perplexity_chat_transformation.py @@ -5,14 +5,11 @@ Tests the response transformation to extract citation tokens and search queries from Perplexity API responses. """ -import os -import sys from unittest.mock import Mock import pytest # Add the project root to Python path -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm import ModelResponse from litellm.llms.perplexity.chat.transformation import PerplexityChatConfig diff --git a/tests/test_litellm/llms/perplexity/responses/test_perplexity_responses_transformation.py b/tests/test_litellm/llms/perplexity/responses/test_perplexity_responses_transformation.py index a3ec81c569c..534176e381a 100644 --- a/tests/test_litellm/llms/perplexity/responses/test_perplexity_responses_transformation.py +++ b/tests/test_litellm/llms/perplexity/responses/test_perplexity_responses_transformation.py @@ -8,13 +8,10 @@ Source: litellm/llms/perplexity/responses/transformation.py """ import json -import os -import sys import httpx import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj from litellm.llms.base_llm.chat.transformation import BaseLLMException diff --git a/tests/test_litellm/llms/perplexity/test_perplexity.py b/tests/test_litellm/llms/perplexity/test_perplexity.py index c6fb819e97b..797a56070c6 100644 --- a/tests/test_litellm/llms/perplexity/test_perplexity.py +++ b/tests/test_litellm/llms/perplexity/test_perplexity.py @@ -1,7 +1,4 @@ -import os -import sys -sys.path.insert(0, os.path.abspath("../../..")) import pytest diff --git a/tests/test_litellm/llms/perplexity/test_perplexity_cost_calculator.py b/tests/test_litellm/llms/perplexity/test_perplexity_cost_calculator.py index 16708e062e4..117379c331a 100644 --- a/tests/test_litellm/llms/perplexity/test_perplexity_cost_calculator.py +++ b/tests/test_litellm/llms/perplexity/test_perplexity_cost_calculator.py @@ -8,13 +8,11 @@ search queries, and reasoning tokens. import json import math import os -import sys from unittest.mock import patch import pytest # Add the project root to Python path -sys.path.insert(0, os.path.abspath("../../../..")) import litellm from litellm.cost_calculator import completion_cost, cost_per_token diff --git a/tests/test_litellm/llms/perplexity/test_perplexity_integration.py b/tests/test_litellm/llms/perplexity/test_perplexity_integration.py index 8691e6a1ee5..990fa7eb464 100644 --- a/tests/test_litellm/llms/perplexity/test_perplexity_integration.py +++ b/tests/test_litellm/llms/perplexity/test_perplexity_integration.py @@ -8,12 +8,10 @@ including integration with the main LiteLLM cost calculator. import json import math import os -import sys import pytest # Add the project root to Python path -sys.path.insert(0, os.path.abspath("../../../..")) import litellm from litellm import ModelResponse diff --git a/tests/test_litellm/llms/publicai/test_publicai_chat_transformation.py b/tests/test_litellm/llms/publicai/test_publicai_chat_transformation.py index 2dabf604b98..487f311b2fc 100644 --- a/tests/test_litellm/llms/publicai/test_publicai_chat_transformation.py +++ b/tests/test_litellm/llms/publicai/test_publicai_chat_transformation.py @@ -5,11 +5,8 @@ These tests validate the PublicAI configuration which is now JSON-based. PublicAI is an OpenAI-compatible provider with minor customizations. """ -import os -import sys from unittest.mock import patch -sys.path.insert(0, os.path.abspath("../../../../..")) import pytest diff --git a/tests/test_litellm/llms/ragflow/chat/test_ragflow_chat_transformation.py b/tests/test_litellm/llms/ragflow/chat/test_ragflow_chat_transformation.py index baf2ab33910..437f53fea1a 100644 --- a/tests/test_litellm/llms/ragflow/chat/test_ragflow_chat_transformation.py +++ b/tests/test_litellm/llms/ragflow/chat/test_ragflow_chat_transformation.py @@ -6,13 +6,11 @@ for RAGFlow's OpenAI-compatible API with custom path structures. """ import os -import sys from unittest.mock import Mock, patch import pytest # Add the project root to Python path -sys.path.insert(0, os.path.abspath("../../../../..")) import litellm from litellm.llms.ragflow.chat.transformation import RAGFlowConfig diff --git a/tests/test_litellm/llms/recraft/image_edit/test_recraft_image_edit_transformation.py b/tests/test_litellm/llms/recraft/image_edit/test_recraft_image_edit_transformation.py index 47811321133..97d65935a1b 100644 --- a/tests/test_litellm/llms/recraft/image_edit/test_recraft_image_edit_transformation.py +++ b/tests/test_litellm/llms/recraft/image_edit/test_recraft_image_edit_transformation.py @@ -1,6 +1,4 @@ import json -import os -import sys from io import BufferedReader, BytesIO from typing import Dict, List from unittest.mock import MagicMock, mock_open, patch @@ -8,9 +6,6 @@ from unittest.mock import MagicMock, mock_open, patch import httpx import pytest -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path from litellm.llms.recraft.image_edit.transformation import RecraftImageEditConfig from litellm.types.images.main import ImageEditOptionalRequestParams diff --git a/tests/test_litellm/llms/recraft/image_generation/test_recraft_image_gen_transformation.py b/tests/test_litellm/llms/recraft/image_generation/test_recraft_image_gen_transformation.py index ccc72dde7b8..2dfe33b828c 100644 --- a/tests/test_litellm/llms/recraft/image_generation/test_recraft_image_gen_transformation.py +++ b/tests/test_litellm/llms/recraft/image_generation/test_recraft_image_gen_transformation.py @@ -1,15 +1,10 @@ import json -import os -import sys from typing import List, Optional from unittest.mock import MagicMock, patch import httpx import pytest -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path from litellm.llms.recraft.image_generation.transformation import ( RecraftImageGenerationConfig, diff --git a/tests/test_litellm/llms/runwayml/test_text_to_speech_transformation.py b/tests/test_litellm/llms/runwayml/test_text_to_speech_transformation.py index 8871260813d..2e4d68a02da 100644 --- a/tests/test_litellm/llms/runwayml/test_text_to_speech_transformation.py +++ b/tests/test_litellm/llms/runwayml/test_text_to_speech_transformation.py @@ -2,10 +2,7 @@ Test RunwayML text-to-speech transformation """ -import os -import sys -sys.path.insert(0, os.path.abspath("../../../..")) from litellm.llms.runwayml.text_to_speech.transformation import ( RunwayMLTextToSpeechConfig, diff --git a/tests/test_litellm/llms/sagemaker/test_sagemaker_common_utils.py b/tests/test_litellm/llms/sagemaker/test_sagemaker_common_utils.py index f928964dab8..e2dd3bca74f 100644 --- a/tests/test_litellm/llms/sagemaker/test_sagemaker_common_utils.py +++ b/tests/test_litellm/llms/sagemaker/test_sagemaker_common_utils.py @@ -1,12 +1,9 @@ import json -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import httpx import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm.llms.sagemaker.common_utils import AWSEventStreamDecoder from litellm.llms.sagemaker.completion.transformation import SagemakerConfig diff --git a/tests/test_litellm/llms/sagemaker/test_sagemaker_embedding_role_assumption.py b/tests/test_litellm/llms/sagemaker/test_sagemaker_embedding_role_assumption.py index c7ffe727d1a..2a14d58a187 100644 --- a/tests/test_litellm/llms/sagemaker/test_sagemaker_embedding_role_assumption.py +++ b/tests/test_litellm/llms/sagemaker/test_sagemaker_embedding_role_assumption.py @@ -7,12 +7,9 @@ matching the behavior of the completion handler. """ import json -import os -import sys from datetime import timezone from unittest.mock import MagicMock, call, patch -sys.path.insert(0, os.path.abspath("../../../../..")) from botocore.credentials import Credentials diff --git a/tests/test_litellm/llms/sagemaker/test_sagemaker_embedding_voyage.py b/tests/test_litellm/llms/sagemaker/test_sagemaker_embedding_voyage.py index 943a3160bb7..3951b17db92 100644 --- a/tests/test_litellm/llms/sagemaker/test_sagemaker_embedding_voyage.py +++ b/tests/test_litellm/llms/sagemaker/test_sagemaker_embedding_voyage.py @@ -7,14 +7,11 @@ transformation, and model type detection. """ import json -import os -import sys from unittest.mock import MagicMock, patch import httpx import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm import embedding from litellm.llms.sagemaker.embedding.cohere_transformation import ( diff --git a/tests/test_litellm/llms/test_cache_control_and_reasoning.py b/tests/test_litellm/llms/test_cache_control_and_reasoning.py index 42f754bc093..be1ba1e7dbd 100644 --- a/tests/test_litellm/llms/test_cache_control_and_reasoning.py +++ b/tests/test_litellm/llms/test_cache_control_and_reasoning.py @@ -7,14 +7,9 @@ This test file verifies the fixes for Issue #19923: - Model metadata correctly reflects capabilities """ -import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from litellm.llms.minimax.chat.transformation import MinimaxChatConfig from litellm.llms.openrouter.chat.transformation import OpenrouterConfig diff --git a/tests/test_litellm/llms/vercel_ai_gateway/chat/test_vercel_ai_gateway_transformation.py b/tests/test_litellm/llms/vercel_ai_gateway/chat/test_vercel_ai_gateway_transformation.py index f6ac8af1115..a58942559fd 100644 --- a/tests/test_litellm/llms/vercel_ai_gateway/chat/test_vercel_ai_gateway_transformation.py +++ b/tests/test_litellm/llms/vercel_ai_gateway/chat/test_vercel_ai_gateway_transformation.py @@ -1,12 +1,7 @@ -import os -import sys from unittest.mock import patch import pytest -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path from litellm.llms.vercel_ai_gateway.chat.transformation import ( VercelAIGatewayConfig, diff --git a/tests/test_litellm/llms/vercel_ai_gateway/embedding/test_vercel_ai_gateway_embedding.py b/tests/test_litellm/llms/vercel_ai_gateway/embedding/test_vercel_ai_gateway_embedding.py index af1e1df92fd..7ce91558f39 100644 --- a/tests/test_litellm/llms/vercel_ai_gateway/embedding/test_vercel_ai_gateway_embedding.py +++ b/tests/test_litellm/llms/vercel_ai_gateway/embedding/test_vercel_ai_gateway_embedding.py @@ -1,13 +1,9 @@ import os -import sys from unittest.mock import MagicMock, patch import httpx import pytest -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path from litellm.llms.vercel_ai_gateway.embedding.transformation import ( VercelAIGatewayEmbeddingConfig, diff --git a/tests/test_litellm/llms/vertex_ai/agent_engine/test_transformation.py b/tests/test_litellm/llms/vertex_ai/agent_engine/test_transformation.py index af0faee9e21..19616682c59 100644 --- a/tests/test_litellm/llms/vertex_ai/agent_engine/test_transformation.py +++ b/tests/test_litellm/llms/vertex_ai/agent_engine/test_transformation.py @@ -4,12 +4,9 @@ Tests for Vertex AI Agent Engine transformation. Tests the request transformation and streaming chunk parsing without making real API calls. """ -import os -import sys import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm.llms.vertex_ai.agent_engine.sse_iterator import ( VertexAgentEngineResponseIterator, diff --git a/tests/test_litellm/llms/vertex_ai/audio_transcription/test_vertex_ai_audio_transcription_transformation.py b/tests/test_litellm/llms/vertex_ai/audio_transcription/test_vertex_ai_audio_transcription_transformation.py index 3fa28699f73..3a1922d1021 100644 --- a/tests/test_litellm/llms/vertex_ai/audio_transcription/test_vertex_ai_audio_transcription_transformation.py +++ b/tests/test_litellm/llms/vertex_ai/audio_transcription/test_vertex_ai_audio_transcription_transformation.py @@ -1,13 +1,11 @@ import base64 import json import os -import sys from urllib.parse import urlparse import httpx import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) import litellm from litellm.llms.vertex_ai.audio_transcription.transformation import ( diff --git a/tests/test_litellm/llms/vertex_ai/batches/test_handler.py b/tests/test_litellm/llms/vertex_ai/batches/test_handler.py index 9535bf17411..38fde3caa63 100644 --- a/tests/test_litellm/llms/vertex_ai/batches/test_handler.py +++ b/tests/test_litellm/llms/vertex_ai/batches/test_handler.py @@ -30,14 +30,11 @@ from __future__ import annotations import asyncio import json -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import httpx import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm.llms.vertex_ai.batches.handler import ( # noqa: E402 VertexAIBatchPrediction, diff --git a/tests/test_litellm/llms/vertex_ai/batches/test_transformation.py b/tests/test_litellm/llms/vertex_ai/batches/test_transformation.py index 8352ec16389..ccb2d7e310d 100644 --- a/tests/test_litellm/llms/vertex_ai/batches/test_transformation.py +++ b/tests/test_litellm/llms/vertex_ai/batches/test_transformation.py @@ -13,13 +13,10 @@ There are no real I/O seams here; ``uuid.uuid4`` is the only nondeterministic dependency and is patched where the displayName is asserted. """ -import os -import sys from unittest.mock import patch import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm.llms.vertex_ai.batches.transformation import ( # noqa: E402 VertexAIBatchTransformation, diff --git a/tests/test_litellm/llms/vertex_ai/context_caching/test_vertex_ai_context_caching.py b/tests/test_litellm/llms/vertex_ai/context_caching/test_vertex_ai_context_caching.py index ad890d0c7ea..f666829d2e8 100644 --- a/tests/test_litellm/llms/vertex_ai/context_caching/test_vertex_ai_context_caching.py +++ b/tests/test_litellm/llms/vertex_ai/context_caching/test_vertex_ai_context_caching.py @@ -1,14 +1,9 @@ -import os -import sys from typing import List from unittest.mock import AsyncMock, MagicMock, patch import httpx import pytest -sys.path.insert( - 0, os.path.abspath("../../../..") -) # Adds the parent directory to the system path from litellm.litellm_core_utils.litellm_logging import Logging from litellm.llms.custom_httpx.http_handler import AsyncHTTPHandler, HTTPHandler diff --git a/tests/test_litellm/llms/vertex_ai/gemini/test_transformation.py b/tests/test_litellm/llms/vertex_ai/gemini/test_transformation.py index 756923c5df6..fad310fc5c0 100644 --- a/tests/test_litellm/llms/vertex_ai/gemini/test_transformation.py +++ b/tests/test_litellm/llms/vertex_ai/gemini/test_transformation.py @@ -1,11 +1,6 @@ -import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path from litellm.llms.vertex_ai.gemini import transformation from litellm.llms.vertex_ai.gemini.vertex_and_google_ai_studio_gemini import ( VertexGeminiConfig, diff --git a/tests/test_litellm/llms/vertex_ai/image_generation/test_vertex_ai_image_generation_transformation.py b/tests/test_litellm/llms/vertex_ai/image_generation/test_vertex_ai_image_generation_transformation.py index 8c72bdee525..54607cc5284 100644 --- a/tests/test_litellm/llms/vertex_ai/image_generation/test_vertex_ai_image_generation_transformation.py +++ b/tests/test_litellm/llms/vertex_ai/image_generation/test_vertex_ai_image_generation_transformation.py @@ -1,11 +1,9 @@ import os -import sys from unittest.mock import MagicMock, patch import httpx import pytest -sys.path.insert(0, os.path.abspath("../..")) from litellm.llms.vertex_ai.image_generation import ( get_vertex_ai_image_generation_config, diff --git a/tests/test_litellm/llms/vertex_ai/multimodal_embeddings/test_vertex_ai_multimodal_embedding_transformation.py b/tests/test_litellm/llms/vertex_ai/multimodal_embeddings/test_vertex_ai_multimodal_embedding_transformation.py index 6b605aed0ca..edb6e889814 100644 --- a/tests/test_litellm/llms/vertex_ai/multimodal_embeddings/test_vertex_ai_multimodal_embedding_transformation.py +++ b/tests/test_litellm/llms/vertex_ai/multimodal_embeddings/test_vertex_ai_multimodal_embedding_transformation.py @@ -1,14 +1,9 @@ import json -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import httpx import pytest -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path from litellm.llms.vertex_ai.multimodal_embeddings.transformation import ( VertexAIMultimodalEmbeddingConfig, diff --git a/tests/test_litellm/llms/vertex_ai/realtime/test_vertex_ai_realtime_transformation.py b/tests/test_litellm/llms/vertex_ai/realtime/test_vertex_ai_realtime_transformation.py index f11b00d204d..720c629cbf7 100644 --- a/tests/test_litellm/llms/vertex_ai/realtime/test_vertex_ai_realtime_transformation.py +++ b/tests/test_litellm/llms/vertex_ai/realtime/test_vertex_ai_realtime_transformation.py @@ -10,14 +10,11 @@ Validates: """ import json -import os -import sys from unittest.mock import AsyncMock, MagicMock import pytest import websockets.exceptions # registers websockets.exceptions on the websockets namespace -sys.path.insert(0, os.path.abspath("../../../../..")) import litellm from litellm.llms.vertex_ai.realtime.transformation import VertexAIRealtimeConfig diff --git a/tests/test_litellm/llms/vertex_ai/test_bge_embedding.py b/tests/test_litellm/llms/vertex_ai/test_bge_embedding.py index d8b299dcf66..7538c070cd0 100644 --- a/tests/test_litellm/llms/vertex_ai/test_bge_embedding.py +++ b/tests/test_litellm/llms/vertex_ai/test_bge_embedding.py @@ -6,11 +6,8 @@ and that the request body is properly formatted. """ import json -import os -import sys from unittest.mock import MagicMock, patch -sys.path.insert(0, os.path.abspath("../../../..")) import pytest diff --git a/tests/test_litellm/llms/vertex_ai/test_bge_response_transformation.py b/tests/test_litellm/llms/vertex_ai/test_bge_response_transformation.py index 26aa85a886e..9e960570036 100644 --- a/tests/test_litellm/llms/vertex_ai/test_bge_response_transformation.py +++ b/tests/test_litellm/llms/vertex_ai/test_bge_response_transformation.py @@ -5,10 +5,7 @@ This test verifies that the BGE response transformer properly validates and handles different response formats. """ -import os -import sys -sys.path.insert(0, os.path.abspath("../../../..")) import pytest diff --git a/tests/test_litellm/llms/vertex_ai/test_gemini_empty_properties.py b/tests/test_litellm/llms/vertex_ai/test_gemini_empty_properties.py index 1a4e4d35ca9..441b598e751 100644 --- a/tests/test_litellm/llms/vertex_ai/test_gemini_empty_properties.py +++ b/tests/test_litellm/llms/vertex_ai/test_gemini_empty_properties.py @@ -1,9 +1,6 @@ """Test for Gemini schema handling with empty properties.""" -import os -import sys -sys.path.insert(0, os.path.abspath("../../../..")) from litellm.llms.vertex_ai.common_utils import add_object_type diff --git a/tests/test_litellm/llms/vertex_ai/test_vertex.py b/tests/test_litellm/llms/vertex_ai/test_vertex.py index ec73e5e42be..e3007bac7f3 100644 --- a/tests/test_litellm/llms/vertex_ai/test_vertex.py +++ b/tests/test_litellm/llms/vertex_ai/test_vertex.py @@ -1,7 +1,5 @@ import base64 import json -import os -import sys from dotenv import load_dotenv @@ -12,9 +10,6 @@ import litellm.litellm_core_utils.prompt_templates.factory load_dotenv() from unittest.mock import MagicMock -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import pytest import litellm @@ -33,7 +28,6 @@ def test_completion_pydantic_obj_2(): from litellm.llms.custom_httpx.http_handler import HTTPHandler - litellm.set_verbose = True class CalendarEvent(BaseModel): name: str @@ -259,7 +253,6 @@ def test_vertex_tool_type_field_removal(): def test_function_calling_with_gemini(): from litellm.llms.custom_httpx.http_handler import HTTPHandler - litellm.set_verbose = True client = HTTPHandler() with patch.object(client, "post", new=MagicMock()) as mock_post: try: @@ -310,7 +303,6 @@ def test_function_calling_with_gemini(): def test_multiple_function_call(): - litellm.set_verbose = True from litellm.llms.custom_httpx.http_handler import HTTPHandler client = HTTPHandler() @@ -420,7 +412,6 @@ def test_multiple_function_call(): def test_multiple_function_call_changed_text_pos(): - litellm.set_verbose = True from litellm.llms.custom_httpx.http_handler import HTTPHandler client = HTTPHandler() @@ -528,7 +519,6 @@ def test_multiple_function_call_changed_text_pos(): def test_function_calling_with_gemini_multiple_results(): - litellm.set_verbose = True from litellm.llms.custom_httpx.http_handler import HTTPHandler client = HTTPHandler() @@ -1103,7 +1093,6 @@ def test_logprobs_unit_test(): def test_logprobs(): - litellm.set_verbose = True from litellm.llms.custom_httpx.http_handler import HTTPHandler client = HTTPHandler() diff --git a/tests/test_litellm/llms/vertex_ai/test_vertex_ai_common_utils.py b/tests/test_litellm/llms/vertex_ai/test_vertex_ai_common_utils.py index 39a06c68913..cc923f05831 100644 --- a/tests/test_litellm/llms/vertex_ai/test_vertex_ai_common_utils.py +++ b/tests/test_litellm/llms/vertex_ai/test_vertex_ai_common_utils.py @@ -1,14 +1,9 @@ -import os -import sys from unittest.mock import patch import pytest from litellm.constants import DEFAULT_MAX_RECURSE_DEPTH -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from litellm.llms.vertex_ai.common_utils import ( _get_vertex_url, diff --git a/tests/test_litellm/llms/vertex_ai/test_vertex_gemini_gcs_uri_mime.py b/tests/test_litellm/llms/vertex_ai/test_vertex_gemini_gcs_uri_mime.py index e0eccad80e2..55493d47f3d 100644 --- a/tests/test_litellm/llms/vertex_ai/test_vertex_gemini_gcs_uri_mime.py +++ b/tests/test_litellm/llms/vertex_ai/test_vertex_gemini_gcs_uri_mime.py @@ -3,8 +3,6 @@ Split from test_vertex.py to satisfy CI per-file size limits. """ import asyncio -import os -import sys import time from dotenv import load_dotenv @@ -16,7 +14,6 @@ import pytest import litellm from unittest.mock import MagicMock, patch -sys.path.insert(0, os.path.abspath("../..")) from litellm.llms.vertex_ai.gemini.transformation import _process_gemini_media diff --git a/tests/test_litellm/llms/vertex_ai/test_vertex_image_generation.py b/tests/test_litellm/llms/vertex_ai/test_vertex_image_generation.py index 2a87d84e20f..84444690fa2 100644 --- a/tests/test_litellm/llms/vertex_ai/test_vertex_image_generation.py +++ b/tests/test_litellm/llms/vertex_ai/test_vertex_image_generation.py @@ -1,12 +1,7 @@ -import os -import sys from unittest.mock import MagicMock import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm.llms.vertex_ai.image_generation.image_generation_handler import ( diff --git a/tests/test_litellm/llms/vertex_ai/test_vertex_llm_base.py b/tests/test_litellm/llms/vertex_ai/test_vertex_llm_base.py index 18fc239b7c6..29d22e844a5 100644 --- a/tests/test_litellm/llms/vertex_ai/test_vertex_llm_base.py +++ b/tests/test_litellm/llms/vertex_ai/test_vertex_llm_base.py @@ -1,16 +1,11 @@ import asyncio import json -import os -import sys from unittest.mock import MagicMock, call, patch import pytest from litellm.constants import DEFAULT_MAX_RECURSE_DEPTH -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path import litellm from litellm.llms.vertex_ai.vertex_ai_aws_wif import VertexAIAwsWifAuth diff --git a/tests/test_litellm/llms/vertex_ai/text_to_speech/test_transformation.py b/tests/test_litellm/llms/vertex_ai/text_to_speech/test_transformation.py index 1e5ae05aa25..05da22a73fd 100644 --- a/tests/test_litellm/llms/vertex_ai/text_to_speech/test_transformation.py +++ b/tests/test_litellm/llms/vertex_ai/text_to_speech/test_transformation.py @@ -1,13 +1,8 @@ -import os -import sys from unittest.mock import MagicMock, Mock, patch import httpx import pytest -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path import litellm from litellm.llms.vertex_ai.text_to_speech.transformation import ( diff --git a/tests/test_litellm/llms/vertex_ai/vertex_ai_partner_models/anthropic/test_vertex_ai_anthropic_image_url_handling.py b/tests/test_litellm/llms/vertex_ai/vertex_ai_partner_models/anthropic/test_vertex_ai_anthropic_image_url_handling.py index b1aa7f629d5..fa286f6f609 100644 --- a/tests/test_litellm/llms/vertex_ai/vertex_ai_partner_models/anthropic/test_vertex_ai_anthropic_image_url_handling.py +++ b/tests/test_litellm/llms/vertex_ai/vertex_ai_partner_models/anthropic/test_vertex_ai_anthropic_image_url_handling.py @@ -6,15 +6,10 @@ Vertex AI Anthropic models don't support URL sources for images. LiteLLM should convert image URLs to base64 when using Vertex AI Anthropic. """ -import os -import sys from unittest.mock import patch, MagicMock import pytest -sys.path.insert( - 0, os.path.abspath("../../../../../..") -) # Adds the parent directory to the system path from litellm.litellm_core_utils.prompt_templates.factory import ( anthropic_messages_pt, diff --git a/tests/test_litellm/llms/vertex_ai/vertex_ai_partner_models/anthropic/test_vertex_ai_partner_models_anthropic_transformation.py b/tests/test_litellm/llms/vertex_ai/vertex_ai_partner_models/anthropic/test_vertex_ai_partner_models_anthropic_transformation.py index ac2368130d8..552ca98441f 100644 --- a/tests/test_litellm/llms/vertex_ai/vertex_ai_partner_models/anthropic/test_vertex_ai_partner_models_anthropic_transformation.py +++ b/tests/test_litellm/llms/vertex_ai/vertex_ai_partner_models/anthropic/test_vertex_ai_partner_models_anthropic_transformation.py @@ -1,11 +1,6 @@ -import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../../../../../..") -) # Adds the parent directory to the system path from litellm.anthropic_beta_headers_manager import ( update_headers_with_filtered_beta, ) diff --git a/tests/test_litellm/llms/vertex_ai/vertex_ai_partner_models/gemma/test_vertex_ai_gemma_global_endpoint.py b/tests/test_litellm/llms/vertex_ai/vertex_ai_partner_models/gemma/test_vertex_ai_gemma_global_endpoint.py index 7c61aba4f99..957d7475d91 100644 --- a/tests/test_litellm/llms/vertex_ai/vertex_ai_partner_models/gemma/test_vertex_ai_gemma_global_endpoint.py +++ b/tests/test_litellm/llms/vertex_ai/vertex_ai_partner_models/gemma/test_vertex_ai_gemma_global_endpoint.py @@ -13,14 +13,10 @@ These tests verify that: import json import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../../../../../..") -) # Adds the parent directory to the system path import litellm from litellm.llms.vertex_ai.vertex_ai_partner_models.main import VertexAIPartnerModels diff --git a/tests/test_litellm/llms/vertex_ai/vertex_ai_partner_models/gpt_oss/test_vertex_ai_gpt_oss_transformation.py b/tests/test_litellm/llms/vertex_ai/vertex_ai_partner_models/gpt_oss/test_vertex_ai_gpt_oss_transformation.py index f617a8db850..6255394d838 100644 --- a/tests/test_litellm/llms/vertex_ai/vertex_ai_partner_models/gpt_oss/test_vertex_ai_gpt_oss_transformation.py +++ b/tests/test_litellm/llms/vertex_ai/vertex_ai_partner_models/gpt_oss/test_vertex_ai_gpt_oss_transformation.py @@ -1,13 +1,9 @@ import json import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../../../../../..") -) # Adds the parent directory to the system path import litellm from litellm.llms.vertex_ai.vertex_ai_partner_models.gpt_oss.transformation import ( diff --git a/tests/test_litellm/llms/vertex_ai/vertex_ai_partner_models/llama3/test_vertex_ai_partner_models_llama3_transformation.py b/tests/test_litellm/llms/vertex_ai/vertex_ai_partner_models/llama3/test_vertex_ai_partner_models_llama3_transformation.py index 242a89d729a..3bca51ec6b3 100644 --- a/tests/test_litellm/llms/vertex_ai/vertex_ai_partner_models/llama3/test_vertex_ai_partner_models_llama3_transformation.py +++ b/tests/test_litellm/llms/vertex_ai/vertex_ai_partner_models/llama3/test_vertex_ai_partner_models_llama3_transformation.py @@ -1,14 +1,9 @@ import json -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import httpx import pytest -sys.path.insert( - 0, os.path.abspath("../../../../../..") -) # Adds the parent directory to the system path from litellm.llms.vertex_ai.vertex_ai_partner_models.llama3.transformation import ( VertexAILlama3Config, diff --git a/tests/test_litellm/llms/vertex_ai/vertex_ai_partner_models/qwen/test_vertex_ai_qwen_global_endpoint.py b/tests/test_litellm/llms/vertex_ai/vertex_ai_partner_models/qwen/test_vertex_ai_qwen_global_endpoint.py index 5a86325b7fd..4a11c84a96d 100644 --- a/tests/test_litellm/llms/vertex_ai/vertex_ai_partner_models/qwen/test_vertex_ai_qwen_global_endpoint.py +++ b/tests/test_litellm/llms/vertex_ai/vertex_ai_partner_models/qwen/test_vertex_ai_qwen_global_endpoint.py @@ -8,14 +8,10 @@ These tests verify that: """ import os -import sys from unittest.mock import MagicMock, patch, AsyncMock import pytest -sys.path.insert( - 0, os.path.abspath("../../../../../..") -) # Adds the parent directory to the system path import litellm from litellm.llms.vertex_ai.vertex_llm_base import VertexBase diff --git a/tests/test_litellm/llms/volcengine/responses/test_volcengine_responses_transformation.py b/tests/test_litellm/llms/volcengine/responses/test_volcengine_responses_transformation.py index 7922331d19f..d42bf7b7a1c 100644 --- a/tests/test_litellm/llms/volcengine/responses/test_volcengine_responses_transformation.py +++ b/tests/test_litellm/llms/volcengine/responses/test_volcengine_responses_transformation.py @@ -2,15 +2,12 @@ Tests for Volcengine Responses API transformation. """ -import os -import sys from typing import List, Literal, Optional, Union import httpx import pytest from pydantic import BaseModel, Field -sys.path.insert(0, os.path.abspath("../../../../..")) import litellm from litellm.llms.volcengine.responses.transformation import ( diff --git a/tests/test_litellm/llms/volcengine/test_volcengine_embedding.py b/tests/test_litellm/llms/volcengine/test_volcengine_embedding.py index 1670dac0e9d..0122bc50695 100644 --- a/tests/test_litellm/llms/volcengine/test_volcengine_embedding.py +++ b/tests/test_litellm/llms/volcengine/test_volcengine_embedding.py @@ -3,13 +3,10 @@ Integration tests for Volcengine embedding following LiteLLM testing patterns Based on the BaseLLMEmbeddingTest framework """ -import os -import sys from unittest.mock import MagicMock, patch import pytest # Add parent directory to path for imports -sys.path.insert(0, os.path.abspath("../../../../..")) from tests.llm_translation.base_embedding_unit_tests import BaseLLMEmbeddingTest import litellm @@ -31,7 +28,6 @@ class TestVolcEngineEmbedding(BaseLLMEmbeddingTest): @pytest.mark.parametrize("sync_mode", [True, False]) async def test_basic_embedding(self, sync_mode): """Test basic embedding functionality with realistic response""" - litellm.set_verbose = True embedding_call_args = self.get_base_embedding_call_args() # Mock the embedding functions to avoid actual API calls diff --git a/tests/test_litellm/llms/wandb/test_wandb_chat_transformation.py b/tests/test_litellm/llms/wandb/test_wandb_chat_transformation.py index ef7bb0e44f0..a5d1eccebe0 100644 --- a/tests/test_litellm/llms/wandb/test_wandb_chat_transformation.py +++ b/tests/test_litellm/llms/wandb/test_wandb_chat_transformation.py @@ -5,12 +5,7 @@ These tests validate the WandbInferenceConfig class which extends OpenAIGPTConfi Nebius AI Studio is an OpenAI-compatible provider with minor customizations. """ -import os -import sys -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path import pytest diff --git a/tests/test_litellm/llms/watsonx/audio_transcription/test_watsonx_audio_transcription_transformation.py b/tests/test_litellm/llms/watsonx/audio_transcription/test_watsonx_audio_transcription_transformation.py index 6ff53287e9d..e269e782061 100644 --- a/tests/test_litellm/llms/watsonx/audio_transcription/test_watsonx_audio_transcription_transformation.py +++ b/tests/test_litellm/llms/watsonx/audio_transcription/test_watsonx_audio_transcription_transformation.py @@ -5,13 +5,10 @@ Validates that litellm.transcription transforms requests correctly for WatsonX. """ import json -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) import litellm from litellm.llms.watsonx.audio_transcription.transformation import ( diff --git a/tests/test_litellm/llms/watsonx/embed/test_watsonx_embedding_transformation.py b/tests/test_litellm/llms/watsonx/embed/test_watsonx_embedding_transformation.py index 5c2688620d4..58f6bb23498 100644 --- a/tests/test_litellm/llms/watsonx/embed/test_watsonx_embedding_transformation.py +++ b/tests/test_litellm/llms/watsonx/embed/test_watsonx_embedding_transformation.py @@ -1,7 +1,4 @@ -import os -import sys -sys.path.insert(0, os.path.abspath("../../../../..")) import pytest diff --git a/tests/test_litellm/llms/watsonx/passthrough/test_watsonx_passthrough_transformation.py b/tests/test_litellm/llms/watsonx/passthrough/test_watsonx_passthrough_transformation.py index d1db04f5215..d8976d19f5c 100644 --- a/tests/test_litellm/llms/watsonx/passthrough/test_watsonx_passthrough_transformation.py +++ b/tests/test_litellm/llms/watsonx/passthrough/test_watsonx_passthrough_transformation.py @@ -5,14 +5,11 @@ Tests the Watsonx-specific passthrough configuration including URL construction, streaming detection, and authentication handling. """ -import os -import sys from unittest.mock import MagicMock, patch import httpx import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) import litellm from litellm.llms.watsonx.passthrough.transformation import WatsonxPassthroughConfig diff --git a/tests/test_litellm/llms/watsonx/test_watsonx.py b/tests/test_litellm/llms/watsonx/test_watsonx.py index 315ffdb45a9..8ac4472b22d 100644 --- a/tests/test_litellm/llms/watsonx/test_watsonx.py +++ b/tests/test_litellm/llms/watsonx/test_watsonx.py @@ -1,10 +1,5 @@ import json -import os -import sys -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path from typing import Optional from unittest.mock import Mock, patch diff --git a/tests/test_litellm/llms/watsonx/test_watsonx_common_utils.py b/tests/test_litellm/llms/watsonx/test_watsonx_common_utils.py index be74dc40eda..ffc48ecfae9 100644 --- a/tests/test_litellm/llms/watsonx/test_watsonx_common_utils.py +++ b/tests/test_litellm/llms/watsonx/test_watsonx_common_utils.py @@ -1,12 +1,7 @@ -import os -import sys from unittest.mock import MagicMock, call, patch import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from litellm.llms.watsonx.common_utils import generate_iam_token diff --git a/tests/test_litellm/llms/xai/responses/test_xai_responses_transformation.py b/tests/test_litellm/llms/xai/responses/test_xai_responses_transformation.py index 871613c9c9a..befd4c5ffbd 100644 --- a/tests/test_litellm/llms/xai/responses/test_xai_responses_transformation.py +++ b/tests/test_litellm/llms/xai/responses/test_xai_responses_transformation.py @@ -7,11 +7,8 @@ transformations for the Responses API. Source: litellm/llms/xai/responses/transformation.py """ -import os -import sys from unittest.mock import MagicMock -sys.path.insert(0, os.path.abspath("../../../../..")) import pytest diff --git a/tests/test_litellm/llms/xai/test_xai_chat_transformation.py b/tests/test_litellm/llms/xai/test_xai_chat_transformation.py index eac5b89e4f3..e5e853ec82f 100644 --- a/tests/test_litellm/llms/xai/test_xai_chat_transformation.py +++ b/tests/test_litellm/llms/xai/test_xai_chat_transformation.py @@ -1,9 +1,4 @@ -import os -import sys -sys.path.insert( - 0, os.path.abspath("../../../..") -) # Adds the parent directory to the system path import pytest diff --git a/tests/test_litellm/llms/xai/test_xai_cost_calculator.py b/tests/test_litellm/llms/xai/test_xai_cost_calculator.py index b3855202ae0..55e28dff81d 100644 --- a/tests/test_litellm/llms/xai/test_xai_cost_calculator.py +++ b/tests/test_litellm/llms/xai/test_xai_cost_calculator.py @@ -4,7 +4,6 @@ Test suite for XAI cost calculation functionality. import math import os -import sys import litellm from litellm.types.utils import ( @@ -13,9 +12,6 @@ from litellm.types.utils import ( Usage, ) -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from litellm.litellm_core_utils.llm_cost_calc.tool_call_cost_tracking import ( StandardBuiltInToolCostTracking, diff --git a/tests/test_litellm/llms/xai/test_xai_key_fallback.py b/tests/test_litellm/llms/xai/test_xai_key_fallback.py index ec3eb83309c..092e4951547 100644 --- a/tests/test_litellm/llms/xai/test_xai_key_fallback.py +++ b/tests/test_litellm/llms/xai/test_xai_key_fallback.py @@ -1,10 +1,5 @@ import asyncio -import os -import sys -sys.path.insert( - 0, os.path.abspath("../../../..") -) # Adds the parent directory to the system path import pytest diff --git a/tests/test_litellm/llms/xai/xai_responses/test_transformation.py b/tests/test_litellm/llms/xai/xai_responses/test_transformation.py index dc535cf709b..c783918ca06 100644 --- a/tests/test_litellm/llms/xai/xai_responses/test_transformation.py +++ b/tests/test_litellm/llms/xai/xai_responses/test_transformation.py @@ -7,10 +7,7 @@ transformations for the Responses API. Source: litellm/llms/xai/responses/transformation.py """ -import sys -import os -sys.path.insert(0, os.path.abspath("../../../../..")) import pytest from litellm.types.utils import LlmProviders diff --git a/tests/test_litellm/llms/you_com/test_you_com_search.py b/tests/test_litellm/llms/you_com/test_you_com_search.py index eacc495cede..13d1be6062f 100644 --- a/tests/test_litellm/llms/you_com/test_you_com_search.py +++ b/tests/test_litellm/llms/you_com/test_you_com_search.py @@ -2,12 +2,9 @@ Tests for You.com Search API integration. """ -import os -import sys import pytest from unittest.mock import AsyncMock, patch, MagicMock -sys.path.insert(0, os.path.abspath("../..")) import litellm diff --git a/tests/test_litellm/passthrough/test_passthrough_main.py b/tests/test_litellm/passthrough/test_passthrough_main.py index e43e4be8bcc..b8f265ad7ea 100644 --- a/tests/test_litellm/passthrough/test_passthrough_main.py +++ b/tests/test_litellm/passthrough/test_passthrough_main.py @@ -1,6 +1,4 @@ import json -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import httpx @@ -9,9 +7,6 @@ from fastapi.testclient import TestClient from litellm.llms.custom_httpx.http_handler import AsyncHTTPHandler, HTTPHandler -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path diff --git a/tests/test_litellm/proxy/_experimental/mcp_server/auth/test_user_api_key_auth_mcp.py b/tests/test_litellm/proxy/_experimental/mcp_server/auth/test_user_api_key_auth_mcp.py index 17c4d773981..697c9b018ec 100644 --- a/tests/test_litellm/proxy/_experimental/mcp_server/auth/test_user_api_key_auth_mcp.py +++ b/tests/test_litellm/proxy/_experimental/mcp_server/auth/test_user_api_key_auth_mcp.py @@ -1,7 +1,6 @@ import contextlib import json import os -import sys from datetime import datetime, timedelta, timezone from unittest.mock import AsyncMock, MagicMock, patch @@ -9,7 +8,6 @@ import pytest from fastapi import HTTPException from fastapi.testclient import TestClient -sys.path.insert(0, os.path.abspath("../../../..")) # Adds the parent directory to the system path from starlette.datastructures import Headers @@ -6240,7 +6238,6 @@ class TestAggregateGatewayDcrChallenge: well_known_root_suffix), so a DCR client behind a sub-path is pointed at a route that exists instead of a 404. Regression: the challenge used to hard-code /mcp and omit the root path the route inserts.""" - import os with ( patch.dict(os.environ, {"SERVER_ROOT_PATH": "/litellm"}), @@ -6321,7 +6318,6 @@ class TestAggregateGatewayDcrChallenge: used to fail, silently pointing a legacy-spelling client at the standard-pattern document whose ``resource`` is ``{base}/mcp/{server}`` rather than the ``{base}/{server}/mcp`` URL it called, which a strict RFC 9728 section 3 client rejects.""" - import os from litellm.types.mcp import MCPAuth from litellm.types.mcp_server.mcp_server_manager import MCPServer diff --git a/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_cost_calculator.py b/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_cost_calculator.py index 4b9e7f2258b..5357e0dce9e 100644 --- a/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_cost_calculator.py +++ b/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_cost_calculator.py @@ -1,6 +1,4 @@ import json -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import orjson @@ -8,9 +6,6 @@ import pytest from fastapi import Request from fastapi.testclient import TestClient -sys.path.insert( - 0, os.path.abspath("../../../..") -) # Adds the parent directory to the system path from litellm.proxy._experimental.mcp_server.cost_calculator import MCPCostCalculator diff --git a/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_custom_fields.py b/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_custom_fields.py index 7a096fdc899..333d4c98899 100644 --- a/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_custom_fields.py +++ b/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_custom_fields.py @@ -5,13 +5,10 @@ Tests that mcp_info can accept arbitrary custom fields in addition to predefined """ import pytest -import sys -import os from unittest.mock import Mock, patch from typing import Dict, Any # Add the path to find the modules -sys.path.insert(0, os.path.abspath("../../../..")) # Adjust the path as needed from litellm.proxy._experimental.mcp_server.mcp_server_manager import MCPServerManager from litellm.types.mcp import MCPAuth diff --git a/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_discovery.py b/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_discovery.py index 9a741a3f861..43cf35c152d 100644 --- a/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_discovery.py +++ b/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_discovery.py @@ -1,12 +1,8 @@ import json import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../../../..") -) # Adds the parent directory to the system path class TestMCPRegistryFile: diff --git a/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_metadata_preservation.py b/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_metadata_preservation.py index 3182318caed..5a24ca00c25 100644 --- a/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_metadata_preservation.py +++ b/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_metadata_preservation.py @@ -5,12 +5,10 @@ This module tests that tool metadata is preserved when creating prefixed tools, which is critical for ChatGPT UI widget rendering. """ -import sys import pytest # Add the parent directory to the path so we can import litellm -sys.path.insert(0, "../../../../../") from mcp.types import Tool as MCPTool diff --git a/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_oauth_passthrough.py b/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_oauth_passthrough.py index fe583ace897..1c59b7b87e0 100644 --- a/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_oauth_passthrough.py +++ b/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_oauth_passthrough.py @@ -8,7 +8,6 @@ Covers: """ import asyncio -import sys import time from unittest.mock import AsyncMock, MagicMock, patch @@ -16,7 +15,6 @@ import httpx import pytest from fastapi import HTTPException, Request -sys.path.insert(0, "../../../../../") from litellm.proxy._experimental.mcp_server import discoverable_endpoints diff --git a/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_oauth_passthrough_cold_start.py b/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_oauth_passthrough_cold_start.py index f25d3baea0a..67663448d65 100644 --- a/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_oauth_passthrough_cold_start.py +++ b/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_oauth_passthrough_cold_start.py @@ -1,10 +1,8 @@ """Unit tests for MCP OAuth passthrough cold-start route behavior.""" -import sys import pytest -sys.path.insert(0, "../../../../../") from litellm.proxy._types import MCPTransport from litellm.types.mcp import MCPAuth diff --git a/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_oauth_passthrough_tools.py b/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_oauth_passthrough_tools.py index 095ae00fd45..6d66748bf3f 100644 --- a/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_oauth_passthrough_tools.py +++ b/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_oauth_passthrough_tools.py @@ -1,12 +1,10 @@ """Unit tests for MCP OAuth passthrough tool-fetch behavior.""" -import sys from unittest.mock import AsyncMock, MagicMock import httpx import pytest -sys.path.insert(0, "../../../../../") from litellm.proxy._experimental.mcp_server.exceptions import MCPUpstreamAuthError from litellm.proxy._experimental.mcp_server.mcp_server_manager import ( diff --git a/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_server_manager.py b/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_server_manager.py index 09e8c78a3f8..cdea803ebf3 100644 --- a/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_server_manager.py +++ b/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_server_manager.py @@ -18,7 +18,6 @@ from litellm.proxy._experimental.mcp_server.exceptions import ( from litellm.proxy._experimental.mcp_server.faults.list_outcomes import ServerListFault # Add the parent directory to the path so we can import litellm -sys.path.insert(0, "../../../../../") import httpx diff --git a/tests/test_litellm/proxy/_experimental/mcp_server/test_semantic_tool_filter.py b/tests/test_litellm/proxy/_experimental/mcp_server/test_semantic_tool_filter.py index 0b211255218..054146d474d 100644 --- a/tests/test_litellm/proxy/_experimental/mcp_server/test_semantic_tool_filter.py +++ b/tests/test_litellm/proxy/_experimental/mcp_server/test_semantic_tool_filter.py @@ -6,7 +6,6 @@ an ordered set of top K tools based on semantic similarity. """ import asyncio -import os import sys from unittest.mock import AsyncMock, Mock, patch @@ -15,7 +14,6 @@ import pytest if sys.version_info < (3, 11): # BaseExceptionGroup is a builtin only from 3.11 from exceptiongroup import BaseExceptionGroup -sys.path.insert(0, os.path.abspath("../..")) from mcp.types import Tool as MCPTool diff --git a/tests/test_litellm/proxy/agent_endpoints/auth/test_agent_permission_handler.py b/tests/test_litellm/proxy/agent_endpoints/auth/test_agent_permission_handler.py index 066d33dc187..82528c58ae0 100644 --- a/tests/test_litellm/proxy/agent_endpoints/auth/test_agent_permission_handler.py +++ b/tests/test_litellm/proxy/agent_endpoints/auth/test_agent_permission_handler.py @@ -4,14 +4,11 @@ Unit tests for AgentRequestHandler - Agent permission management for keys and te import hashlib import json -import os -import sys from typing import Final from unittest.mock import AsyncMock, patch import pytest -sys.path.insert(0, os.path.abspath("../../../..")) from litellm.proxy._types import UserAPIKeyAuth from litellm.proxy.agent_endpoints.agent_registry import AgentRegistry diff --git a/tests/test_litellm/proxy/agent_endpoints/test_model_list_helpers.py b/tests/test_litellm/proxy/agent_endpoints/test_model_list_helpers.py index ccf5942c89d..939ab1cab40 100644 --- a/tests/test_litellm/proxy/agent_endpoints/test_model_list_helpers.py +++ b/tests/test_litellm/proxy/agent_endpoints/test_model_list_helpers.py @@ -4,10 +4,7 @@ Test appending A2A agents to model lists. Maps to: litellm/proxy/agent_endpoints/model_list_helpers.py """ -import os -import sys -sys.path.insert(0, os.path.abspath("../../../..")) from unittest.mock import AsyncMock, Mock, patch diff --git a/tests/test_litellm/proxy/auth/test_admin_viewer_handler_access.py b/tests/test_litellm/proxy/auth/test_admin_viewer_handler_access.py index 36f656a7adc..2309b0a931f 100644 --- a/tests/test_litellm/proxy/auth/test_admin_viewer_handler_access.py +++ b/tests/test_litellm/proxy/auth/test_admin_viewer_handler_access.py @@ -11,15 +11,12 @@ The principle (see Admin Viewer role doc): anything Proxy Admin can read, Admin Viewer can read. No writes, no cost-incurring actions. """ -import os -import sys import types from unittest.mock import AsyncMock, MagicMock import pytest from fastapi.testclient import TestClient -sys.path.insert(0, os.path.abspath("../../../")) import litellm.proxy.proxy_server as ps from litellm.proxy._types import LitellmUserRoles, UserAPIKeyAuth diff --git a/tests/test_litellm/proxy/auth/test_auth_checks.py b/tests/test_litellm/proxy/auth/test_auth_checks.py index 762d2cbf3c7..a34df54adfa 100644 --- a/tests/test_litellm/proxy/auth/test_auth_checks.py +++ b/tests/test_litellm/proxy/auth/test_auth_checks.py @@ -1,7 +1,5 @@ import asyncio import json -import os -import sys from types import SimpleNamespace from typing import TYPE_CHECKING, Optional from unittest.mock import AsyncMock, MagicMock, patch @@ -9,9 +7,6 @@ from unittest.mock import AsyncMock, MagicMock, patch if TYPE_CHECKING: from litellm.router import Router -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from datetime import datetime, timedelta, timezone diff --git a/tests/test_litellm/proxy/auth/test_auth_exception_handler.py b/tests/test_litellm/proxy/auth/test_auth_exception_handler.py index 721857e5411..b0094b81112 100644 --- a/tests/test_litellm/proxy/auth/test_auth_exception_handler.py +++ b/tests/test_litellm/proxy/auth/test_auth_exception_handler.py @@ -1,7 +1,5 @@ import asyncio import json -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import httpx @@ -26,9 +24,6 @@ from prisma.errors import ( UniqueViolationError, ) -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from litellm._logging import verbose_proxy_logger from litellm.exceptions import BudgetExceededError diff --git a/tests/test_litellm/proxy/auth/test_auth_hot_path_network_requests.py b/tests/test_litellm/proxy/auth/test_auth_hot_path_network_requests.py index 6b2d2babedc..e3b76cac8ce 100644 --- a/tests/test_litellm/proxy/auth/test_auth_hot_path_network_requests.py +++ b/tests/test_litellm/proxy/auth/test_auth_hot_path_network_requests.py @@ -18,15 +18,12 @@ NOTE: This test does NOT require proxy extras (apscheduler, etc.) because it tests at the auth_checks level, not the full proxy_server level. """ -import os -import sys import time from typing import Any, Dict, List, Optional from unittest.mock import AsyncMock, MagicMock import pytest -sys.path.insert(0, os.path.abspath("../../..")) from litellm.caching.dual_cache import DualCache from litellm.caching.in_memory_cache import InMemoryCache diff --git a/tests/test_litellm/proxy/auth/test_litellm_license.py b/tests/test_litellm/proxy/auth/test_litellm_license.py index 77dd45046a0..8da365cb587 100644 --- a/tests/test_litellm/proxy/auth/test_litellm_license.py +++ b/tests/test_litellm/proxy/auth/test_litellm_license.py @@ -1,12 +1,7 @@ import asyncio import json -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from litellm.proxy.auth.litellm_license import LicenseCheck diff --git a/tests/test_litellm/proxy/auth/test_oauth2_proxy_hook.py b/tests/test_litellm/proxy/auth/test_oauth2_proxy_hook.py index 2d81d48de1e..315fc1471b3 100644 --- a/tests/test_litellm/proxy/auth/test_oauth2_proxy_hook.py +++ b/tests/test_litellm/proxy/auth/test_oauth2_proxy_hook.py @@ -13,14 +13,11 @@ constructs a ``UserAPIKeyAuth`` from them. The fix has two parts: ``"proxy_admin"`` into ``LitellmUserRoles.PROXY_ADMIN``. """ -import os -import sys import pytest from fastapi import Request from starlette.datastructures import Headers -sys.path.insert(0, os.path.abspath("../../../..")) from litellm.proxy._types import LitellmUserRoles from litellm.proxy.auth.oauth2_proxy_hook import ( diff --git a/tests/test_litellm/proxy/auth/test_object_permission_loading.py b/tests/test_litellm/proxy/auth/test_object_permission_loading.py index 0dfd82e0ea0..8db4e210107 100644 --- a/tests/test_litellm/proxy/auth/test_object_permission_loading.py +++ b/tests/test_litellm/proxy/auth/test_object_permission_loading.py @@ -2,13 +2,10 @@ Test that object_permission is automatically loaded when fetching keys and teams. """ -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import pytest -sys.path.insert(0, os.path.abspath("../../../..")) from litellm.proxy._types import ( LiteLLM_ObjectPermissionTable, diff --git a/tests/test_litellm/proxy/auth/test_organization_budget_enforcement.py b/tests/test_litellm/proxy/auth/test_organization_budget_enforcement.py index 45e24832274..3c8a793e957 100644 --- a/tests/test_litellm/proxy/auth/test_organization_budget_enforcement.py +++ b/tests/test_litellm/proxy/auth/test_organization_budget_enforcement.py @@ -10,14 +10,11 @@ organization's budget limit. """ import asyncio -import os -import sys from typing import Optional from unittest.mock import AsyncMock, MagicMock, patch import pytest -sys.path.insert(0, os.path.abspath("../../../")) import litellm from litellm.proxy._types import ( diff --git a/tests/test_litellm/proxy/auth/test_route_checks.py b/tests/test_litellm/proxy/auth/test_route_checks.py index b3b73723726..2eab03c2947 100644 --- a/tests/test_litellm/proxy/auth/test_route_checks.py +++ b/tests/test_litellm/proxy/auth/test_route_checks.py @@ -1,11 +1,7 @@ import os -import sys from datetime import datetime from unittest.mock import MagicMock, patch -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path import pytest from fastapi import HTTPException, Request diff --git a/tests/test_litellm/proxy/auth/test_user_api_key_auth.py b/tests/test_litellm/proxy/auth/test_user_api_key_auth.py index 043bbb5b76a..c1e235b77f6 100644 --- a/tests/test_litellm/proxy/auth/test_user_api_key_auth.py +++ b/tests/test_litellm/proxy/auth/test_user_api_key_auth.py @@ -1,15 +1,10 @@ import asyncio import json -import os -import sys from contextlib import contextmanager from datetime import datetime, timedelta from types import SimpleNamespace from unittest.mock import ANY, AsyncMock, MagicMock, patch -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path import pytest from fastapi import status diff --git a/tests/test_litellm/proxy/batches_endpoints/test_endpoints.py b/tests/test_litellm/proxy/batches_endpoints/test_endpoints.py index 863d9204cff..b548b0b3135 100644 --- a/tests/test_litellm/proxy/batches_endpoints/test_endpoints.py +++ b/tests/test_litellm/proxy/batches_endpoints/test_endpoints.py @@ -29,8 +29,6 @@ added to this layer raises instead of silently passing - the inventory of seams cannot drift without a test failure. """ -import os -import sys from contextlib import ExitStack from dataclasses import dataclass from typing import Any, Dict, Optional @@ -38,7 +36,6 @@ from unittest.mock import AsyncMock, MagicMock, patch import pytest -sys.path.insert(0, os.path.abspath("../../../..")) import litellm import litellm.proxy.batches_endpoints.endpoints as endpoints diff --git a/tests/test_litellm/proxy/client/cli/test_agents.py b/tests/test_litellm/proxy/client/cli/test_agents.py index e504dd6e8a0..32dfb8d521d 100644 --- a/tests/test_litellm/proxy/client/cli/test_agents.py +++ b/tests/test_litellm/proxy/client/cli/test_agents.py @@ -8,9 +8,6 @@ import pytest import requests from click.testing import CliRunner -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from litellm.proxy.client.cli.commands.agents import ( diff --git a/tests/test_litellm/proxy/client/cli/test_auth_commands.py b/tests/test_litellm/proxy/client/cli/test_auth_commands.py index be29269fe25..85a4d90abf9 100644 --- a/tests/test_litellm/proxy/client/cli/test_auth_commands.py +++ b/tests/test_litellm/proxy/client/cli/test_auth_commands.py @@ -1,12 +1,10 @@ import json import os import stat -import sys import time from pathlib import Path from unittest.mock import Mock, patch -sys.path.insert(0, os.path.abspath("../../..")) # Adds the parent directory to the system path import pytest diff --git a/tests/test_litellm/proxy/client/cli/test_config_commands.py b/tests/test_litellm/proxy/client/cli/test_config_commands.py index 6f3f4e4b268..611307635e0 100644 --- a/tests/test_litellm/proxy/client/cli/test_config_commands.py +++ b/tests/test_litellm/proxy/client/cli/test_config_commands.py @@ -1,14 +1,11 @@ import json -import os import stat -import sys from pathlib import Path from unittest.mock import patch import pytest from click.testing import CliRunner -sys.path.insert(0, os.path.abspath("../../..")) from litellm.proxy.client.cli import cli diff --git a/tests/test_litellm/proxy/client/cli/test_credentials_commands.py b/tests/test_litellm/proxy/client/cli/test_credentials_commands.py index c751bb675ce..fb9d749dd02 100644 --- a/tests/test_litellm/proxy/client/cli/test_credentials_commands.py +++ b/tests/test_litellm/proxy/client/cli/test_credentials_commands.py @@ -1,15 +1,10 @@ import json -import os -import sys from unittest.mock import MagicMock import pytest import requests from click.testing import CliRunner -sys.path.insert( - 0, os.path.abspath("../../../..") -) # Adds the parent directory to the system path from litellm.proxy.client.cli.main import cli diff --git a/tests/test_litellm/proxy/client/cli/test_global_options.py b/tests/test_litellm/proxy/client/cli/test_global_options.py index 9c6fc15b242..0dd388919a5 100644 --- a/tests/test_litellm/proxy/client/cli/test_global_options.py +++ b/tests/test_litellm/proxy/client/cli/test_global_options.py @@ -1,14 +1,12 @@ # stdlib imports import json import os -import sys from pathlib import Path from unittest.mock import Mock, patch import pytest from click.testing import CliRunner -sys.path.insert(0, os.path.abspath("../../..")) # Adds the parent directory to the system path import litellm.proxy.client.cli diff --git a/tests/test_litellm/proxy/client/cli/test_keys_commands.py b/tests/test_litellm/proxy/client/cli/test_keys_commands.py index 5d88b031eac..5cc0fb70881 100644 --- a/tests/test_litellm/proxy/client/cli/test_keys_commands.py +++ b/tests/test_litellm/proxy/client/cli/test_keys_commands.py @@ -1,13 +1,9 @@ import json import os -import sys from unittest.mock import patch import requests -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path import pytest diff --git a/tests/test_litellm/proxy/client/cli/test_models_commands.py b/tests/test_litellm/proxy/client/cli/test_models_commands.py index 7f47d14656a..80353955e7f 100644 --- a/tests/test_litellm/proxy/client/cli/test_models_commands.py +++ b/tests/test_litellm/proxy/client/cli/test_models_commands.py @@ -1,7 +1,6 @@ # stdlib imports import json import os -import sys import time from unittest.mock import patch @@ -10,9 +9,6 @@ import pytest # third party imports from click.testing import CliRunner -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path # local imports diff --git a/tests/test_litellm/proxy/client/cli/test_users_commands.py b/tests/test_litellm/proxy/client/cli/test_users_commands.py index f18ceb30c22..72539173318 100644 --- a/tests/test_litellm/proxy/client/cli/test_users_commands.py +++ b/tests/test_litellm/proxy/client/cli/test_users_commands.py @@ -1,13 +1,8 @@ -import os -import sys from unittest.mock import patch import pytest from click.testing import CliRunner -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from litellm.proxy.client.cli import cli diff --git a/tests/test_litellm/proxy/client/test_client.py b/tests/test_litellm/proxy/client/test_client.py index b0e458da89e..fe3e2c52ce5 100644 --- a/tests/test_litellm/proxy/client/test_client.py +++ b/tests/test_litellm/proxy/client/test_client.py @@ -1,11 +1,6 @@ -import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from litellm.proxy.client import ChatClient, Client, ModelsManagementClient from litellm.proxy.client.http_client import HTTPClient diff --git a/tests/test_litellm/proxy/client/test_credentials.py b/tests/test_litellm/proxy/client/test_credentials.py index 72c643467b2..41886e3b292 100644 --- a/tests/test_litellm/proxy/client/test_credentials.py +++ b/tests/test_litellm/proxy/client/test_credentials.py @@ -1,12 +1,7 @@ -import os -import sys import pytest import requests -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path import responses diff --git a/tests/test_litellm/proxy/client/test_http_client.py b/tests/test_litellm/proxy/client/test_http_client.py index 3d8fe44438a..c0f66b0f98e 100644 --- a/tests/test_litellm/proxy/client/test_http_client.py +++ b/tests/test_litellm/proxy/client/test_http_client.py @@ -1,15 +1,10 @@ """Tests for the HTTP client.""" import json -import os -import sys import pytest import requests -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path import responses diff --git a/tests/test_litellm/proxy/client/test_http_commands.py b/tests/test_litellm/proxy/client/test_http_commands.py index 16579cfffbc..04894248ff2 100644 --- a/tests/test_litellm/proxy/client/test_http_commands.py +++ b/tests/test_litellm/proxy/client/test_http_commands.py @@ -1,15 +1,10 @@ """Tests for the HTTP command group.""" import json -import os -import sys import pytest from click.testing import CliRunner -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path import responses diff --git a/tests/test_litellm/proxy/client/test_keys.py b/tests/test_litellm/proxy/client/test_keys.py index 620daefb39e..282b97b1c09 100644 --- a/tests/test_litellm/proxy/client/test_keys.py +++ b/tests/test_litellm/proxy/client/test_keys.py @@ -1,13 +1,8 @@ -import os -import sys import traceback import pytest import requests -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path import responses diff --git a/tests/test_litellm/proxy/client/test_model_groups.py b/tests/test_litellm/proxy/client/test_model_groups.py index 1c87672e723..9ea8e94ff95 100644 --- a/tests/test_litellm/proxy/client/test_model_groups.py +++ b/tests/test_litellm/proxy/client/test_model_groups.py @@ -1,12 +1,7 @@ -import os -import sys import pytest import requests -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path import responses diff --git a/tests/test_litellm/proxy/client/test_models.py b/tests/test_litellm/proxy/client/test_models.py index 33f963b74af..fe053ffd683 100644 --- a/tests/test_litellm/proxy/client/test_models.py +++ b/tests/test_litellm/proxy/client/test_models.py @@ -1,12 +1,7 @@ -import os -import sys import pytest import requests -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path import responses diff --git a/tests/test_litellm/proxy/client/test_users.py b/tests/test_litellm/proxy/client/test_users.py index a48cf8f791b..87b8392e402 100644 --- a/tests/test_litellm/proxy/client/test_users.py +++ b/tests/test_litellm/proxy/client/test_users.py @@ -1,12 +1,7 @@ -import os -import sys from unittest.mock import MagicMock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from litellm.proxy.client.users import ( diff --git a/tests/test_litellm/proxy/common_utils/html_forms/test_native_client_consent.py b/tests/test_litellm/proxy/common_utils/html_forms/test_native_client_consent.py index 600e421c176..6464dd7899a 100644 --- a/tests/test_litellm/proxy/common_utils/html_forms/test_native_client_consent.py +++ b/tests/test_litellm/proxy/common_utils/html_forms/test_native_client_consent.py @@ -1,7 +1,4 @@ -import os -import sys -sys.path.insert(0, os.path.abspath("../../../")) from litellm.constants import CLI_JWT_EXPIRATION_HOURS from litellm.proxy.common_utils.html_forms.native_client_consent import render_native_client_consent_page diff --git a/tests/test_litellm/proxy/common_utils/html_forms/test_ui_login.py b/tests/test_litellm/proxy/common_utils/html_forms/test_ui_login.py index 436564d24a0..1d4261d278c 100644 --- a/tests/test_litellm/proxy/common_utils/html_forms/test_ui_login.py +++ b/tests/test_litellm/proxy/common_utils/html_forms/test_ui_login.py @@ -1,7 +1,4 @@ -import os -import sys -sys.path.insert(0, os.path.abspath("../../../")) from litellm.proxy.common_utils.html_forms.ui_login import build_ui_login_form diff --git a/tests/test_litellm/proxy/common_utils/test_callback_utils.py b/tests/test_litellm/proxy/common_utils/test_callback_utils.py index 77ada4c11a9..66f77db6da9 100644 --- a/tests/test_litellm/proxy/common_utils/test_callback_utils.py +++ b/tests/test_litellm/proxy/common_utils/test_callback_utils.py @@ -1,13 +1,9 @@ import copy import sys -import os from types import ModuleType, SimpleNamespace import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from litellm.proxy.common_utils.callback_utils import ( add_guardrail_scan_id, diff --git a/tests/test_litellm/proxy/common_utils/test_expired_ui_session_key_cleanup_manager.py b/tests/test_litellm/proxy/common_utils/test_expired_ui_session_key_cleanup_manager.py index 3efeeee9a27..8623d93c0a3 100644 --- a/tests/test_litellm/proxy/common_utils/test_expired_ui_session_key_cleanup_manager.py +++ b/tests/test_litellm/proxy/common_utils/test_expired_ui_session_key_cleanup_manager.py @@ -2,15 +2,12 @@ Test expired UI session key cleanup manager functionality. """ -import os -import sys from datetime import datetime, timedelta, timezone from unittest.mock import AsyncMock, MagicMock, patch import pytest from fastapi import HTTPException, status -sys.path.insert(0, os.path.abspath("../../../..")) from litellm.constants import ( EXPIRED_UI_SESSION_KEY_CLEANUP_JOB_NAME, diff --git a/tests/test_litellm/proxy/common_utils/test_http_parsing_utils.py b/tests/test_litellm/proxy/common_utils/test_http_parsing_utils.py index 869d228d5a4..375c0d2640c 100644 --- a/tests/test_litellm/proxy/common_utils/test_http_parsing_utils.py +++ b/tests/test_litellm/proxy/common_utils/test_http_parsing_utils.py @@ -1,6 +1,4 @@ import json -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import orjson @@ -8,9 +6,6 @@ import pytest from fastapi import Request from fastapi.testclient import TestClient -sys.path.insert( - 0, os.path.abspath("../../../..") -) # Adds the parent directory to the system path import litellm diff --git a/tests/test_litellm/proxy/common_utils/test_key_rotation_e2e.py b/tests/test_litellm/proxy/common_utils/test_key_rotation_e2e.py index d6e1d22fdde..dd6c1637cad 100644 --- a/tests/test_litellm/proxy/common_utils/test_key_rotation_e2e.py +++ b/tests/test_litellm/proxy/common_utils/test_key_rotation_e2e.py @@ -11,7 +11,6 @@ Covers the critical gaps: """ import os -import sys from datetime import datetime, timedelta, timezone from typing import cast from unittest.mock import AsyncMock, MagicMock, patch @@ -19,7 +18,6 @@ from uuid import uuid4 import pytest -sys.path.insert(0, os.path.abspath("../../../..")) from litellm.proxy._types import ( GenerateKeyResponse, diff --git a/tests/test_litellm/proxy/common_utils/test_key_rotation_integration.py b/tests/test_litellm/proxy/common_utils/test_key_rotation_integration.py index 3bc62d549b0..6103a40d6c7 100644 --- a/tests/test_litellm/proxy/common_utils/test_key_rotation_integration.py +++ b/tests/test_litellm/proxy/common_utils/test_key_rotation_integration.py @@ -9,13 +9,10 @@ Bug Fixed: Key alias was not passed during auto-rotation, causing secrets to be created at a new location instead of updating in-place. """ -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import pytest -sys.path.insert(0, os.path.abspath("../../../..")) from litellm.proxy._types import ( GenerateKeyResponse, diff --git a/tests/test_litellm/proxy/common_utils/test_key_rotation_lock.py b/tests/test_litellm/proxy/common_utils/test_key_rotation_lock.py index c0b3611b2b4..27dc6ae6a5e 100644 --- a/tests/test_litellm/proxy/common_utils/test_key_rotation_lock.py +++ b/tests/test_litellm/proxy/common_utils/test_key_rotation_lock.py @@ -5,13 +5,10 @@ Verifies that PodLockManager is correctly used to prevent concurrent key rotation across multiple pods in a distributed deployment. """ -import os -import sys from unittest.mock import AsyncMock, MagicMock import pytest -sys.path.insert(0, os.path.abspath("../../../..")) from litellm.proxy._types import LiteLLM_VerificationToken from litellm.proxy.common_utils.key_rotation_manager import KeyRotationManager diff --git a/tests/test_litellm/proxy/common_utils/test_key_rotation_manager.py b/tests/test_litellm/proxy/common_utils/test_key_rotation_manager.py index 18432d106af..40a186a9059 100644 --- a/tests/test_litellm/proxy/common_utils/test_key_rotation_manager.py +++ b/tests/test_litellm/proxy/common_utils/test_key_rotation_manager.py @@ -2,14 +2,11 @@ Test key rotation manager functionality """ -import os -import sys from datetime import datetime, timedelta, timezone from unittest.mock import AsyncMock import pytest -sys.path.insert(0, os.path.abspath("../../../..")) from litellm.proxy._types import ( GenerateKeyResponse, diff --git a/tests/test_litellm/proxy/common_utils/test_model_deprecation.py b/tests/test_litellm/proxy/common_utils/test_model_deprecation.py index 051ddd2e78c..91055dbac9f 100644 --- a/tests/test_litellm/proxy/common_utils/test_model_deprecation.py +++ b/tests/test_litellm/proxy/common_utils/test_model_deprecation.py @@ -4,13 +4,10 @@ These tests focus on the helper itself — not on the proxy endpoint or Slack integration — so they can run without the full proxy stack. """ -import os -import sys from datetime import date, datetime, timezone from unittest.mock import MagicMock -sys.path.insert(0, os.path.abspath("../../../..")) import litellm from litellm.proxy.common_utils.model_deprecation import ( diff --git a/tests/test_litellm/proxy/common_utils/test_reset_budget_job.py b/tests/test_litellm/proxy/common_utils/test_reset_budget_job.py index 8233b0d3864..25c177a308d 100644 --- a/tests/test_litellm/proxy/common_utils/test_reset_budget_job.py +++ b/tests/test_litellm/proxy/common_utils/test_reset_budget_job.py @@ -1,6 +1,5 @@ import asyncio import json -import os import sys import types from datetime import datetime, timedelta, timezone @@ -12,7 +11,6 @@ import httpx import prisma import pytest -sys.path.insert(0, os.path.abspath("../../..")) # Adds the parent directory to the system path from litellm.proxy._types import LiteLLM_VerificationToken from litellm.proxy.common_utils import reset_budget_job as reset_budget_job_module diff --git a/tests/test_litellm/proxy/common_utils/test_static_asset_utils.py b/tests/test_litellm/proxy/common_utils/test_static_asset_utils.py index 93f7ccc92c2..593158515a5 100644 --- a/tests/test_litellm/proxy/common_utils/test_static_asset_utils.py +++ b/tests/test_litellm/proxy/common_utils/test_static_asset_utils.py @@ -7,11 +7,9 @@ arbitrary local image paths working while refusing non-image files like """ import os -import sys import pytest -sys.path.insert(0, os.path.abspath("../../../..")) from litellm.proxy.common_utils.static_asset_utils import ( detect_local_image_media_type, diff --git a/tests/test_litellm/proxy/common_utils/test_timezone_utils.py b/tests/test_litellm/proxy/common_utils/test_timezone_utils.py index dc3917cb48e..0ae74ab6f59 100644 --- a/tests/test_litellm/proxy/common_utils/test_timezone_utils.py +++ b/tests/test_litellm/proxy/common_utils/test_timezone_utils.py @@ -1,13 +1,8 @@ -import os -import sys from datetime import datetime, time, timezone from zoneinfo import ZoneInfo import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path import litellm from litellm.proxy.common_utils.timezone_utils import ( diff --git a/tests/test_litellm/proxy/credential_endpoints/test_endpoints.py b/tests/test_litellm/proxy/credential_endpoints/test_endpoints.py index e2fa1de6962..dcd8e6881bd 100644 --- a/tests/test_litellm/proxy/credential_endpoints/test_endpoints.py +++ b/tests/test_litellm/proxy/credential_endpoints/test_endpoints.py @@ -1,13 +1,10 @@ """Tests for the credential management endpoints.""" -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import pytest from fastapi.testclient import TestClient -sys.path.insert(0, os.path.abspath("../../../..")) from litellm.proxy._types import UserAPIKeyAuth from litellm.proxy.auth.user_api_key_auth import user_api_key_auth diff --git a/tests/test_litellm/proxy/db/db_transaction_queue/test_base_update_queue.py b/tests/test_litellm/proxy/db/db_transaction_queue/test_base_update_queue.py index f357d7fbea8..abb79458318 100644 --- a/tests/test_litellm/proxy/db/db_transaction_queue/test_base_update_queue.py +++ b/tests/test_litellm/proxy/db/db_transaction_queue/test_base_update_queue.py @@ -1,15 +1,10 @@ import asyncio import json -import os -import sys from unittest.mock import patch import pytest from fastapi.testclient import TestClient -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from litellm.constants import MAX_IN_MEMORY_QUEUE_FLUSH_COUNT from litellm.proxy.db.db_transaction_queue.base_update_queue import BaseUpdateQueue diff --git a/tests/test_litellm/proxy/db/db_transaction_queue/test_daily_spend_update_queue.py b/tests/test_litellm/proxy/db/db_transaction_queue/test_daily_spend_update_queue.py index a55d4f0dcfd..a00815345aa 100644 --- a/tests/test_litellm/proxy/db/db_transaction_queue/test_daily_spend_update_queue.py +++ b/tests/test_litellm/proxy/db/db_transaction_queue/test_daily_spend_update_queue.py @@ -1,14 +1,9 @@ import asyncio import json -import os -import sys import pytest from fastapi.testclient import TestClient -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path import litellm from litellm.constants import MAX_SIZE_IN_MEMORY_QUEUE from litellm.proxy._types import ( diff --git a/tests/test_litellm/proxy/db/db_transaction_queue/test_pod_lock_manager.py b/tests/test_litellm/proxy/db/db_transaction_queue/test_pod_lock_manager.py index 7a1ab60c547..ecd5c5f50c0 100644 --- a/tests/test_litellm/proxy/db/db_transaction_queue/test_pod_lock_manager.py +++ b/tests/test_litellm/proxy/db/db_transaction_queue/test_pod_lock_manager.py @@ -1,13 +1,10 @@ import json -import os -import sys from datetime import datetime, timedelta, timezone from unittest.mock import AsyncMock, MagicMock, patch import pytest from fastapi.testclient import TestClient -sys.path.insert(0, os.path.abspath("../../..")) # Adds the parent directory to the system path from litellm.constants import DEFAULT_CRON_JOB_LOCK_TTL_SECONDS from litellm.proxy.db.db_transaction_queue.pod_lock_manager import PodLockManager diff --git a/tests/test_litellm/proxy/db/db_transaction_queue/test_redis_update_buffer.py b/tests/test_litellm/proxy/db/db_transaction_queue/test_redis_update_buffer.py index 3325893c5f6..fb0c994a476 100644 --- a/tests/test_litellm/proxy/db/db_transaction_queue/test_redis_update_buffer.py +++ b/tests/test_litellm/proxy/db/db_transaction_queue/test_redis_update_buffer.py @@ -1,13 +1,8 @@ import json -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path from litellm.proxy.db.db_transaction_queue.redis_update_buffer import RedisUpdateBuffer from litellm.proxy.proxy_server import ProxyStartupEvent diff --git a/tests/test_litellm/proxy/db/db_transaction_queue/test_spend_update_queue.py b/tests/test_litellm/proxy/db/db_transaction_queue/test_spend_update_queue.py index 0ed5940dd75..43f1a820885 100644 --- a/tests/test_litellm/proxy/db/db_transaction_queue/test_spend_update_queue.py +++ b/tests/test_litellm/proxy/db/db_transaction_queue/test_spend_update_queue.py @@ -1,7 +1,5 @@ import asyncio import json -import os -import sys import pytest from fastapi.testclient import TestClient @@ -10,9 +8,6 @@ from litellm.constants import MAX_SIZE_IN_MEMORY_QUEUE from litellm.proxy._types import Litellm_EntityType, SpendUpdateQueueItem from litellm.proxy.db.db_transaction_queue.spend_update_queue import SpendUpdateQueue -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path @pytest.fixture diff --git a/tests/test_litellm/proxy/db/db_transaction_queue/test_tool_discovery_queue.py b/tests/test_litellm/proxy/db/db_transaction_queue/test_tool_discovery_queue.py index defdb3834d8..e400ad16e84 100644 --- a/tests/test_litellm/proxy/db/db_transaction_queue/test_tool_discovery_queue.py +++ b/tests/test_litellm/proxy/db/db_transaction_queue/test_tool_discovery_queue.py @@ -2,12 +2,9 @@ Unit tests for ToolDiscoveryQueue. """ -import os -import sys import pytest -sys.path.insert(0, os.path.abspath("../../..")) from litellm.proxy.db.db_transaction_queue.tool_discovery_queue import ( ToolDiscoveryQueue, diff --git a/tests/test_litellm/proxy/db/mcp_server/test_db.py b/tests/test_litellm/proxy/db/mcp_server/test_db.py index 481d1a864c0..aa40ec0d76c 100644 --- a/tests/test_litellm/proxy/db/mcp_server/test_db.py +++ b/tests/test_litellm/proxy/db/mcp_server/test_db.py @@ -1,13 +1,8 @@ -import os -import sys from types import SimpleNamespace from unittest.mock import AsyncMock, MagicMock import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from litellm.proxy._experimental.mcp_server.db import get_mcp_servers_by_team diff --git a/tests/test_litellm/proxy/db/test_check_migration.py b/tests/test_litellm/proxy/db/test_check_migration.py index 5b182f03c4b..9e2f6a1089c 100644 --- a/tests/test_litellm/proxy/db/test_check_migration.py +++ b/tests/test_litellm/proxy/db/test_check_migration.py @@ -1,11 +1,6 @@ -import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../../../..") -) # Adds the parent directory to the system path def test_check_migration_out_of_sync(mocker): diff --git a/tests/test_litellm/proxy/db/test_db_spend_update_writer.py b/tests/test_litellm/proxy/db/test_db_spend_update_writer.py index 4113d708196..76a80ac2651 100644 --- a/tests/test_litellm/proxy/db/test_db_spend_update_writer.py +++ b/tests/test_litellm/proxy/db/test_db_spend_update_writer.py @@ -1,13 +1,8 @@ import asyncio import copy import json -import os import re -import sys -sys.path.insert( - 0, os.path.abspath("../../../..") -) # Adds the parent directory to the system path from collections.abc import Callable diff --git a/tests/test_litellm/proxy/db/test_exception_handler.py b/tests/test_litellm/proxy/db/test_exception_handler.py index 4c6315024dd..d80e3acb4b8 100644 --- a/tests/test_litellm/proxy/db/test_exception_handler.py +++ b/tests/test_litellm/proxy/db/test_exception_handler.py @@ -1,6 +1,5 @@ import asyncio import json -import os import sys from unittest.mock import MagicMock, patch @@ -21,9 +20,6 @@ from prisma.errors import ( UniqueViolationError, ) -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path import litellm from litellm._logging import verbose_proxy_logger @@ -335,7 +331,6 @@ def test_is_database_service_unavailable_error_asyncpg(monkeypatch): """asyncpg connection/interface errors map to service-unavailable. asyncpg is not a hard dependency, so inject a stand-in module to exercise the branch deterministically regardless of the install environment.""" - import sys import types fake_asyncpg = types.ModuleType("asyncpg") diff --git a/tests/test_litellm/proxy/db/test_exception_handler_reconnect_retry.py b/tests/test_litellm/proxy/db/test_exception_handler_reconnect_retry.py index 0a25ed55e90..4286da23242 100644 --- a/tests/test_litellm/proxy/db/test_exception_handler_reconnect_retry.py +++ b/tests/test_litellm/proxy/db/test_exception_handler_reconnect_retry.py @@ -8,15 +8,12 @@ LiteLLM 1.83.x and started emitting `db_exceptions` alerts on transient `httpx.ReadError` flaps that used to self-heal in 1.82.6. """ -import os -import sys from unittest.mock import AsyncMock, MagicMock import httpx import pytest from prisma.errors import ClientNotConnectedError, UniqueViolationError -sys.path.insert(0, os.path.abspath("../../..")) from litellm.proxy.db.exception_handler import call_with_db_reconnect_retry diff --git a/tests/test_litellm/proxy/db/test_prisma_client.py b/tests/test_litellm/proxy/db/test_prisma_client.py index 395f17e85ef..b1ecbfeff8e 100644 --- a/tests/test_litellm/proxy/db/test_prisma_client.py +++ b/tests/test_litellm/proxy/db/test_prisma_client.py @@ -8,9 +8,6 @@ from unittest.mock import AsyncMock, MagicMock, Mock, patch import pytest from fastapi.testclient import TestClient -sys.path.insert( - 0, os.path.abspath("../../../..") -) # Adds the parent directory to the system path from litellm.proxy.db.prisma_client import PrismaWrapper, should_update_prisma_schema diff --git a/tests/test_litellm/proxy/db/test_prisma_planned_engine_restart.py b/tests/test_litellm/proxy/db/test_prisma_planned_engine_restart.py index 95e794012ec..f3f742b2023 100644 --- a/tests/test_litellm/proxy/db/test_prisma_planned_engine_restart.py +++ b/tests/test_litellm/proxy/db/test_prisma_planned_engine_restart.py @@ -40,9 +40,6 @@ import pytest from prisma import Prisma as GeneratedPrisma from prisma.engine.errors import EngineConnectionError -sys.path.insert( - 0, os.path.abspath("../../../..") -) # Adds the parent directory to the system path from litellm.proxy.db.prisma_client import PrismaWrapper from litellm.proxy.utils import PrismaClient diff --git a/tests/test_litellm/proxy/db/test_prisma_self_heal.py b/tests/test_litellm/proxy/db/test_prisma_self_heal.py index cc47cf4a7e4..10a48941693 100644 --- a/tests/test_litellm/proxy/db/test_prisma_self_heal.py +++ b/tests/test_litellm/proxy/db/test_prisma_self_heal.py @@ -8,9 +8,6 @@ from unittest.mock import AsyncMock, MagicMock, patch import httpx import pytest -sys.path.insert( - 0, os.path.abspath("../../../..") -) # Adds the parent directory to the system path from litellm.proxy.utils import PrismaClient, ProxyLogging diff --git a/tests/test_litellm/proxy/db/test_routing_prisma_wrapper.py b/tests/test_litellm/proxy/db/test_routing_prisma_wrapper.py index 11ed63cf8f0..dcc0036ff04 100644 --- a/tests/test_litellm/proxy/db/test_routing_prisma_wrapper.py +++ b/tests/test_litellm/proxy/db/test_routing_prisma_wrapper.py @@ -7,7 +7,6 @@ from unittest.mock import AsyncMock, MagicMock, patch import pytest -sys.path.insert(0, os.path.abspath("../../../..")) # NOTE: do NOT patch sys.modules["prisma"] file-wide via an autouse fixture. diff --git a/tests/test_litellm/proxy/db/test_tool_registry_writer.py b/tests/test_litellm/proxy/db/test_tool_registry_writer.py index 7bf1ffda4fe..6318e4422cf 100644 --- a/tests/test_litellm/proxy/db/test_tool_registry_writer.py +++ b/tests/test_litellm/proxy/db/test_tool_registry_writer.py @@ -3,14 +3,11 @@ Unit tests for tool_registry_writer.py — uses a mock prisma client that exposes litellm_tooltable.upsert / find_many / find_unique. """ -import os -import sys from datetime import datetime, timezone from unittest.mock import AsyncMock, MagicMock import pytest -sys.path.insert(0, os.path.abspath("../../..")) from litellm.proxy.db.tool_registry_writer import ( ToolPolicyRegistry, diff --git a/tests/test_litellm/proxy/discovery_endpoints/test_ui_discovery_endpoints.py b/tests/test_litellm/proxy/discovery_endpoints/test_ui_discovery_endpoints.py index 37f5e6046ca..f4da8c941a4 100644 --- a/tests/test_litellm/proxy/discovery_endpoints/test_ui_discovery_endpoints.py +++ b/tests/test_litellm/proxy/discovery_endpoints/test_ui_discovery_endpoints.py @@ -1,12 +1,10 @@ import os -import sys from unittest.mock import MagicMock, patch import pytest from fastapi import FastAPI from fastapi.testclient import TestClient -sys.path.insert(0, os.path.abspath("../../..")) from litellm.proxy.discovery_endpoints.ui_discovery_endpoints import router from litellm.types.proxy.control_plane_endpoints import WorkerRegistryEntry diff --git a/tests/test_litellm/proxy/experimental/mcp_server/test_tool_registry.py b/tests/test_litellm/proxy/experimental/mcp_server/test_tool_registry.py index d5ba9744c7d..9fc2e8744c1 100644 --- a/tests/test_litellm/proxy/experimental/mcp_server/test_tool_registry.py +++ b/tests/test_litellm/proxy/experimental/mcp_server/test_tool_registry.py @@ -1,12 +1,7 @@ import json -import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from litellm.proxy._experimental.mcp_server.tool_registry import MCPToolRegistry diff --git a/tests/test_litellm/proxy/fine_tuning_endpoints/test_endpoints.py b/tests/test_litellm/proxy/fine_tuning_endpoints/test_endpoints.py index b54787bf428..7ed1a436cb6 100644 --- a/tests/test_litellm/proxy/fine_tuning_endpoints/test_endpoints.py +++ b/tests/test_litellm/proxy/fine_tuning_endpoints/test_endpoints.py @@ -11,15 +11,12 @@ seam stayed untouched, so a guard that raises after the provider call would stil """ import base64 -import os -import sys from contextlib import ExitStack from dataclasses import dataclass from unittest.mock import AsyncMock, MagicMock, patch import pytest -sys.path.insert(0, os.path.abspath("../../../..")) from fastapi import Response diff --git a/tests/test_litellm/proxy/google_endpoints/test_endpoints.py b/tests/test_litellm/proxy/google_endpoints/test_endpoints.py index f3518999f72..92001118e2c 100644 --- a/tests/test_litellm/proxy/google_endpoints/test_endpoints.py +++ b/tests/test_litellm/proxy/google_endpoints/test_endpoints.py @@ -13,7 +13,6 @@ from starlette.requests import Request load_dotenv() -sys.path.insert(0, os.path.abspath("../../../..")) @pytest.mark.asyncio diff --git a/tests/test_litellm/proxy/google_endpoints/test_google_api_endpoints.py b/tests/test_litellm/proxy/google_endpoints/test_google_api_endpoints.py index 99f587e87a3..e4cd7d9dfa8 100644 --- a/tests/test_litellm/proxy/google_endpoints/test_google_api_endpoints.py +++ b/tests/test_litellm/proxy/google_endpoints/test_google_api_endpoints.py @@ -3,15 +3,10 @@ Test to verify the Google GenAI proxy API endpoints """ -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path def _build_test_client(): diff --git a/tests/test_litellm/proxy/guardrails/guardrail_hooks/_cisco_ai_defense_test_utils.py b/tests/test_litellm/proxy/guardrails/guardrail_hooks/_cisco_ai_defense_test_utils.py index 4f29d83d4a5..f09135dd56d 100644 --- a/tests/test_litellm/proxy/guardrails/guardrail_hooks/_cisco_ai_defense_test_utils.py +++ b/tests/test_litellm/proxy/guardrails/guardrail_hooks/_cisco_ai_defense_test_utils.py @@ -1,6 +1,5 @@ import json import os -import sys from contextlib import contextmanager from datetime import datetime from types import SimpleNamespace @@ -39,7 +38,6 @@ def _make_model_response_with_content(content: str) -> ModelResponse: ) -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm import DualCache from litellm.proxy._types import UserAPIKeyAuth diff --git a/tests/test_litellm/proxy/guardrails/guardrail_hooks/content_filter/test_content_filter.py b/tests/test_litellm/proxy/guardrails/guardrail_hooks/content_filter/test_content_filter.py index 62d25f1b9c0..be55ac47bde 100644 --- a/tests/test_litellm/proxy/guardrails/guardrail_hooks/content_filter/test_content_filter.py +++ b/tests/test_litellm/proxy/guardrails/guardrail_hooks/content_filter/test_content_filter.py @@ -4,14 +4,10 @@ Tests for the Content Filter Guardrail import json import os -import sys from unittest.mock import MagicMock import pytest -sys.path.insert( - 0, os.path.abspath("../../") -) # Adds the parent directory to the system path from fastapi import HTTPException diff --git a/tests/test_litellm/proxy/guardrails/guardrail_hooks/content_filter/test_gdpr_policy_e2e.py b/tests/test_litellm/proxy/guardrails/guardrail_hooks/content_filter/test_gdpr_policy_e2e.py index 238331b32c8..4af9bd99ed1 100644 --- a/tests/test_litellm/proxy/guardrails/guardrail_hooks/content_filter/test_gdpr_policy_e2e.py +++ b/tests/test_litellm/proxy/guardrails/guardrail_hooks/content_filter/test_gdpr_policy_e2e.py @@ -3,12 +3,9 @@ End-to-end tests for GDPR Art. 32 EU PII Protection policy template Tests the complete policy with various EU PII patterns """ -import os -import sys import pytest -sys.path.insert(0, os.path.abspath("../../")) from litellm.proxy.guardrails.guardrail_hooks.litellm_content_filter.content_filter import ( ContentFilterGuardrail, diff --git a/tests/test_litellm/proxy/guardrails/guardrail_hooks/content_filter/test_patterns.py b/tests/test_litellm/proxy/guardrails/guardrail_hooks/content_filter/test_patterns.py index c942e5fe820..d702b9e0116 100644 --- a/tests/test_litellm/proxy/guardrails/guardrail_hooks/content_filter/test_patterns.py +++ b/tests/test_litellm/proxy/guardrails/guardrail_hooks/content_filter/test_patterns.py @@ -4,11 +4,9 @@ Tests for content filter pattern loading from JSON import json import os -import sys import pytest -sys.path.insert(0, os.path.abspath("../../")) from litellm.proxy.guardrails.guardrail_hooks.litellm_content_filter.patterns import ( PATTERN_CATEGORIES, diff --git a/tests/test_litellm/proxy/guardrails/guardrail_hooks/openai/test_moderations.py b/tests/test_litellm/proxy/guardrails/guardrail_hooks/openai/test_moderations.py index 729dcb54309..112bc5e6e49 100644 --- a/tests/test_litellm/proxy/guardrails/guardrail_hooks/openai/test_moderations.py +++ b/tests/test_litellm/proxy/guardrails/guardrail_hooks/openai/test_moderations.py @@ -4,9 +4,7 @@ Test OpenAI Moderation Guardrail """ import os -import sys -sys.path.insert(0, os.path.abspath("../../../../../..")) from unittest.mock import MagicMock, patch diff --git a/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_bedrock_guardrails.py b/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_bedrock_guardrails.py index 5d971bf1212..dd339d4e51f 100644 --- a/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_bedrock_guardrails.py +++ b/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_bedrock_guardrails.py @@ -3,7 +3,6 @@ Unit tests for Bedrock Guardrails """ import json -import os import sys from unittest.mock import AsyncMock, MagicMock, patch @@ -11,7 +10,6 @@ import httpx import pytest from fastapi import HTTPException -sys.path.insert(0, os.path.abspath("../../../../../..")) import litellm from litellm.caching.caching import DualCache diff --git a/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_bedrock_invoke_guardrail_checks.py b/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_bedrock_invoke_guardrail_checks.py index ceb59571389..d842a1ee5f9 100644 --- a/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_bedrock_invoke_guardrail_checks.py +++ b/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_bedrock_invoke_guardrail_checks.py @@ -6,14 +6,11 @@ All Bedrock HTTP calls are mocked; no real AWS calls are made. import json import logging -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import pytest from fastapi import HTTPException -sys.path.insert(0, os.path.abspath("../../../../../..")) from litellm.exceptions import ModifyResponseException from litellm.proxy.guardrails.guardrail_hooks.bedrock_guardrails import ( diff --git a/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_cato_networks.py b/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_cato_networks.py index c23fbc0234e..d319d619ff7 100644 --- a/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_cato_networks.py +++ b/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_cato_networks.py @@ -1,8 +1,6 @@ import asyncio import json -import os import ssl -import sys from unittest.mock import AsyncMock, MagicMock, patch import pytest @@ -18,15 +16,11 @@ from litellm.proxy.guardrails.guardrail_hooks.cato_networks.cato_networks import from litellm.proxy.proxy_server import UserAPIKeyAuth from litellm.types.utils import ModelResponse, ResponsesAPIResponse -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm.proxy.guardrails.init_guardrails import init_guardrails_v2 def test_cato_guard_config(): - litellm.set_verbose = True litellm.guardrail_name_config_map = {} init_guardrails_v2( @@ -47,7 +41,6 @@ def test_cato_guard_config(): def test_cato_guard_config_no_api_key(monkeypatch): monkeypatch.delenv("CATO_API_KEY", raising=False) - litellm.set_verbose = True litellm.guardrail_name_config_map = {} with pytest.raises(CatoNetworksGuardrailMissingSecrets, match="Couldn't get Cato Networks api key"): init_guardrails_v2( diff --git a/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_cisco_ai_defense_chat.py b/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_cisco_ai_defense_chat.py index 8974a18593b..779075a40d9 100644 --- a/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_cisco_ai_defense_chat.py +++ b/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_cisco_ai_defense_chat.py @@ -44,7 +44,6 @@ from tests.test_litellm.proxy.guardrails.guardrail_hooks._cisco_ai_defense_test_ def test_cisco_ai_defense_config_via_init_v2_chat(monkeypatch): monkeypatch.setenv("CISCO_AI_DEFENSE_API_KEY", "test-key") - litellm.set_verbose = True litellm.guardrail_name_config_map = {} init_guardrails_v2( diff --git a/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_lasso.py b/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_lasso.py index dcb004e5422..870c5e6d4a0 100644 --- a/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_lasso.py +++ b/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_lasso.py @@ -1,12 +1,10 @@ import os -import sys import pytest import uuid from unittest.mock import patch, MagicMock from httpx import Response, Request from fastapi import HTTPException -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm import DualCache diff --git a/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_mcp_end_user_permission.py b/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_mcp_end_user_permission.py index 713f089e158..596c11908cb 100644 --- a/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_mcp_end_user_permission.py +++ b/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_mcp_end_user_permission.py @@ -2,15 +2,10 @@ Tests for MCP End User Permission Guardrail Hook """ -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../../../..") -) # Adds the parent directory to the system path from litellm.exceptions import GuardrailRaisedException from litellm.proxy._types import UserAPIKeyAuth diff --git a/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_model_armor.py b/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_model_armor.py index 613cbbce8b4..da66c36328e 100644 --- a/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_model_armor.py +++ b/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_model_armor.py @@ -2,13 +2,10 @@ import asyncio import base64 import io import json -import os -import sys from unittest.mock import AsyncMock, MagicMock, Mock, patch import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) import httpx from fastapi import HTTPException diff --git a/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_presidio.py b/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_presidio.py index c779150ad3e..60be3be5e8b 100644 --- a/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_presidio.py +++ b/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_presidio.py @@ -4,14 +4,11 @@ Tests PII detection and masking for different message formats """ import asyncio -import os -import sys from contextlib import asynccontextmanager from unittest.mock import MagicMock, patch import pytest -sys.path.insert(0, os.path.abspath("../../../../../..")) import litellm from litellm.caching.caching import DualCache diff --git a/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_tool_permission.py b/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_tool_permission.py index 0c5addbc143..0dbd4591ac9 100644 --- a/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_tool_permission.py +++ b/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_tool_permission.py @@ -3,16 +3,13 @@ Unit tests for Tool Permission Guardrail (OpenAI tool_calls semantics) """ import json -import os import re -import sys from unittest.mock import patch import pytest from litellm.caching.dual_cache import DualCache -sys.path.insert(0, os.path.abspath("../../../../../..")) from fastapi import HTTPException diff --git a/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_tool_policy_guardrail.py b/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_tool_policy_guardrail.py index 8b9b6820e8c..9113ac5015f 100644 --- a/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_tool_policy_guardrail.py +++ b/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_tool_policy_guardrail.py @@ -2,15 +2,12 @@ Unit tests for ToolPolicyGuardrail. """ -import os -import sys from typing import Any from unittest.mock import AsyncMock, MagicMock, patch import pytest from fastapi import HTTPException -sys.path.insert(0, os.path.abspath("../../../../../..")) from litellm.proxy.guardrails.guardrail_hooks.tool_policy.tool_policy_guardrail import ( ToolPolicyGuardrail, diff --git a/tests/test_litellm/proxy/guardrails/test_deferred_guardrail_logging.py b/tests/test_litellm/proxy/guardrails/test_deferred_guardrail_logging.py index 291ce732fc6..e70fc61de30 100644 --- a/tests/test_litellm/proxy/guardrails/test_deferred_guardrail_logging.py +++ b/tests/test_litellm/proxy/guardrails/test_deferred_guardrail_logging.py @@ -15,14 +15,11 @@ Streaming: CSW.__anext__ stores args on logging_obj at stream end. """ import asyncio -import os -import sys from typing import Any from unittest.mock import AsyncMock, MagicMock, patch import pytest -sys.path.insert(0, os.path.abspath("../../../..")) import litellm from litellm.caching.caching import DualCache diff --git a/tests/test_litellm/proxy/guardrails/test_guardrail_endpoints.py b/tests/test_litellm/proxy/guardrails/test_guardrail_endpoints.py index 71ff9111b60..45f5afef1bc 100644 --- a/tests/test_litellm/proxy/guardrails/test_guardrail_endpoints.py +++ b/tests/test_litellm/proxy/guardrails/test_guardrail_endpoints.py @@ -1,15 +1,10 @@ import json -import os -import sys from datetime import datetime from typing import Dict, List, Optional from unittest.mock import AsyncMock import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from fastapi import HTTPException diff --git a/tests/test_litellm/proxy/guardrails/test_init_guardrails.py b/tests/test_litellm/proxy/guardrails/test_init_guardrails.py index 8edb56ce25e..82363302d2e 100644 --- a/tests/test_litellm/proxy/guardrails/test_init_guardrails.py +++ b/tests/test_litellm/proxy/guardrails/test_init_guardrails.py @@ -1,11 +1,8 @@ import json -import os -import sys from unittest.mock import MagicMock, patch import pytest -sys.path.insert(0, os.path.abspath("../../..")) # Adds the parent directory to the system path from litellm.proxy.guardrails.guardrail_registry import InMemoryGuardrailHandler from litellm.types.guardrails import SupportedGuardrailIntegrations diff --git a/tests/test_litellm/proxy/guardrails/test_pillar_guardrails.py b/tests/test_litellm/proxy/guardrails/test_pillar_guardrails.py index 48f6b3ba2b9..c6be433399a 100644 --- a/tests/test_litellm/proxy/guardrails/test_pillar_guardrails.py +++ b/tests/test_litellm/proxy/guardrails/test_pillar_guardrails.py @@ -7,13 +7,10 @@ and following LiteLLM testing patterns and best practices. # Standard library imports import importlib -import os -import sys from typing import Any, Dict from unittest.mock import Mock, patch # Add parent directory to path for imports -sys.path.insert(0, os.path.abspath("../../..")) # Third-party imports import json @@ -65,7 +62,6 @@ def setup_and_teardown(): asyncio.set_event_loop(loop) # Set up litellm state - litellm.set_verbose = True litellm.guardrail_name_config_map = {} yield diff --git a/tests/test_litellm/proxy/guardrails/test_usage_endpoints.py b/tests/test_litellm/proxy/guardrails/test_usage_endpoints.py index ff143bd055f..1665fa03639 100644 --- a/tests/test_litellm/proxy/guardrails/test_usage_endpoints.py +++ b/tests/test_litellm/proxy/guardrails/test_usage_endpoints.py @@ -8,15 +8,12 @@ detail 404'd, overview omitted them (or rendered them as Custom/Guardrail orphans), and logs missed their logical-name alias. """ -import os -import sys from datetime import datetime from typing import Any, Optional from unittest.mock import AsyncMock, MagicMock, patch import pytest -sys.path.insert(0, os.path.abspath("../../..")) from fastapi import HTTPException from prisma.errors import TableNotFoundError diff --git a/tests/test_litellm/proxy/health_endpoints/test_health_endpoints.py b/tests/test_litellm/proxy/health_endpoints/test_health_endpoints.py index e576ba87e88..62919200d47 100644 --- a/tests/test_litellm/proxy/health_endpoints/test_health_endpoints.py +++ b/tests/test_litellm/proxy/health_endpoints/test_health_endpoints.py @@ -1,13 +1,8 @@ -import os -import sys import time from datetime import datetime, timedelta from types import SimpleNamespace from unittest.mock import AsyncMock, MagicMock, patch -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path import httpx import pytest diff --git a/tests/test_litellm/proxy/hooks/test_async_post_call_streaming_iterator_hook.py b/tests/test_litellm/proxy/hooks/test_async_post_call_streaming_iterator_hook.py index 9a097230c19..9c785d59830 100644 --- a/tests/test_litellm/proxy/hooks/test_async_post_call_streaming_iterator_hook.py +++ b/tests/test_litellm/proxy/hooks/test_async_post_call_streaming_iterator_hook.py @@ -7,16 +7,11 @@ Verifies that the hook: 3. Actually yields chunks from async generators """ -import os -import sys from typing import AsyncGenerator, Any from unittest.mock import MagicMock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../../../..") -) # Adds the parent directory to the system path import litellm from litellm.integrations.custom_logger import CustomLogger diff --git a/tests/test_litellm/proxy/hooks/test_dynamic_rate_limiter_v3.py b/tests/test_litellm/proxy/hooks/test_dynamic_rate_limiter_v3.py index 13997fc4cd1..0ff8b67b1a7 100644 --- a/tests/test_litellm/proxy/hooks/test_dynamic_rate_limiter_v3.py +++ b/tests/test_litellm/proxy/hooks/test_dynamic_rate_limiter_v3.py @@ -6,14 +6,12 @@ Core tests to validate that priority weights are respected (0.9/0.1) instead of import asyncio import os -import sys import time from datetime import datetime, timedelta from unittest.mock import AsyncMock, patch import pytest -sys.path.insert(0, os.path.abspath("../../../..")) import litellm from litellm import DualCache, Router diff --git a/tests/test_litellm/proxy/hooks/test_image_generation_guardrails.py b/tests/test_litellm/proxy/hooks/test_image_generation_guardrails.py index 04fdc00e114..fd8299b07ec 100644 --- a/tests/test_litellm/proxy/hooks/test_image_generation_guardrails.py +++ b/tests/test_litellm/proxy/hooks/test_image_generation_guardrails.py @@ -9,14 +9,11 @@ These tests verify: 3. A guardrail that raises blocks the response (exception propagates). """ -import os -import sys from typing import Any, Optional from unittest.mock import patch import pytest -sys.path.insert(0, os.path.abspath("../../../..")) import litellm from litellm.caching.caching import DualCache diff --git a/tests/test_litellm/proxy/hooks/test_key_management_event_hooks.py b/tests/test_litellm/proxy/hooks/test_key_management_event_hooks.py index fa7320b2bc6..860fb762450 100644 --- a/tests/test_litellm/proxy/hooks/test_key_management_event_hooks.py +++ b/tests/test_litellm/proxy/hooks/test_key_management_event_hooks.py @@ -5,13 +5,10 @@ Validates that email and secret manager operations are independent and non-block """ import asyncio -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import pytest -sys.path.insert(0, os.path.abspath("../../../..")) from litellm.proxy.hooks.key_management_event_hooks import KeyManagementEventHooks diff --git a/tests/test_litellm/proxy/hooks/test_post_call_failure_hook_integration.py b/tests/test_litellm/proxy/hooks/test_post_call_failure_hook_integration.py index f9cb586d405..55e058d86a1 100644 --- a/tests/test_litellm/proxy/hooks/test_post_call_failure_hook_integration.py +++ b/tests/test_litellm/proxy/hooks/test_post_call_failure_hook_integration.py @@ -5,13 +5,10 @@ Tests verify that the failure hook can transform error responses sent to clients similar to how async_post_call_success_hook can transform successful responses. """ -import os -import sys import pytest from typing import Optional from unittest.mock import patch -sys.path.insert(0, os.path.abspath("../../../..")) from fastapi import HTTPException from litellm.integrations.custom_logger import CustomLogger diff --git a/tests/test_litellm/proxy/hooks/test_post_call_response_headers_hook.py b/tests/test_litellm/proxy/hooks/test_post_call_response_headers_hook.py index 660b0b0162a..a896ab62bef 100644 --- a/tests/test_litellm/proxy/hooks/test_post_call_response_headers_hook.py +++ b/tests/test_litellm/proxy/hooks/test_post_call_response_headers_hook.py @@ -5,13 +5,10 @@ Tests verify that CustomLogger callbacks can inject custom HTTP response headers into success (streaming and non-streaming) and failure responses. """ -import os -import sys import pytest from typing import Any, Dict, Optional from unittest.mock import patch -sys.path.insert(0, os.path.abspath("../../../..")) from litellm.integrations.custom_logger import CustomLogger from litellm.proxy._types import UserAPIKeyAuth diff --git a/tests/test_litellm/proxy/hooks/test_post_call_streaming_hook_integration.py b/tests/test_litellm/proxy/hooks/test_post_call_streaming_hook_integration.py index 22349ec9821..e539bd3a0b2 100644 --- a/tests/test_litellm/proxy/hooks/test_post_call_streaming_hook_integration.py +++ b/tests/test_litellm/proxy/hooks/test_post_call_streaming_hook_integration.py @@ -4,13 +4,10 @@ Integration tests for async_post_call_streaming_hook. Tests verify that the streaming hook can transform streaming responses sent to clients. """ -import os -import sys import pytest from typing import Any from unittest.mock import patch, MagicMock -sys.path.insert(0, os.path.abspath("../../../..")) import litellm from litellm.integrations.custom_logger import CustomLogger diff --git a/tests/test_litellm/proxy/hooks/test_post_call_success_hook_integration.py b/tests/test_litellm/proxy/hooks/test_post_call_success_hook_integration.py index 219f436f985..50208cc278e 100644 --- a/tests/test_litellm/proxy/hooks/test_post_call_success_hook_integration.py +++ b/tests/test_litellm/proxy/hooks/test_post_call_success_hook_integration.py @@ -5,13 +5,10 @@ Tests verify that the success hook can transform responses sent to clients. This mirrors the behavior of CustomGuardrail hooks and streaming iterator hooks. """ -import os -import sys import pytest from typing import Any from unittest.mock import patch, MagicMock -sys.path.insert(0, os.path.abspath("../../../..")) import litellm from litellm.integrations.custom_logger import CustomLogger diff --git a/tests/test_litellm/proxy/hooks/test_proxy_track_cost_callback.py b/tests/test_litellm/proxy/hooks/test_proxy_track_cost_callback.py index 50c93ed5275..871f4b4bcd1 100644 --- a/tests/test_litellm/proxy/hooks/test_proxy_track_cost_callback.py +++ b/tests/test_litellm/proxy/hooks/test_proxy_track_cost_callback.py @@ -1,11 +1,6 @@ -import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../../../..") -) # Adds the parent directory to the system path from datetime import datetime from unittest.mock import AsyncMock, MagicMock, patch diff --git a/tests/test_litellm/proxy/hooks/test_rate_limiter_toctou.py b/tests/test_litellm/proxy/hooks/test_rate_limiter_toctou.py index 97a986d1ade..23c717b0e3a 100644 --- a/tests/test_litellm/proxy/hooks/test_rate_limiter_toctou.py +++ b/tests/test_litellm/proxy/hooks/test_rate_limiter_toctou.py @@ -18,12 +18,10 @@ check-and-increment becomes atomic. import asyncio import os -import sys from typing import List import pytest -sys.path.insert(0, os.path.abspath("../../../..")) import litellm from litellm import DualCache, Router diff --git a/tests/test_litellm/proxy/image_endpoints/test_azure_routes.py b/tests/test_litellm/proxy/image_endpoints/test_azure_routes.py index f5410ef0d70..91fff717d25 100644 --- a/tests/test_litellm/proxy/image_endpoints/test_azure_routes.py +++ b/tests/test_litellm/proxy/image_endpoints/test_azure_routes.py @@ -1,13 +1,11 @@ import asyncio import os -import sys from pathlib import Path from unittest import mock import pytest from fastapi.testclient import TestClient -sys.path.insert(0, os.path.abspath("../../..")) import litellm from litellm.proxy.proxy_server import app, initialize diff --git a/tests/test_litellm/proxy/management_endpoints/scim/test_scim_transformations.py b/tests/test_litellm/proxy/management_endpoints/scim/test_scim_transformations.py index 6970e34f759..9853ce7e1cf 100644 --- a/tests/test_litellm/proxy/management_endpoints/scim/test_scim_transformations.py +++ b/tests/test_litellm/proxy/management_endpoints/scim/test_scim_transformations.py @@ -1,12 +1,7 @@ -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../../../") -) # Adds the parent directory to the system path from litellm.proxy._types import LiteLLM_TeamTable, LiteLLM_UserTable, Member from litellm.proxy.management_endpoints.scim.scim_transformations import ( diff --git a/tests/test_litellm/proxy/management_endpoints/search_endpoints/test_search_tool_management.py b/tests/test_litellm/proxy/management_endpoints/search_endpoints/test_search_tool_management.py index a64397d9818..7b895cd7fdb 100644 --- a/tests/test_litellm/proxy/management_endpoints/search_endpoints/test_search_tool_management.py +++ b/tests/test_litellm/proxy/management_endpoints/search_endpoints/test_search_tool_management.py @@ -1,6 +1,4 @@ import contextlib -import os -import sys from datetime import datetime from unittest.mock import AsyncMock, MagicMock, patch @@ -8,9 +6,6 @@ import pytest from fastapi import HTTPException from fastapi.testclient import TestClient -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path from litellm.proxy._types import ( LiteLLM_ObjectPermissionTable, diff --git a/tests/test_litellm/proxy/management_endpoints/test_access_group_endpoints.py b/tests/test_litellm/proxy/management_endpoints/test_access_group_endpoints.py index 016e10859b6..e8f768c14ef 100644 --- a/tests/test_litellm/proxy/management_endpoints/test_access_group_endpoints.py +++ b/tests/test_litellm/proxy/management_endpoints/test_access_group_endpoints.py @@ -2,8 +2,6 @@ Tests for access group management endpoints. """ -import os -import sys import types from contextlib import asynccontextmanager from datetime import datetime @@ -21,7 +19,6 @@ from litellm.proxy._types import ( UserAPIKeyAuth, ) -sys.path.insert(0, os.path.abspath("../../../")) def _make_access_group_record( diff --git a/tests/test_litellm/proxy/management_endpoints/test_access_group_management.py b/tests/test_litellm/proxy/management_endpoints/test_access_group_management.py index c973c6a8346..db0557cfbf0 100644 --- a/tests/test_litellm/proxy/management_endpoints/test_access_group_management.py +++ b/tests/test_litellm/proxy/management_endpoints/test_access_group_management.py @@ -2,15 +2,10 @@ Test access group management endpoints """ -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../../../..") -) # Adds the parent directory to the system path from litellm import Router from litellm.proxy.management_endpoints.model_management_endpoints import ( diff --git a/tests/test_litellm/proxy/management_endpoints/test_auto_router_endpoints.py b/tests/test_litellm/proxy/management_endpoints/test_auto_router_endpoints.py index 5c61f8c557c..805168c84ac 100644 --- a/tests/test_litellm/proxy/management_endpoints/test_auto_router_endpoints.py +++ b/tests/test_litellm/proxy/management_endpoints/test_auto_router_endpoints.py @@ -2,8 +2,6 @@ Unit tests for auto router management endpoints """ -import os -import sys from pathlib import Path from typing import Final @@ -11,7 +9,6 @@ import pytest from fastapi import HTTPException from pydantic import ValidationError -sys.path.insert(0, os.path.abspath("../../../..")) # Adds the parent directory to the system path from litellm.proxy._types import ( LitellmUserRoles, diff --git a/tests/test_litellm/proxy/management_endpoints/test_budget_endpoints.py b/tests/test_litellm/proxy/management_endpoints/test_budget_endpoints.py index 6a9e894feb5..0bad0d24be5 100644 --- a/tests/test_litellm/proxy/management_endpoints/test_budget_endpoints.py +++ b/tests/test_litellm/proxy/management_endpoints/test_budget_endpoints.py @@ -1,7 +1,5 @@ # tests/test_budget_endpoints.py -import os -import sys import types from datetime import datetime, timedelta, timezone import pytest @@ -12,9 +10,6 @@ import litellm.proxy.proxy_server as ps from litellm.proxy.proxy_server import app from litellm.proxy._types import UserAPIKeyAuth, LitellmUserRoles, CommonProxyErrors -sys.path.insert( - 0, os.path.abspath("../../../") -) # Adds the parent directory to the system path @pytest.fixture diff --git a/tests/test_litellm/proxy/management_endpoints/test_cache_settings_endpoints.py b/tests/test_litellm/proxy/management_endpoints/test_cache_settings_endpoints.py index 2504b5744fc..9a2dd914866 100644 --- a/tests/test_litellm/proxy/management_endpoints/test_cache_settings_endpoints.py +++ b/tests/test_litellm/proxy/management_endpoints/test_cache_settings_endpoints.py @@ -4,13 +4,10 @@ Unit tests for cache settings management endpoints import asyncio import json -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import pytest -sys.path.insert(0, os.path.abspath("../../../..")) # Adds the parent directory to the system path import litellm from litellm.proxy._types import LitellmTableNames, LitellmUserRoles diff --git a/tests/test_litellm/proxy/management_endpoints/test_callback_management_endpoints.py b/tests/test_litellm/proxy/management_endpoints/test_callback_management_endpoints.py index dfc9f0361c6..b2a242bf8f2 100644 --- a/tests/test_litellm/proxy/management_endpoints/test_callback_management_endpoints.py +++ b/tests/test_litellm/proxy/management_endpoints/test_callback_management_endpoints.py @@ -1,13 +1,11 @@ import json import os -import sys from datetime import datetime, timezone from unittest.mock import AsyncMock, MagicMock, patch import pytest from fastapi.testclient import TestClient -sys.path.insert(0, os.path.abspath("../../../..")) # from typing import cast diff --git a/tests/test_litellm/proxy/management_endpoints/test_common_daily_activity.py b/tests/test_litellm/proxy/management_endpoints/test_common_daily_activity.py index 1491782419f..1bcb331430e 100644 --- a/tests/test_litellm/proxy/management_endpoints/test_common_daily_activity.py +++ b/tests/test_litellm/proxy/management_endpoints/test_common_daily_activity.py @@ -1,5 +1,3 @@ -import os -import sys from datetime import datetime, timedelta, timezone from types import SimpleNamespace from typing import Final @@ -9,7 +7,6 @@ import pytest from litellm.proxy.spend_tracking.ptu_feature_flag import PTU_COST_ATTRIBUTION_ENV_VAR -sys.path.insert(0, os.path.abspath("../../../..")) # Adds the parent directory to the system path from litellm.proxy.management_endpoints.common_daily_activity import ( _adjust_dates_for_timezone, diff --git a/tests/test_litellm/proxy/management_endpoints/test_compliance_endpoints.py b/tests/test_litellm/proxy/management_endpoints/test_compliance_endpoints.py index 33e45ccb22c..dcbe515d5de 100644 --- a/tests/test_litellm/proxy/management_endpoints/test_compliance_endpoints.py +++ b/tests/test_litellm/proxy/management_endpoints/test_compliance_endpoints.py @@ -2,12 +2,9 @@ Unit tests for compliance check endpoints (EU AI Act and GDPR). """ -import os -import sys import pytest -sys.path.insert(0, os.path.abspath("../../../..")) # Adds the parent directory to the system path from litellm.proxy.compliance_checks import ComplianceChecker from litellm.types.proxy.compliance_endpoints import ComplianceCheckRequest diff --git a/tests/test_litellm/proxy/management_endpoints/test_coordination_redis_endpoints.py b/tests/test_litellm/proxy/management_endpoints/test_coordination_redis_endpoints.py index 2e78a4ca0e3..4481a87c9e7 100644 --- a/tests/test_litellm/proxy/management_endpoints/test_coordination_redis_endpoints.py +++ b/tests/test_litellm/proxy/management_endpoints/test_coordination_redis_endpoints.py @@ -4,14 +4,11 @@ Unit tests for coordination Redis settings management endpoints import asyncio import json -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import pytest from fastapi import HTTPException -sys.path.insert(0, os.path.abspath("../../../..")) # Adds the parent directory to the system path import litellm from litellm.caching.caching import RedisCache diff --git a/tests/test_litellm/proxy/management_endpoints/test_cost_tracking_settings.py b/tests/test_litellm/proxy/management_endpoints/test_cost_tracking_settings.py index ea86731eba4..e1eb031abc2 100644 --- a/tests/test_litellm/proxy/management_endpoints/test_cost_tracking_settings.py +++ b/tests/test_litellm/proxy/management_endpoints/test_cost_tracking_settings.py @@ -4,14 +4,11 @@ Tests for cost tracking settings management endpoints. Tests the GET and PATCH endpoints for managing cost discount configuration. """ -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import pytest from fastapi.testclient import TestClient -sys.path.insert(0, os.path.abspath("../../../..")) import litellm from litellm.proxy.management_endpoints.cost_tracking_settings import router diff --git a/tests/test_litellm/proxy/management_endpoints/test_delete_callbacks_endpoint.py b/tests/test_litellm/proxy/management_endpoints/test_delete_callbacks_endpoint.py index 4ba656d1286..291f3d8fe2f 100644 --- a/tests/test_litellm/proxy/management_endpoints/test_delete_callbacks_endpoint.py +++ b/tests/test_litellm/proxy/management_endpoints/test_delete_callbacks_endpoint.py @@ -1,11 +1,8 @@ -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import pytest from fastapi.testclient import TestClient -sys.path.insert(0, os.path.abspath("../../../..")) from litellm.proxy._types import ( CallbackDelete, diff --git a/tests/test_litellm/proxy/management_endpoints/test_delete_verification_tokens_failed.py b/tests/test_litellm/proxy/management_endpoints/test_delete_verification_tokens_failed.py index 63e584e49bc..e33945df7dc 100644 --- a/tests/test_litellm/proxy/management_endpoints/test_delete_verification_tokens_failed.py +++ b/tests/test_litellm/proxy/management_endpoints/test_delete_verification_tokens_failed.py @@ -8,12 +8,9 @@ its result dict in all scenarios, populated with any token hashes that could not be deleted. """ -import os -import sys import pytest -sys.path.insert(0, os.path.abspath("../../../..")) from unittest.mock import AsyncMock, MagicMock diff --git a/tests/test_litellm/proxy/management_endpoints/test_internal_user_endpoints.py b/tests/test_litellm/proxy/management_endpoints/test_internal_user_endpoints.py index da51d513b39..f86e17c61b0 100644 --- a/tests/test_litellm/proxy/management_endpoints/test_internal_user_endpoints.py +++ b/tests/test_litellm/proxy/management_endpoints/test_internal_user_endpoints.py @@ -1,15 +1,10 @@ import json -import os -import sys from datetime import datetime, timezone from types import SimpleNamespace import pytest from fastapi.testclient import TestClient -sys.path.insert( - 0, os.path.abspath("../../../..") -) # Adds the parent directory to the system path from litellm.proxy._types import ( LiteLLM_UserTableFiltered, diff --git a/tests/test_litellm/proxy/management_endpoints/test_mcp_management_endpoints.py b/tests/test_litellm/proxy/management_endpoints/test_mcp_management_endpoints.py index f8db8433be5..0d639e1cb6a 100644 --- a/tests/test_litellm/proxy/management_endpoints/test_mcp_management_endpoints.py +++ b/tests/test_litellm/proxy/management_endpoints/test_mcp_management_endpoints.py @@ -17,7 +17,6 @@ from litellm.proxy.management_endpoints import ( mcp_management_endpoints as mgmt_endpoints, ) -sys.path.insert(0, os.path.abspath("../../../..")) # Adds the parent directory to the system path from litellm.proxy._types import ( LiteLLM_MCPServerTable, @@ -6482,7 +6481,6 @@ def test_bundled_openapi_registry_parses_and_entries_are_well_formed(): authorization_url would recreate the exact 400 ("authorization url is not set") the catalog exists to prevent for spec-only servers, which never run OAuth endpoint discovery.""" import json - import os registry_path = os.path.join( os.path.dirname(os.path.abspath(__file__)), diff --git a/tests/test_litellm/proxy/management_endpoints/test_model_management_endpoints.py b/tests/test_litellm/proxy/management_endpoints/test_model_management_endpoints.py index 42e96ad8659..097230108d4 100644 --- a/tests/test_litellm/proxy/management_endpoints/test_model_management_endpoints.py +++ b/tests/test_litellm/proxy/management_endpoints/test_model_management_endpoints.py @@ -1,7 +1,5 @@ import asyncio import json -import os -import sys from typing import Dict, Optional from unittest.mock import AsyncMock, MagicMock, patch @@ -10,9 +8,6 @@ from fastapi.testclient import TestClient from litellm._uuid import uuid -sys.path.insert( - 0, os.path.abspath("../../../..") -) # Adds the parent directory to the system path from litellm.proxy._types import ( LiteLLM_ModelTable, LiteLLM_ProxyModelTable, diff --git a/tests/test_litellm/proxy/management_endpoints/test_org_admin_team_access.py b/tests/test_litellm/proxy/management_endpoints/test_org_admin_team_access.py index 9828d104a8b..d5c958f9f84 100644 --- a/tests/test_litellm/proxy/management_endpoints/test_org_admin_team_access.py +++ b/tests/test_litellm/proxy/management_endpoints/test_org_admin_team_access.py @@ -7,14 +7,11 @@ Covers: - _user_is_org_admin route-level check (no privilege escalation) """ -import os -import sys from datetime import datetime, timezone from unittest.mock import AsyncMock, MagicMock, patch import pytest -sys.path.insert(0, os.path.abspath("../../../")) from litellm.proxy._types import ( LiteLLM_OrganizationMembershipTable, diff --git a/tests/test_litellm/proxy/management_endpoints/test_organization_endpoints.py b/tests/test_litellm/proxy/management_endpoints/test_organization_endpoints.py index 3061da336f6..a62c98e56a7 100644 --- a/tests/test_litellm/proxy/management_endpoints/test_organization_endpoints.py +++ b/tests/test_litellm/proxy/management_endpoints/test_organization_endpoints.py @@ -1,7 +1,5 @@ import asyncio import json -import os -import sys from litellm._uuid import uuid from typing import Optional, cast from unittest.mock import AsyncMock, MagicMock, patch @@ -10,7 +8,6 @@ import pytest from fastapi import HTTPException from fastapi.testclient import TestClient -sys.path.insert(0, os.path.abspath("../../../")) # Adds the parent directory to the system path @pytest.mark.asyncio diff --git a/tests/test_litellm/proxy/management_endpoints/test_router_settings_endpoints.py b/tests/test_litellm/proxy/management_endpoints/test_router_settings_endpoints.py index b62f077a62e..308f4d88f02 100644 --- a/tests/test_litellm/proxy/management_endpoints/test_router_settings_endpoints.py +++ b/tests/test_litellm/proxy/management_endpoints/test_router_settings_endpoints.py @@ -4,14 +4,11 @@ Tests for router settings management endpoints. Tests the GET endpoints for router settings and router fields. """ -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import pytest from fastapi.testclient import TestClient -sys.path.insert(0, os.path.abspath("../../../..")) from litellm.proxy import proxy_server from litellm.proxy._types import LitellmUserRoles, UserAPIKeyAuth diff --git a/tests/test_litellm/proxy/management_endpoints/test_tag_management_endpoints.py b/tests/test_litellm/proxy/management_endpoints/test_tag_management_endpoints.py index 018979aa19b..71c67837515 100644 --- a/tests/test_litellm/proxy/management_endpoints/test_tag_management_endpoints.py +++ b/tests/test_litellm/proxy/management_endpoints/test_tag_management_endpoints.py @@ -1,7 +1,5 @@ import inspect import json -import os -import sys from collections.abc import Sequence from typing import Optional @@ -10,9 +8,6 @@ from fastapi import HTTPException from fastapi.testclient import TestClient from prisma.actions import LiteLLM_VerificationTokenActions -sys.path.insert( - 0, os.path.abspath("../../../..") -) # Adds the parent directory to the system path from contextlib import contextmanager from unittest.mock import AsyncMock, Mock, patch diff --git a/tests/test_litellm/proxy/management_endpoints/test_team_default_params.py b/tests/test_litellm/proxy/management_endpoints/test_team_default_params.py index a485d95db06..265437f97e9 100644 --- a/tests/test_litellm/proxy/management_endpoints/test_team_default_params.py +++ b/tests/test_litellm/proxy/management_endpoints/test_team_default_params.py @@ -3,14 +3,11 @@ Tests for applying default team params during team creation and loading default_team_params from DB on startup. """ -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import pytest from fastapi import HTTPException -sys.path.insert(0, os.path.abspath("../../../")) # Adds the parent directory to the system path import litellm from litellm.proxy._types import ( diff --git a/tests/test_litellm/proxy/management_endpoints/test_team_endpoints.py b/tests/test_litellm/proxy/management_endpoints/test_team_endpoints.py index a4c2b7c06bf..34b12aecfed 100644 --- a/tests/test_litellm/proxy/management_endpoints/test_team_endpoints.py +++ b/tests/test_litellm/proxy/management_endpoints/test_team_endpoints.py @@ -1,7 +1,5 @@ import asyncio import json -import os -import sys from contextlib import asynccontextmanager from datetime import datetime, timezone from types import SimpleNamespace @@ -14,9 +12,6 @@ from fastapi.testclient import TestClient from litellm._uuid import uuid -sys.path.insert( - 0, os.path.abspath("../../../") -) # Adds the parent directory to the system path from litellm.proxy._types import UserAPIKeyAuth # Import UserAPIKeyAuth from litellm.proxy._types import ( LiteLLM_BudgetTableFull, diff --git a/tests/test_litellm/proxy/management_endpoints/test_team_model_alias_merge.py b/tests/test_litellm/proxy/management_endpoints/test_team_model_alias_merge.py index 45405ba78d6..7cdf60f043e 100644 --- a/tests/test_litellm/proxy/management_endpoints/test_team_model_alias_merge.py +++ b/tests/test_litellm/proxy/management_endpoints/test_team_model_alias_merge.py @@ -6,13 +6,10 @@ Concurrent BYOK model creates must not overwrite each other's entries in team.models. """ -import os -import sys from unittest.mock import AsyncMock, MagicMock import pytest -sys.path.insert(0, os.path.abspath("../../../..")) from litellm.proxy._types import ( LitellmUserRoles, diff --git a/tests/test_litellm/proxy/management_endpoints/test_tool_management_endpoints.py b/tests/test_litellm/proxy/management_endpoints/test_tool_management_endpoints.py index 18ea5c3f27d..09d14cfe5df 100644 --- a/tests/test_litellm/proxy/management_endpoints/test_tool_management_endpoints.py +++ b/tests/test_litellm/proxy/management_endpoints/test_tool_management_endpoints.py @@ -8,8 +8,6 @@ imports these inside function bodies to avoid circular imports. """ import inspect -import os -import sys from collections.abc import Sequence from datetime import datetime, timedelta, timezone from typing import Optional @@ -20,7 +18,6 @@ from fastapi import FastAPI from fastapi.testclient import TestClient from prisma.actions import LiteLLM_TeamTableActions -sys.path.insert(0, os.path.abspath("../../..")) from litellm.proxy.management_endpoints.tool_management_endpoints import router from litellm.types.tool_management import LiteLLM_ToolTableRow diff --git a/tests/test_litellm/proxy/management_endpoints/test_ui_sso.py b/tests/test_litellm/proxy/management_endpoints/test_ui_sso.py index 66cb07ef2c0..3facbf07889 100644 --- a/tests/test_litellm/proxy/management_endpoints/test_ui_sso.py +++ b/tests/test_litellm/proxy/management_endpoints/test_ui_sso.py @@ -1,7 +1,6 @@ import asyncio import json import os -import sys from contextlib import asynccontextmanager from types import SimpleNamespace from unittest.mock import AsyncMock, MagicMock, patch @@ -11,9 +10,6 @@ from fastapi import HTTPException, Request from litellm._uuid import uuid -sys.path.insert( - 0, os.path.abspath("../../../") -) # Adds the parent directory to the system path import litellm from litellm.proxy._types import LiteLLM_UserTable, NewUserResponse diff --git a/tests/test_litellm/proxy/management_endpoints/test_workflow_management_endpoints.py b/tests/test_litellm/proxy/management_endpoints/test_workflow_management_endpoints.py index 27adb3e0892..0c3d5107cb6 100644 --- a/tests/test_litellm/proxy/management_endpoints/test_workflow_management_endpoints.py +++ b/tests/test_litellm/proxy/management_endpoints/test_workflow_management_endpoints.py @@ -4,8 +4,6 @@ Uses FastAPI TestClient with a mocked prisma_client. """ import asyncio -import os -import sys from datetime import datetime, timezone from typing import Any from unittest.mock import AsyncMock, MagicMock, patch @@ -15,7 +13,6 @@ from fastapi import FastAPI, HTTPException from fastapi.testclient import TestClient from prisma.errors import UniqueViolationError -sys.path.insert(0, os.path.abspath("../../..")) from litellm.proxy.management_endpoints.workflow_management_endpoints import ( _read_scope_caller, diff --git a/tests/test_litellm/proxy/management_helpers/test_access_group_team_sync.py b/tests/test_litellm/proxy/management_helpers/test_access_group_team_sync.py index eb11292cf42..f99b576019a 100644 --- a/tests/test_litellm/proxy/management_helpers/test_access_group_team_sync.py +++ b/tests/test_litellm/proxy/management_helpers/test_access_group_team_sync.py @@ -1,9 +1,6 @@ -import os -import sys import pytest -sys.path.insert(0, os.path.abspath("../../../..")) from litellm.proxy.management_helpers.access_group_team_sync import ( invalidate_access_group_caches, diff --git a/tests/test_litellm/proxy/management_helpers/test_management_helpers_utils.py b/tests/test_litellm/proxy/management_helpers/test_management_helpers_utils.py index 504414ea635..bdc2f9065b9 100644 --- a/tests/test_litellm/proxy/management_helpers/test_management_helpers_utils.py +++ b/tests/test_litellm/proxy/management_helpers/test_management_helpers_utils.py @@ -1,15 +1,10 @@ import json -import os -import sys from datetime import datetime, timezone from litellm._uuid import uuid from unittest.mock import AsyncMock, MagicMock import pytest -sys.path.insert( - 0, os.path.abspath("../../../..") -) # Adds the parent directory to the system path from litellm.proxy._types import ( LiteLLM_TeamMembership, diff --git a/tests/test_litellm/proxy/management_helpers/test_object_permission_utils.py b/tests/test_litellm/proxy/management_helpers/test_object_permission_utils.py index d797a27aa67..b129ad0f659 100644 --- a/tests/test_litellm/proxy/management_helpers/test_object_permission_utils.py +++ b/tests/test_litellm/proxy/management_helpers/test_object_permission_utils.py @@ -1,11 +1,8 @@ import json -import os -import sys import pytest from fastapi import HTTPException -sys.path.insert(0, os.path.abspath("../../../..")) from unittest.mock import AsyncMock, MagicMock, patch diff --git a/tests/test_litellm/proxy/management_helpers/test_team_member_permission_checks.py b/tests/test_litellm/proxy/management_helpers/test_team_member_permission_checks.py index 71999e29f96..36c61eddbb2 100644 --- a/tests/test_litellm/proxy/management_helpers/test_team_member_permission_checks.py +++ b/tests/test_litellm/proxy/management_helpers/test_team_member_permission_checks.py @@ -1,12 +1,7 @@ -import os -import sys from unittest.mock import MagicMock import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from litellm.proxy._types import KeyManagementRoutes, Member, ProxyException from litellm.proxy.management_helpers.team_member_permission_checks import ( diff --git a/tests/test_litellm/proxy/management_helpers/test_team_metadata_validation.py b/tests/test_litellm/proxy/management_helpers/test_team_metadata_validation.py index 1acb8e7e016..dfb834dc31f 100644 --- a/tests/test_litellm/proxy/management_helpers/test_team_metadata_validation.py +++ b/tests/test_litellm/proxy/management_helpers/test_team_metadata_validation.py @@ -1,12 +1,9 @@ import asyncio -import os -import sys from unittest.mock import patch import pytest from fastapi import HTTPException -sys.path.insert(0, os.path.abspath("../../../..")) from litellm.proxy._types import CommonProxyErrors, LitellmUserRoles, UserAPIKeyAuth from litellm.proxy.management_helpers.team_metadata_validation import ( diff --git a/tests/test_litellm/proxy/memory/test_memory_endpoints.py b/tests/test_litellm/proxy/memory/test_memory_endpoints.py index ec81ef2ff7a..3d99a600a73 100644 --- a/tests/test_litellm/proxy/memory/test_memory_endpoints.py +++ b/tests/test_litellm/proxy/memory/test_memory_endpoints.py @@ -7,8 +7,6 @@ We patch the endpoint module's `_require_prisma` helper so we never need the real proxy_server import chain (which pulls heavy optional deps). """ -import os -import sys from datetime import datetime, timezone from typing import Any, Dict, List, Optional from unittest.mock import MagicMock, patch @@ -16,7 +14,6 @@ from unittest.mock import MagicMock, patch from fastapi import FastAPI from fastapi.testclient import TestClient -sys.path.insert(0, os.path.abspath("../../..")) from litellm.proxy._types import LitellmUserRoles, UserAPIKeyAuth from litellm.proxy.memory.memory_endpoints import _visibility_filter, router diff --git a/tests/test_litellm/proxy/openai_files_endpoint/test_files_common_utils.py b/tests/test_litellm/proxy/openai_files_endpoint/test_files_common_utils.py index 6ffb7daaa2d..2161e345b40 100644 --- a/tests/test_litellm/proxy/openai_files_endpoint/test_files_common_utils.py +++ b/tests/test_litellm/proxy/openai_files_endpoint/test_files_common_utils.py @@ -1,11 +1,8 @@ -import os -import sys from types import MappingProxyType from unittest.mock import AsyncMock, MagicMock import pytest -sys.path.insert(0, os.path.abspath("../../../..")) from litellm.proxy.openai_files_endpoints.common_utils import ( apply_unified_file_ids, diff --git a/tests/test_litellm/proxy/openai_files_endpoint/test_files_endpoint.py b/tests/test_litellm/proxy/openai_files_endpoint/test_files_endpoint.py index bf9323cdc6a..c15ba5bcedb 100644 --- a/tests/test_litellm/proxy/openai_files_endpoint/test_files_endpoint.py +++ b/tests/test_litellm/proxy/openai_files_endpoint/test_files_endpoint.py @@ -1,7 +1,5 @@ import json -import os -import sys -from typing import List +from typing import Final, List from unittest.mock import ANY, AsyncMock import pytest @@ -10,9 +8,6 @@ import httpx from fastapi.testclient import TestClient from pytest_mock import MockerFixture -sys.path.insert( - 0, os.path.abspath("../../../..") -) # Adds the parent directory to the system path import litellm from litellm import Router @@ -24,7 +19,11 @@ from litellm.proxy.openai_files_endpoints.file_content_streaming_handler import FileContentStreamingHandler, ) from litellm.proxy.proxy_server import app -from litellm.types.llms.openai import HttpxBinaryResponseContent, OpenAIFileObject +from litellm.types.llms.openai import ( + FileListPage, + HttpxBinaryResponseContent, + OpenAIFileObject, +) client = TestClient(app) from litellm.caching.caching import DualCache @@ -330,7 +329,15 @@ def test_mock_create_audio_file(mocker: MockerFixture, monkeypatch, llm_router: async def afile_retrieve(self, file_id, litellm_parent_otel_span, llm_router): raise NotImplementedError("Not implemented for test") - async def afile_list(self, purpose, litellm_parent_otel_span): + async def afile_list( + self, + purpose, + litellm_parent_otel_span, + user_api_key_dict, + limit=None, + after=None, + **data, + ): raise NotImplementedError("Not implemented for test") async def afile_delete( @@ -904,7 +911,15 @@ def test_create_file_with_expires_after( async def afile_retrieve(self, file_id, litellm_parent_otel_span, llm_router): raise NotImplementedError("Not implemented for test") - async def afile_list(self, purpose, litellm_parent_otel_span): + async def afile_list( + self, + purpose, + litellm_parent_otel_span, + user_api_key_dict, + limit=None, + after=None, + **data, + ): raise NotImplementedError("Not implemented for test") async def afile_delete( @@ -1067,7 +1082,15 @@ def test_create_file_with_expires_after_valid_values( async def afile_retrieve(self, file_id, litellm_parent_otel_span, llm_router): raise NotImplementedError("Not implemented for test") - async def afile_list(self, purpose, litellm_parent_otel_span): + async def afile_list( + self, + purpose, + litellm_parent_otel_span, + user_api_key_dict, + limit=None, + after=None, + **data, + ): raise NotImplementedError("Not implemented for test") async def afile_delete( @@ -1155,7 +1178,15 @@ def test_create_file_without_expires_after( async def afile_retrieve(self, file_id, litellm_parent_otel_span, llm_router): raise NotImplementedError("Not implemented for test") - async def afile_list(self, purpose, litellm_parent_otel_span): + async def afile_list( + self, + purpose, + litellm_parent_otel_span, + user_api_key_dict, + limit=None, + after=None, + **data, + ): raise NotImplementedError("Not implemented for test") async def afile_delete( @@ -1252,7 +1283,15 @@ def test_managed_files_with_loadbalancing( async def afile_retrieve(self, file_id, litellm_parent_otel_span, llm_router): raise NotImplementedError("Not implemented for test") - async def afile_list(self, purpose, litellm_parent_otel_span): + async def afile_list( + self, + purpose, + litellm_parent_otel_span, + user_api_key_dict, + limit=None, + after=None, + **data, + ): raise NotImplementedError("Not implemented for test") async def afile_delete( @@ -1369,7 +1408,15 @@ def test_create_file_with_nested_litellm_metadata( async def afile_retrieve(self, file_id, litellm_parent_otel_span, llm_router): raise NotImplementedError("Not implemented for test") - async def afile_list(self, purpose, litellm_parent_otel_span): + async def afile_list( + self, + purpose, + litellm_parent_otel_span, + user_api_key_dict, + limit=None, + after=None, + **data, + ): raise NotImplementedError("Not implemented for test") async def afile_delete( @@ -1473,7 +1520,15 @@ def test_create_file_with_deep_nested_litellm_metadata( async def afile_retrieve(self, file_id, litellm_parent_otel_span, llm_router): raise NotImplementedError("Not implemented for test") - async def afile_list(self, purpose, litellm_parent_otel_span): + async def afile_list( + self, + purpose, + litellm_parent_otel_span, + user_api_key_dict, + limit=None, + after=None, + **data, + ): raise NotImplementedError("Not implemented for test") async def afile_delete( @@ -1569,7 +1624,15 @@ def _make_capturing_managed_files(): async def afile_retrieve(self, file_id, litellm_parent_otel_span, llm_router): raise NotImplementedError - async def afile_list(self, purpose, litellm_parent_otel_span): + async def afile_list( + self, + purpose, + litellm_parent_otel_span, + user_api_key_dict, + limit=None, + after=None, + **data, + ): raise NotImplementedError async def afile_delete( @@ -2052,7 +2115,15 @@ def test_require_managed_files_allows_managed_file_upload( async def afile_retrieve(self, file_id, litellm_parent_otel_span, llm_router): raise NotImplementedError - async def afile_list(self, purpose, litellm_parent_otel_span): + async def afile_list( + self, + purpose, + litellm_parent_otel_span, + user_api_key_dict, + limit=None, + after=None, + **data, + ): raise NotImplementedError async def afile_delete( @@ -2176,7 +2247,15 @@ def test_require_managed_files_accepts_target_model_names_bracket_form( async def afile_retrieve(self, file_id, litellm_parent_otel_span, llm_router): raise NotImplementedError - async def afile_list(self, purpose, litellm_parent_otel_span): + async def afile_list( + self, + purpose, + litellm_parent_otel_span, + user_api_key_dict, + limit=None, + after=None, + **data, + ): raise NotImplementedError async def afile_delete( @@ -2256,7 +2335,15 @@ def test_require_managed_files_accepts_repeated_target_model_names_bracket_form( async def afile_retrieve(self, file_id, litellm_parent_otel_span, llm_router): raise NotImplementedError - async def afile_list(self, purpose, litellm_parent_otel_span): + async def afile_list( + self, + purpose, + litellm_parent_otel_span, + user_api_key_dict, + limit=None, + after=None, + **data, + ): raise NotImplementedError async def afile_delete( @@ -2468,6 +2555,403 @@ def test_list_files_without_target_model_names_uses_team_openai_deployment( proxy_logging_obj.post_call_failure_hook.assert_not_called() +def test_unscoped_list_files_uses_managed_file_store( + mocker: MockerFixture, monkeypatch, llm_router: Router +): + import litellm.proxy.proxy_server as ps + from litellm.llms.base_llm.files.transformation import BaseFileEndpoints + from litellm.proxy._types import LitellmUserRoles + + managed_file = OpenAIFileObject( + id="unified-file-id", + object="file", + bytes=100, + created_at=1700000000, + filename="output.jsonl", + purpose="batch_output", + status="processed", + ) + + proxy_logging_obj = setup_proxy_logging_object(monkeypatch, llm_router) + managed_files = mocker.MagicMock(spec=BaseFileEndpoints) + managed_files.afile_list = mocker.AsyncMock( + return_value={ + "object": "list", + "data": [managed_file], + "first_id": managed_file.id, + "last_id": managed_file.id, + "has_more": False, + } + ) + proxy_logging_obj.proxy_hook_mapping["managed_files"] = managed_files + proxy_logging_obj.update_request_status = mocker.AsyncMock() + proxy_logging_obj.post_call_success_hook = mocker.AsyncMock(return_value=None) + proxy_logging_obj.post_call_failure_hook = mocker.AsyncMock() + monkeypatch.setattr("litellm.proxy.proxy_server.master_key", None) + monkeypatch.setattr("litellm.proxy.proxy_server.prisma_client", None) + monkeypatch.setattr("litellm.proxy.proxy_server.llm_router", llm_router) + provider_list = mocker.patch.object(litellm, "afile_list", new=mocker.AsyncMock()) + + app.dependency_overrides[ps.user_api_key_auth] = lambda: UserAPIKeyAuth( + api_key="test-key", + user_role=LitellmUserRoles.INTERNAL_USER, + user_id="test-user", + ) + + try: + response = client.get( + "/v1/files", + headers={"Authorization": "Bearer test-key"}, + ) + finally: + app.dependency_overrides.pop(ps.user_api_key_auth, None) + + assert response.status_code == 200, response.text + assert response.json()["data"][0]["id"] == "unified-file-id" + managed_files.afile_list.assert_awaited_once() + assert managed_files.afile_list.await_args.kwargs["user_api_key_dict"].user_id == "test-user" + assert managed_files.afile_list.await_args.kwargs["limit"] is None + assert managed_files.afile_list.await_args.kwargs["after"] is None + provider_list.assert_not_awaited() + proxy_logging_obj.post_call_failure_hook.assert_not_called() + + +def test_unscoped_list_files_forwards_limit_and_after_to_the_managed_file_store( + mocker: MockerFixture, monkeypatch, llm_router: Router +): + import litellm.proxy.proxy_server as ps + from litellm.llms.base_llm.files.transformation import BaseFileEndpoints + from litellm.proxy._types import LitellmUserRoles + + second_page_file = OpenAIFileObject( + id="unified-file-id-2", + object="file", + bytes=100, + created_at=1700000000, + filename="output.jsonl", + purpose="batch", + status="processed", + ) + + proxy_logging_obj = setup_proxy_logging_object(monkeypatch, llm_router) + managed_files = mocker.MagicMock(spec=BaseFileEndpoints) + managed_files.afile_list = mocker.AsyncMock( + return_value={ + "object": "list", + "data": [second_page_file], + "first_id": second_page_file.id, + "last_id": second_page_file.id, + "has_more": True, + } + ) + proxy_logging_obj.proxy_hook_mapping["managed_files"] = managed_files + proxy_logging_obj.update_request_status = mocker.AsyncMock() + proxy_logging_obj.post_call_success_hook = mocker.AsyncMock(return_value=None) + proxy_logging_obj.post_call_failure_hook = mocker.AsyncMock() + monkeypatch.setattr("litellm.proxy.proxy_server.master_key", None) + monkeypatch.setattr("litellm.proxy.proxy_server.prisma_client", None) + monkeypatch.setattr("litellm.proxy.proxy_server.llm_router", llm_router) + provider_list = mocker.patch.object(litellm, "afile_list", new=mocker.AsyncMock()) + + app.dependency_overrides[ps.user_api_key_auth] = lambda: UserAPIKeyAuth( + api_key="test-key", + user_role=LitellmUserRoles.INTERNAL_USER, + user_id="test-user", + ) + + try: + response = client.get( + "/v1/files?limit=2&after=unified-file-id-1&purpose=batch", + headers={"Authorization": "Bearer test-key"}, + ) + finally: + app.dependency_overrides.pop(ps.user_api_key_auth, None) + + assert response.status_code == 200, response.text + assert response.json()["data"][0]["id"] == "unified-file-id-2" + assert response.json()["has_more"] is True + call_kwargs = managed_files.afile_list.await_args.kwargs + assert call_kwargs["limit"] == 2 + assert call_kwargs["after"] == "unified-file-id-1" + assert call_kwargs["purpose"] == "batch" + provider_list.assert_not_awaited() + proxy_logging_obj.post_call_failure_hook.assert_not_called() + + +def _setup_unscoped_list_files_route(mocker, monkeypatch, llm_router: Router, afile_list): + """Wire GET /v1/files to the managed file store, with afile_list as the store.""" + import litellm.proxy.proxy_server as ps + from litellm.llms.base_llm.files.transformation import BaseFileEndpoints + from litellm.proxy._types import LitellmUserRoles + + proxy_logging_obj = setup_proxy_logging_object(monkeypatch, llm_router) + managed_files = mocker.MagicMock(spec=BaseFileEndpoints) + managed_files.afile_list = mocker.AsyncMock(side_effect=afile_list) + proxy_logging_obj.proxy_hook_mapping["managed_files"] = managed_files + proxy_logging_obj.update_request_status = mocker.AsyncMock() + proxy_logging_obj.post_call_success_hook = mocker.AsyncMock(return_value=None) + proxy_logging_obj.post_call_failure_hook = mocker.AsyncMock() + monkeypatch.setattr("litellm.proxy.proxy_server.master_key", None) + monkeypatch.setattr("litellm.proxy.proxy_server.prisma_client", None) + monkeypatch.setattr("litellm.proxy.proxy_server.llm_router", llm_router) + mocker.patch.object(litellm, "afile_list", new=mocker.AsyncMock()) + + app.dependency_overrides[ps.user_api_key_auth] = lambda: UserAPIKeyAuth( + api_key="test-key", + user_role=LitellmUserRoles.INTERNAL_USER, + user_id="test-user", + ) + return managed_files + + +def _get_list_files(path: str): + try: + return client.get(path, headers={"Authorization": "Bearer test-key"}) + finally: + import litellm.proxy.proxy_server as ps + + app.dependency_overrides.pop(ps.user_api_key_auth, None) + + +def _get_unscoped_list_files(query: str): + return _get_list_files(f"/v1/files{query}") + + +_EMPTY_FILE_LIST_PAGE: Final = { + "object": "list", + "data": [], + "first_id": None, + "last_id": None, + "has_more": False, +} + + +async def _validating_afile_list(**kwargs): + """Stand in for the managed file store, applying the real request validation.""" + from litellm.proxy.openai_files_endpoints.common_utils import ( + validate_file_list_limit, + validate_file_list_purpose, + ) + + validate_file_list_limit(kwargs.get("limit")) + validate_file_list_purpose(kwargs.get("purpose")) + return FileListPage(**_EMPTY_FILE_LIST_PAGE) + + +async def _permissive_afile_list(**kwargs): + """Stand in for a file store that validates nothing, so only the route can reject.""" + return FileListPage(**_EMPTY_FILE_LIST_PAGE) + + +@pytest.mark.parametrize( + "limit, bound, expected_range", + [ + (0, "below minimum", ">= 1"), + (-1, "below minimum", ">= 1"), + (10001, "above maximum", "<= 10000"), + ], +) +def test_unscoped_list_files_returns_400_for_a_limit_outside_the_openai_range( + mocker: MockerFixture, monkeypatch, llm_router: Router, limit, bound, expected_range +): + """An out-of-range limit is the caller's mistake, so it must not read as a 500 the SDK retries.""" + _setup_unscoped_list_files_route(mocker, monkeypatch, llm_router, _validating_afile_list) + + response = _get_unscoped_list_files(f"?limit={limit}") + + assert response.status_code == 400, response.text + assert response.json() == { + "error": { + "message": ( + f"Invalid 'limit': integer {bound} value. " + f"Expected a value {expected_range}, but got {limit} instead." + ), + "type": "invalid_request_error", + "param": "limit", + "code": "400", + } + } + + +@pytest.mark.parametrize("limit", [1, 10000]) +def test_unscoped_list_files_accepts_the_ends_of_the_openai_limit_range( + mocker: MockerFixture, monkeypatch, llm_router: Router, limit +): + managed_files = _setup_unscoped_list_files_route(mocker, monkeypatch, llm_router, _validating_afile_list) + + response = _get_unscoped_list_files(f"?limit={limit}") + + assert response.status_code == 200, response.text + assert response.json()["data"] == [] + assert managed_files.afile_list.await_args.kwargs["limit"] == limit + + +@pytest.mark.parametrize( + "path", + [ + "/v1/files?limit=0", + "/v1/files?limit=0&target_model_names=gpt-3.5-turbo", + "/openai/v1/files?limit=0", + ], + ids=["managed-file-store", "target-model-names", "provider-route"], +) +def test_list_files_validates_the_limit_on_every_branch( + mocker: MockerFixture, monkeypatch, llm_router: Router, path +): + """The limit is a route-level contract, so the scoped and provider branches reject it too.""" + _setup_unscoped_list_files_route(mocker, monkeypatch, llm_router, _permissive_afile_list) + + response = _get_list_files(path) + + assert response.status_code == 400, response.text + assert response.json()["error"]["param"] == "limit" + assert response.json()["error"]["message"] == ( + "Invalid 'limit': integer below minimum value. Expected a value >= 1, but got 0 instead." + ) + + +def test_unscoped_list_files_returns_400_for_an_unknown_after_cursor( + mocker: MockerFixture, monkeypatch, llm_router: Router +): + from litellm.proxy._types import ProxyException + + async def _unknown_cursor(**kwargs): + raise ProxyException( + message=f"Invalid 'after' cursor: no file found with id '{kwargs['after']}'.", + type="invalid_request_error", + param="after", + code=400, + openai_code="invalid_value", + ) + + _setup_unscoped_list_files_route(mocker, monkeypatch, llm_router, _unknown_cursor) + + response = _get_unscoped_list_files("?after=file-does-not-exist-xyz") + + assert response.status_code == 400, response.text + assert response.json() == { + "error": { + "message": "Invalid 'after' cursor: no file found with id 'file-does-not-exist-xyz'.", + "type": "invalid_request_error", + "param": "after", + "code": "400", + } + } + + +def _managed_file(file_id: str) -> OpenAIFileObject: + return OpenAIFileObject( + id=file_id, + bytes=17, + created_at=1700000000, + filename="batch_input.jsonl", + object="file", + purpose="batch", + status="uploaded", + ) + + +def test_unscoped_list_files_hands_post_call_hooks_a_page_object( + mocker: MockerFixture, monkeypatch, llm_router: Router +): + """Logging callbacks read ``response.data`` off a listing, so the managed + branch has to hand them the same page shape the provider branch does. A bare + mapping turns every registered callback into a 500 on this route.""" + import litellm.proxy.proxy_server as ps + + seen_by_callback: list[list[str]] = [] + + async def _reads_response_data(data, user_api_key_dict, response): + seen_by_callback.append([file.id for file in response.data]) + return None + + async def _one_managed_file(**kwargs): + return FileListPage( + data=[_managed_file("unified-file-id")], + first_id="unified-file-id", + last_id="unified-file-id", + ) + + _setup_unscoped_list_files_route(mocker, monkeypatch, llm_router, _one_managed_file) + ps.proxy_logging_obj.post_call_success_hook = _reads_response_data + + response = _get_unscoped_list_files("") + + assert response.status_code == 200, response.text + assert seen_by_callback == [["unified-file-id"]] + body = response.json() + assert list(body) == ["object", "data", "first_id", "last_id", "has_more"] + assert body["object"] == "list" + assert [file["id"] for file in body["data"]] == ["unified-file-id"] + assert body["has_more"] is False + + +@pytest.mark.parametrize("purpose", ["nonexistent_purpose", "EVALS", "batch "]) +def test_unscoped_list_files_returns_400_for_a_purpose_the_api_never_accepts( + mocker: MockerFixture, monkeypatch, llm_router: Router, purpose +): + """An unknown purpose matches nothing, so reporting an empty page would dress + a bad request up as a successful one. The provider-backed branches reject the + same values, and so does the upload route.""" + from urllib.parse import quote + + _setup_unscoped_list_files_route(mocker, monkeypatch, llm_router, _validating_afile_list) + + response = _get_list_files(f"/v1/files?purpose={quote(purpose)}") + + assert response.status_code == 400, response.text + assert response.json()["error"]["param"] == "purpose" + assert response.json()["error"]["type"] == "invalid_request_error" + assert response.json()["error"]["message"].startswith(f"Invalid purpose: {purpose}. Must be one of: ") + + +@pytest.mark.parametrize("purpose", ["batch", "assistants", "fine-tune"]) +def test_unscoped_list_files_accepts_every_documented_purpose( + mocker: MockerFixture, monkeypatch, llm_router: Router, purpose +): + managed_files = _setup_unscoped_list_files_route(mocker, monkeypatch, llm_router, _validating_afile_list) + + response = _get_list_files(f"/v1/files?purpose={purpose}") + + assert response.status_code == 200, response.text + assert managed_files.afile_list.await_args.kwargs["purpose"] == purpose + + +def test_list_files_reports_a_bad_target_model_names_as_a_400( + mocker: MockerFixture, monkeypatch, llm_router: Router +): + """The exception tail reports an HTTPException with its own status and error + type rather than relabelling it, so a client that branches on either keeps + reading the same thing off a bad request.""" + _setup_unscoped_list_files_route(mocker, monkeypatch, llm_router, _permissive_afile_list) + + response = _get_list_files("/v1/files?target_model_names=gpt-3.5-turbo,gpt-4o") + + assert response.status_code == 400, response.text + assert response.json() == { + "error": { + "message": "target_model_names on list files must be a list of one model name. Example: ['gpt-4o']", + "type": "None", + "param": "None", + "code": "400", + } + } + + +def test_list_files_reports_an_unexpected_file_store_error_as_a_500( + mocker: MockerFixture, monkeypatch, llm_router: Router +): + async def _blows_up(**kwargs): + raise RuntimeError("managed file table is unreachable") + + _setup_unscoped_list_files_route(mocker, monkeypatch, llm_router, _blows_up) + + response = _get_unscoped_list_files("") + + assert response.status_code == 500, response.text + assert response.json()["error"]["message"] == "managed file table is unreachable" + + def test_list_files_restricted_team_does_not_leak_global_openai_credentials( mocker: MockerFixture, monkeypatch ): diff --git a/tests/test_litellm/proxy/pass_through_endpoints/llm_provider_handlers/test_anthropic_passthrough_logging_handler.py b/tests/test_litellm/proxy/pass_through_endpoints/llm_provider_handlers/test_anthropic_passthrough_logging_handler.py index 7985faa9e4b..8163d009fef 100644 --- a/tests/test_litellm/proxy/pass_through_endpoints/llm_provider_handlers/test_anthropic_passthrough_logging_handler.py +++ b/tests/test_litellm/proxy/pass_through_endpoints/llm_provider_handlers/test_anthropic_passthrough_logging_handler.py @@ -1,16 +1,11 @@ import asyncio import json -import os -import sys from datetime import datetime from typing import Any, Dict, List from unittest.mock import AsyncMock, MagicMock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj from litellm.proxy.pass_through_endpoints.llm_provider_handlers.anthropic_passthrough_logging_handler import ( diff --git a/tests/test_litellm/proxy/pass_through_endpoints/llm_provider_handlers/test_cohere_passthrough_logging_handler.py b/tests/test_litellm/proxy/pass_through_endpoints/llm_provider_handlers/test_cohere_passthrough_logging_handler.py index 6d7011fe10c..814c1a14f3d 100644 --- a/tests/test_litellm/proxy/pass_through_endpoints/llm_provider_handlers/test_cohere_passthrough_logging_handler.py +++ b/tests/test_litellm/proxy/pass_through_endpoints/llm_provider_handlers/test_cohere_passthrough_logging_handler.py @@ -1,13 +1,10 @@ import json -import os -import sys from datetime import datetime from unittest.mock import MagicMock, patch import httpx import pytest -sys.path.insert(0, os.path.abspath("../../..")) # Adds the parent directory to the system path from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj from litellm.proxy.pass_through_endpoints.llm_provider_handlers.cohere_passthrough_logging_handler import ( diff --git a/tests/test_litellm/proxy/pass_through_endpoints/llm_provider_handlers/test_comprehend_medical_passthrough_logging_handler.py b/tests/test_litellm/proxy/pass_through_endpoints/llm_provider_handlers/test_comprehend_medical_passthrough_logging_handler.py index 1804877e688..20ec78cc8de 100644 --- a/tests/test_litellm/proxy/pass_through_endpoints/llm_provider_handlers/test_comprehend_medical_passthrough_logging_handler.py +++ b/tests/test_litellm/proxy/pass_through_endpoints/llm_provider_handlers/test_comprehend_medical_passthrough_logging_handler.py @@ -1,12 +1,9 @@ -import os -import sys from datetime import datetime from unittest.mock import MagicMock import httpx import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm.proxy.pass_through_endpoints.llm_provider_handlers.comprehend_medical_passthrough_logging_handler import ( ComprehendMedicalPassthroughLoggingHandler, diff --git a/tests/test_litellm/proxy/pass_through_endpoints/llm_provider_handlers/test_cursor_passthrough_logging_handler.py b/tests/test_litellm/proxy/pass_through_endpoints/llm_provider_handlers/test_cursor_passthrough_logging_handler.py index 2d025a871b7..af2bb1c816e 100644 --- a/tests/test_litellm/proxy/pass_through_endpoints/llm_provider_handlers/test_cursor_passthrough_logging_handler.py +++ b/tests/test_litellm/proxy/pass_through_endpoints/llm_provider_handlers/test_cursor_passthrough_logging_handler.py @@ -1,12 +1,9 @@ -import os -import sys from datetime import datetime from unittest.mock import MagicMock import httpx import pytest -sys.path.insert(0, os.path.abspath("../../../../..")) from litellm.proxy.pass_through_endpoints.llm_provider_handlers.cursor_passthrough_logging_handler import ( CursorPassthroughLoggingHandler, diff --git a/tests/test_litellm/proxy/pass_through_endpoints/llm_provider_handlers/test_gemini_passthrough_logging_handler.py b/tests/test_litellm/proxy/pass_through_endpoints/llm_provider_handlers/test_gemini_passthrough_logging_handler.py index fae6b6122f5..61d1caacb91 100644 --- a/tests/test_litellm/proxy/pass_through_endpoints/llm_provider_handlers/test_gemini_passthrough_logging_handler.py +++ b/tests/test_litellm/proxy/pass_through_endpoints/llm_provider_handlers/test_gemini_passthrough_logging_handler.py @@ -1,15 +1,10 @@ import json -import os -import sys from datetime import datetime from unittest.mock import AsyncMock, MagicMock, patch import httpx import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj from litellm.proxy.pass_through_endpoints.llm_provider_handlers.gemini_passthrough_logging_handler import ( diff --git a/tests/test_litellm/proxy/pass_through_endpoints/llm_provider_handlers/test_openai_passthrough_logging_handler.py b/tests/test_litellm/proxy/pass_through_endpoints/llm_provider_handlers/test_openai_passthrough_logging_handler.py index 69819318800..f0b2feeb377 100644 --- a/tests/test_litellm/proxy/pass_through_endpoints/llm_provider_handlers/test_openai_passthrough_logging_handler.py +++ b/tests/test_litellm/proxy/pass_through_endpoints/llm_provider_handlers/test_openai_passthrough_logging_handler.py @@ -1,6 +1,4 @@ import json -import os -import sys from datetime import datetime from typing import Any, Dict, List from unittest.mock import AsyncMock, MagicMock, patch @@ -8,7 +6,6 @@ from unittest.mock import AsyncMock, MagicMock, patch import httpx import pytest -sys.path.insert(0, os.path.abspath("../../..")) # Adds the parent directory to the system path from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj from litellm.proxy.pass_through_endpoints.llm_provider_handlers.openai_passthrough_logging_handler import ( diff --git a/tests/test_litellm/proxy/pass_through_endpoints/test_llm_pass_through_endpoints.py b/tests/test_litellm/proxy/pass_through_endpoints/test_llm_pass_through_endpoints.py index 6568f6aeacf..ac140abe31f 100644 --- a/tests/test_litellm/proxy/pass_through_endpoints/test_llm_pass_through_endpoints.py +++ b/tests/test_litellm/proxy/pass_through_endpoints/test_llm_pass_through_endpoints.py @@ -1,7 +1,6 @@ import contextlib import json import os -import sys import traceback from collections.abc import Mapping from types import MappingProxyType, SimpleNamespace @@ -14,9 +13,6 @@ import pytest from fastapi import HTTPException, Request, Response from fastapi.testclient import TestClient -sys.path.insert( - 0, os.path.abspath("../../../..") -) # Adds the parent directory to the system path import litellm from litellm.proxy.pass_through_endpoints.llm_passthrough_endpoints import ( diff --git a/tests/test_litellm/proxy/pass_through_endpoints/test_pass_through_endpoints.py b/tests/test_litellm/proxy/pass_through_endpoints/test_pass_through_endpoints.py index 4c6ba23c88c..25d176e48bb 100644 --- a/tests/test_litellm/proxy/pass_through_endpoints/test_pass_through_endpoints.py +++ b/tests/test_litellm/proxy/pass_through_endpoints/test_pass_through_endpoints.py @@ -2,7 +2,6 @@ import asyncio import json import logging import os -import sys from contextlib import ExitStack, contextmanager from io import BytesIO from types import SimpleNamespace @@ -15,7 +14,6 @@ from fastapi import Request, UploadFile from starlette.datastructures import FormData, Headers, QueryParams from starlette.datastructures import UploadFile as StarletteUploadFile -sys.path.insert(0, os.path.abspath("../../..")) # Adds the parent directory to the system path from litellm.proxy.pass_through_endpoints.pass_through_endpoints import ( DEFAULT_PASS_THROUGH_REQUEST_TIMEOUT_SECONDS, diff --git a/tests/test_litellm/proxy/pass_through_endpoints/test_passthrough_auth_default.py b/tests/test_litellm/proxy/pass_through_endpoints/test_passthrough_auth_default.py index 4cac1cb4d3b..44a75c362e5 100644 --- a/tests/test_litellm/proxy/pass_through_endpoints/test_passthrough_auth_default.py +++ b/tests/test_litellm/proxy/pass_through_endpoints/test_passthrough_auth_default.py @@ -19,14 +19,11 @@ defaults to ``True`` so a config dict (raw, not Pydantic) without an ``auth`` key still requires authentication. """ -import os -import sys from unittest.mock import AsyncMock, MagicMock import pytest from fastapi import FastAPI -sys.path.insert(0, os.path.abspath("../../../..")) from litellm.proxy._types import PassThroughGenericEndpoint from litellm.proxy.auth.user_api_key_auth import ( diff --git a/tests/test_litellm/proxy/pass_through_endpoints/test_passthrough_endpoints_common_utils.py b/tests/test_litellm/proxy/pass_through_endpoints/test_passthrough_endpoints_common_utils.py index 797b22784ae..37d2141e460 100644 --- a/tests/test_litellm/proxy/pass_through_endpoints/test_passthrough_endpoints_common_utils.py +++ b/tests/test_litellm/proxy/pass_through_endpoints/test_passthrough_endpoints_common_utils.py @@ -1,6 +1,4 @@ import json -import os -import sys import traceback from unittest import mock from unittest.mock import MagicMock, patch @@ -12,9 +10,6 @@ from fastapi.testclient import TestClient from litellm.passthrough.utils import CommonUtils -sys.path.insert( - 0, os.path.abspath("../../../..") -) # Adds the parent directory to the system path from unittest.mock import Mock diff --git a/tests/test_litellm/proxy/pass_through_endpoints/test_passthrough_guardrails_field_targeting.py b/tests/test_litellm/proxy/pass_through_endpoints/test_passthrough_guardrails_field_targeting.py index 84856fcb0b1..23f258f0362 100644 --- a/tests/test_litellm/proxy/pass_through_endpoints/test_passthrough_guardrails_field_targeting.py +++ b/tests/test_litellm/proxy/pass_through_endpoints/test_passthrough_guardrails_field_targeting.py @@ -6,13 +6,10 @@ and send only specified fields to the guardrail. """ import json -import os -import sys from unittest.mock import AsyncMock, MagicMock import pytest -sys.path.insert(0, os.path.abspath("../..")) from litellm.proxy._types import PassThroughGuardrailSettings from litellm.proxy.pass_through_endpoints.passthrough_guardrails import ( diff --git a/tests/test_litellm/proxy/pass_through_endpoints/test_upstream_usage_headers.py b/tests/test_litellm/proxy/pass_through_endpoints/test_upstream_usage_headers.py index 34c345b620f..701c583a4ab 100644 --- a/tests/test_litellm/proxy/pass_through_endpoints/test_upstream_usage_headers.py +++ b/tests/test_litellm/proxy/pass_through_endpoints/test_upstream_usage_headers.py @@ -1,10 +1,7 @@ -import os -import sys import httpx import pytest -sys.path.insert(0, os.path.abspath("../../../..")) from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj from litellm.proxy.pass_through_endpoints.upstream_usage_headers import ( diff --git a/tests/test_litellm/proxy/pass_through_endpoints/test_watsonx_proxy_route.py b/tests/test_litellm/proxy/pass_through_endpoints/test_watsonx_proxy_route.py index 19a2f7a0506..5500bb0aad9 100644 --- a/tests/test_litellm/proxy/pass_through_endpoints/test_watsonx_proxy_route.py +++ b/tests/test_litellm/proxy/pass_through_endpoints/test_watsonx_proxy_route.py @@ -6,16 +6,11 @@ and version parameter injection. """ import json -import os -import sys from unittest.mock import AsyncMock, MagicMock, Mock, patch import pytest from fastapi import HTTPException, Request, Response -sys.path.insert( - 0, os.path.abspath("../../../..") -) # Adds the parent directory to the system path import litellm from litellm.proxy._types import UserAPIKeyAuth diff --git a/tests/test_litellm/proxy/proxy_server/test_proxy_config.py b/tests/test_litellm/proxy/proxy_server/test_proxy_config.py index b0b2c68e30d..ee0de8840f6 100644 --- a/tests/test_litellm/proxy/proxy_server/test_proxy_config.py +++ b/tests/test_litellm/proxy/proxy_server/test_proxy_config.py @@ -26,6 +26,7 @@ from litellm.proxy.proxy_server import ( _scrub_guardrail_inner, resolve_complexity_router_plugins, resolve_routing_plugins, + validate_deployment_max_agentic_loops, ) from .conftest import normalize @@ -153,6 +154,71 @@ def test_resolve_complexity_router_plugins_resolves_dotted_path_to_live_instance assert type(config["plugins"][0]).__name__ == "_Plugin" +def test_validate_deployment_max_agentic_loops_allows_a_deployment_without_the_key(): + model = {"model_name": "gpt-4o", "litellm_params": {"model": "gpt-4o"}} + + validate_deployment_max_agentic_loops(model) + + assert "max_agentic_loops" not in model["litellm_params"] + + +def test_validate_deployment_max_agentic_loops_leaves_a_valid_ceiling_alone(): + model = {"model_name": "gpt-4o", "litellm_params": {"model": "gpt-4o", "max_agentic_loops": 5}} + + validate_deployment_max_agentic_loops(model) + + assert model["litellm_params"]["max_agentic_loops"] == 5 + + +def test_validate_deployment_max_agentic_loops_rejects_zero(): + """ + A per-deployment 0 used to be swallowed by an `or 3` and read as the default + ceiling of 3, handing the loosest setting to whoever asked for the tightest. + """ + with pytest.raises(ValueError, match="must be at least 1, got 0"): + validate_deployment_max_agentic_loops( + {"model_name": "gpt-4o", "litellm_params": {"model": "gpt-4o", "max_agentic_loops": 0}} + ) + + +def test_validate_deployment_max_agentic_loops_rejects_a_non_integer(): + """ + A per-deployment non-integer used to let the proxy boot and then fail every + request to that model with `invalid literal for int() with base 10`. + """ + with pytest.raises(TypeError, match="must be an integer"): + validate_deployment_max_agentic_loops( + {"model_name": "gpt-4o", "litellm_params": {"model": "gpt-4o", "max_agentic_loops": "three"}} + ) + + +def test_validate_deployment_max_agentic_loops_rejects_a_bool(): + with pytest.raises(TypeError, match="must be an integer"): + validate_deployment_max_agentic_loops( + {"model_name": "gpt-4o", "litellm_params": {"model": "gpt-4o", "max_agentic_loops": True}} + ) + + +def test_validate_deployment_max_agentic_loops_accepts_a_ceiling_from_an_env_var(): + """ + `max_agentic_loops: os.environ/MAX_AGENTIC_LOOPS` is resolved to a string + before this check runs, and the old `int(... or 3)` accepted that, so + refusing it here would stop an already working proxy from booting. + """ + model = {"model_name": "gpt-4o", "litellm_params": {"model": "gpt-4o", "max_agentic_loops": "5"}} + + validate_deployment_max_agentic_loops(model) + + assert model["litellm_params"]["max_agentic_loops"] == "5" + + +def test_validate_deployment_max_agentic_loops_names_the_offending_model(): + with pytest.raises(ValueError, match="on model 'claude-sonnet-4-5'"): + validate_deployment_max_agentic_loops( + {"model_name": "claude-sonnet-4-5", "litellm_params": {"max_agentic_loops": -1}} + ) + + def test_resolve_complexity_router_plugins_rejects_non_routing_plugin_object(tmp_path): plugin_file = tmp_path / "bad_plugin.py" plugin_file.write_text("not_a_plugin = object()\n") diff --git a/tests/test_litellm/proxy/public_endpoints/test_public_endpoints.py b/tests/test_litellm/proxy/public_endpoints/test_public_endpoints.py index 72e7b1c18d6..31430da71e8 100644 --- a/tests/test_litellm/proxy/public_endpoints/test_public_endpoints.py +++ b/tests/test_litellm/proxy/public_endpoints/test_public_endpoints.py @@ -1,11 +1,8 @@ -import os -import sys from datetime import datetime, timezone from unittest.mock import AsyncMock, MagicMock, patch import pytest -sys.path.insert(0, os.path.abspath("../../..")) from fastapi import FastAPI from fastapi.testclient import TestClient diff --git a/tests/test_litellm/proxy/rag_endpoints/test_rag_endpoints.py b/tests/test_litellm/proxy/rag_endpoints/test_rag_endpoints.py index 15a117bd6fc..b08de04e801 100644 --- a/tests/test_litellm/proxy/rag_endpoints/test_rag_endpoints.py +++ b/tests/test_litellm/proxy/rag_endpoints/test_rag_endpoints.py @@ -6,16 +6,11 @@ Covers: """ import io -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import pytest from fastapi.testclient import TestClient -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path from litellm.proxy._types import LitellmUserRoles, UserAPIKeyAuth from litellm.proxy.auth.user_api_key_auth import user_api_key_auth diff --git a/tests/test_litellm/proxy/realtime_endpoints/test_realtime_webrtc_endpoints.py b/tests/test_litellm/proxy/realtime_endpoints/test_realtime_webrtc_endpoints.py index 9840de8bcb1..66eeb3cef34 100644 --- a/tests/test_litellm/proxy/realtime_endpoints/test_realtime_webrtc_endpoints.py +++ b/tests/test_litellm/proxy/realtime_endpoints/test_realtime_webrtc_endpoints.py @@ -5,8 +5,6 @@ Tests for LiteLLM proxy realtime WebRTC HTTP endpoints: """ import json -import os -import sys import time from unittest.mock import AsyncMock, MagicMock, patch @@ -14,7 +12,6 @@ import httpx import pytest from fastapi.testclient import TestClient -sys.path.insert(0, os.path.abspath("../../../..")) from litellm.proxy._types import UserAPIKeyAuth from litellm.proxy.auth.user_api_key_auth import user_api_key_auth diff --git a/tests/test_litellm/proxy/spend_tracking/test_cloudzero_endpoints.py b/tests/test_litellm/proxy/spend_tracking/test_cloudzero_endpoints.py index dbab627d76f..45aa065380d 100644 --- a/tests/test_litellm/proxy/spend_tracking/test_cloudzero_endpoints.py +++ b/tests/test_litellm/proxy/spend_tracking/test_cloudzero_endpoints.py @@ -1,11 +1,8 @@ -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import pytest from fastapi.testclient import TestClient -sys.path.insert(0, os.path.abspath("../../../..")) import litellm.proxy.proxy_server as ps from litellm.proxy._types import LitellmUserRoles, UserAPIKeyAuth diff --git a/tests/test_litellm/proxy/spend_tracking/test_savings.py b/tests/test_litellm/proxy/spend_tracking/test_savings.py index 227c824afd7..bb8345a9142 100644 --- a/tests/test_litellm/proxy/spend_tracking/test_savings.py +++ b/tests/test_litellm/proxy/spend_tracking/test_savings.py @@ -1,7 +1,4 @@ -import os -import sys -sys.path.insert(0, os.path.abspath("../../../..")) import pytest diff --git a/tests/test_litellm/proxy/spend_tracking/test_spend_management_endpoints.py b/tests/test_litellm/proxy/spend_tracking/test_spend_management_endpoints.py index 24e209a2537..2b062d9020d 100644 --- a/tests/test_litellm/proxy/spend_tracking/test_spend_management_endpoints.py +++ b/tests/test_litellm/proxy/spend_tracking/test_spend_management_endpoints.py @@ -2,18 +2,13 @@ import asyncio import collections import datetime import json -import os import re -import sys from datetime import timezone import pytest from fastapi import HTTPException from fastapi.testclient import TestClient -sys.path.insert( - 0, os.path.abspath("../../../..") -) # Adds the parent directory to the system path from unittest.mock import AsyncMock, MagicMock, patch diff --git a/tests/test_litellm/proxy/spend_tracking/test_spend_query_optimization.py b/tests/test_litellm/proxy/spend_tracking/test_spend_query_optimization.py index 19083486974..ef68d9ce178 100644 --- a/tests/test_litellm/proxy/spend_tracking/test_spend_query_optimization.py +++ b/tests/test_litellm/proxy/spend_tracking/test_spend_query_optimization.py @@ -6,14 +6,11 @@ GitHub Issue: #17487 """ import datetime -import os -import sys from datetime import timezone from unittest.mock import AsyncMock, MagicMock import pytest -sys.path.insert(0, os.path.abspath("../../../..")) from litellm.proxy.spend_tracking.spend_tracking_utils import ( get_spend_by_team, diff --git a/tests/test_litellm/proxy/spend_tracking/test_spend_tracking_utils.py b/tests/test_litellm/proxy/spend_tracking/test_spend_tracking_utils.py index e2c1a835750..6c8e641642b 100644 --- a/tests/test_litellm/proxy/spend_tracking/test_spend_tracking_utils.py +++ b/tests/test_litellm/proxy/spend_tracking/test_spend_tracking_utils.py @@ -1,16 +1,11 @@ import asyncio import datetime import json -import os -import sys from datetime import timezone from typing import Any, Final, cast import pytest -sys.path.insert( - 0, os.path.abspath("../../../..") -) # Adds the parent directory to the system path from unittest.mock import AsyncMock, MagicMock, patch diff --git a/tests/test_litellm/proxy/test_batch_expiry.py b/tests/test_litellm/proxy/test_batch_expiry.py index 38c4a71608d..f7b8fbde0fb 100644 --- a/tests/test_litellm/proxy/test_batch_expiry.py +++ b/tests/test_litellm/proxy/test_batch_expiry.py @@ -2,15 +2,10 @@ Tests for batch output_expires_after passthrough and team-level expiry enforcement. """ -import os -import sys from unittest.mock import MagicMock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path import litellm from litellm.caching.caching import DualCache diff --git a/tests/test_litellm/proxy/test_batch_metadata_none_fix.py b/tests/test_litellm/proxy/test_batch_metadata_none_fix.py index dbc2a402032..aba9b190b66 100644 --- a/tests/test_litellm/proxy/test_batch_metadata_none_fix.py +++ b/tests/test_litellm/proxy/test_batch_metadata_none_fix.py @@ -5,8 +5,6 @@ This test verifies that the fix for handling None metadata in batch requests wor """ import asyncio -import os -import sys from unittest.mock import patch, MagicMock, AsyncMock import pytest @@ -16,9 +14,6 @@ import litellm from litellm.proxy.litellm_pre_call_utils import LiteLLMProxyRequestSetup from litellm.proxy._types import UserAPIKeyAuth -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path def test_add_key_level_controls_with_none_metadata(): diff --git a/tests/test_litellm/proxy/test_batch_retrieve_bedrock.py b/tests/test_litellm/proxy/test_batch_retrieve_bedrock.py index 13945750092..50d531d22d8 100644 --- a/tests/test_litellm/proxy/test_batch_retrieve_bedrock.py +++ b/tests/test_litellm/proxy/test_batch_retrieve_bedrock.py @@ -14,14 +14,11 @@ must round-trip through `client.files.content(...)` back to bedrock with AWS credentials and the raw S3 URI intact. """ -import os -import sys import httpx import pytest from fastapi.testclient import TestClient -sys.path.insert(0, os.path.abspath("../../..")) import litellm from litellm.caching.caching import DualCache diff --git a/tests/test_litellm/proxy/test_caching_routes.py b/tests/test_litellm/proxy/test_caching_routes.py index 840ba054cc9..707d4a3f2c9 100644 --- a/tests/test_litellm/proxy/test_caching_routes.py +++ b/tests/test_litellm/proxy/test_caching_routes.py @@ -1,13 +1,8 @@ import json -import os -import sys import pytest from fastapi.testclient import TestClient -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path import litellm diff --git a/tests/test_litellm/proxy/test_custom_proxy.py b/tests/test_litellm/proxy/test_custom_proxy.py index 3663183d211..b646a4e80e7 100644 --- a/tests/test_litellm/proxy/test_custom_proxy.py +++ b/tests/test_litellm/proxy/test_custom_proxy.py @@ -1,5 +1,4 @@ import os -import sys import uvicorn from dotenv import load_dotenv @@ -8,9 +7,6 @@ from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import JSONResponse load_dotenv() -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path # Set the SERVER_ROOT_PATH environment variable to match the custom mount path os.environ["SERVER_ROOT_PATH"] = "/my-custom-path" diff --git a/tests/test_litellm/proxy/test_empty_model_list.py b/tests/test_litellm/proxy/test_empty_model_list.py index dde2f06126a..dd4643fcf90 100644 --- a/tests/test_litellm/proxy/test_empty_model_list.py +++ b/tests/test_litellm/proxy/test_empty_model_list.py @@ -5,16 +5,11 @@ These tests verify that /v2/model/info and /model_group/info endpoints return empty data arrays instead of 500 errors when no models are configured. """ -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import pytest from fastapi.testclient import TestClient -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system-path from litellm.proxy._types import LitellmUserRoles, UserAPIKeyAuth from litellm.proxy.proxy_server import app diff --git a/tests/test_litellm/proxy/test_fastapi_offline_routes.py b/tests/test_litellm/proxy/test_fastapi_offline_routes.py index f3fc3d3ea28..e06e87ed344 100644 --- a/tests/test_litellm/proxy/test_fastapi_offline_routes.py +++ b/tests/test_litellm/proxy/test_fastapi_offline_routes.py @@ -5,12 +5,7 @@ This test verifies that the /routes endpoint works correctly when the proxy server is initialized using FastAPIOffline instead of regular FastAPI. """ -import os -import sys -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path import pytest from fastapi.testclient import TestClient diff --git a/tests/test_litellm/proxy/test_filter_models_by_team_access_group.py b/tests/test_litellm/proxy/test_filter_models_by_team_access_group.py index 2d8a9f30c1b..1a514ed2c57 100644 --- a/tests/test_litellm/proxy/test_filter_models_by_team_access_group.py +++ b/tests/test_litellm/proxy/test_filter_models_by_team_access_group.py @@ -7,13 +7,10 @@ looking up deployments — matching the behavior of the auth path in auth_checks.py:model_in_access_group(). """ -import os -import sys from unittest.mock import AsyncMock, MagicMock import pytest -sys.path.insert(0, os.path.abspath("../../..")) from litellm.proxy.proxy_server import _filter_models_by_team_id diff --git a/tests/test_litellm/proxy/test_health_check_functions.py b/tests/test_litellm/proxy/test_health_check_functions.py index f223241baf4..f2d95131e5e 100644 --- a/tests/test_litellm/proxy/test_health_check_functions.py +++ b/tests/test_litellm/proxy/test_health_check_functions.py @@ -1,13 +1,10 @@ import asyncio -import os -import sys import time from datetime import datetime, timedelta, timezone from unittest.mock import AsyncMock, MagicMock, patch import pytest -sys.path.insert(0, os.path.abspath("../../..")) from litellm.proxy.health_endpoints._health_endpoints import ( _aggregate_health_check_results, diff --git a/tests/test_litellm/proxy/test_litellm_pre_call_utils.py b/tests/test_litellm/proxy/test_litellm_pre_call_utils.py index 264376495ec..111f11f85ba 100644 --- a/tests/test_litellm/proxy/test_litellm_pre_call_utils.py +++ b/tests/test_litellm/proxy/test_litellm_pre_call_utils.py @@ -2,10 +2,10 @@ import asyncio import copy import json import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import pytest +from botocore.credentials import Credentials from fastapi import Request from pydantic import ValidationError as PydanticValidationError from starlette.datastructures import Headers @@ -26,17 +26,19 @@ from litellm.proxy.litellm_pre_call_utils import ( _update_model_if_key_alias_exists, add_guardrails_from_policy_engine, add_litellm_data_to_request, + add_provider_specific_headers_to_request, check_if_token_is_service_account, clean_headers, ) +from litellm.litellm_core_utils.get_provider_specific_headers import ( + ProviderSpecificHeaderUtils, +) from litellm.litellm_core_utils.initialize_dynamic_callback_params import ( TRUSTED_CALLBACK_VARS_FIELD, ) +from litellm.llms.bedrock.base_aws_llm import BaseAWSLLM from litellm.types.utils import CredentialItem -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path def test_check_if_token_is_service_account(): @@ -6334,7 +6336,17 @@ async def test_add_litellm_data_to_request_redacts_oauth_header_from_logging_cop assert updated["proxy_server_request"]["headers"] is updated[metadata_variable_name]["headers"] - assert updated["provider_specific_header"]["extra_headers"]["Authorization"] == _OAUTH_TOKEN + from litellm.litellm_core_utils.get_provider_specific_headers import ( + ProviderSpecificHeaderUtils, + ) + + assert ( + ProviderSpecificHeaderUtils.get_provider_specific_headers( + provider_specific_header=updated["provider_specific_header"], + custom_llm_provider="anthropic", + )["Authorization"] + == _OAUTH_TOKEN + ) @pytest.mark.asyncio @@ -7008,3 +7020,193 @@ async def test_add_litellm_data_to_request_caller_tags_empty_when_caller_sends_n assert updated["metadata"]["tags"] == ["key-supplied"] assert updated["metadata"]["caller_tags"] == () + + +OAUTH_TOKEN = "Bearer sk-ant-oat01-fake-subscription-token-for-testing-0123456789" +GOOGLE_ACCESS_TOKEN = "Bearer ya29.fake-google-access-token-for-testing" +BEDROCK_API_KEY = "ABSKQmVkcm9ja0FQSUtleUZvclRlc3Rpbmc=" +CROSS_ACCOUNT_AUTHORIZATION = "Bearer deliberately-configured-pass-through-token" + +SIGV4_PREFIX = "AWS4-HMAC-SHA256" +AUTHORIZATION_HEADER_CASINGS = ["authorization", "Authorization", "AUTHORIZATION"] +LEAK_TARGET_PROVIDERS = ["bedrock", "bedrock_converse", "vertex_ai"] + +BEDROCK_ENDPOINT = ( + "https://bedrock-runtime.us-west-2.amazonaws.com" + "/model/us.anthropic.claude-sonnet-4-5-20250929-v1:0/invoke" +) +BEDROCK_REGION = "us-west-2" +BEDROCK_REQUEST_DATA = {"messages": [{"role": "user", "content": "Say OK"}], "max_tokens": 32} +SIGV4_OPTIONAL_PARAMS = { + "aws_access_key_id": "AKIAIOSFODNN7EXAMPLE", + "aws_secret_access_key": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "aws_region_name": BEDROCK_REGION, +} + + +def _client_headers(authorization_header_name: str | None = "authorization") -> dict: + headers = { + "content-type": "application/json", + "anthropic-version": "2023-06-01", + "user-agent": "claude-cli/2.1.239", + } + if authorization_header_name is not None: + headers[authorization_header_name] = OAUTH_TOKEN + return headers + + +def _headers_forwarded_to(client_headers: dict, custom_llm_provider: str) -> dict: + data: dict = {} + add_provider_specific_headers_to_request(data=data, headers=client_headers) + return ProviderSpecificHeaderUtils.get_provider_specific_headers( + provider_specific_header=data.get("provider_specific_header"), + custom_llm_provider=custom_llm_provider, + ) + + +def _authorization_values(headers) -> list: + return [value for name, value in headers.items() if name.lower() == "authorization"] + + +def _signed_headers_for_bedrock(request_headers: dict, api_key: str | None = None) -> dict: + with patch.dict(os.environ, {"AWS_BEARER_TOKEN_BEDROCK": ""}): + signed_headers, _ = BaseAWSLLM()._sign_request( + service_name="bedrock", + headers=request_headers, + optional_params=SIGV4_OPTIONAL_PARAMS, + request_data=BEDROCK_REQUEST_DATA, + api_base=BEDROCK_ENDPOINT, + api_key=api_key, + ) + return signed_headers + + +def _signed_headers_component(signature: str, component: str) -> str: + for part in signature.removeprefix(SIGV4_PREFIX).split(","): + name, _, value = part.strip().partition("=") + if name == component: + return value + raise AssertionError(f"{component} missing from {signature}") + + +@pytest.mark.parametrize("authorization_header_name", AUTHORIZATION_HEADER_CASINGS) +@pytest.mark.parametrize("custom_llm_provider", LEAK_TARGET_PROVIDERS) +def test_oauth_credential_is_never_forwarded_to_bedrock_or_vertex( + authorization_header_name, custom_llm_provider +): + """ + A client's Anthropic OAuth credential is meaningless to AWS and Google, and sending it + there both breaks the request and hands a third-party cloud a credential it should + never hold. It must not survive the pre-call path for any non-Anthropic provider. + """ + forwarded = _headers_forwarded_to(_client_headers(authorization_header_name), custom_llm_provider) + + assert _authorization_values(forwarded) == [] + assert OAUTH_TOKEN not in forwarded.values() + + +@pytest.mark.parametrize("authorization_header_name", AUTHORIZATION_HEADER_CASINGS) +def test_oauth_credential_still_reaches_anthropic_unchanged(authorization_header_name): + forwarded = _headers_forwarded_to(_client_headers(authorization_header_name), "anthropic") + + assert forwarded[authorization_header_name] == OAUTH_TOKEN + assert _authorization_values(forwarded) == [OAUTH_TOKEN] + + +def test_oauth_credential_entry_is_scoped_to_anthropic_alone(): + data: dict = {} + add_provider_specific_headers_to_request(data=data, headers=_client_headers()) + + scoped_headers = data["provider_specific_header"] + if not isinstance(scoped_headers, list): + scoped_headers = [scoped_headers] + + credential_entries = [ + entry for entry in scoped_headers if OAUTH_TOKEN in entry["extra_headers"].values() + ] + assert [entry["custom_llm_provider"] for entry in credential_entries] == ["anthropic"] + + +def test_no_provider_specific_header_when_client_sends_nothing_anthropic(): + data: dict = {} + add_provider_specific_headers_to_request( + data=data, headers={"content-type": "application/json", "authorization": "Bearer sk-a-normal-key"} + ) + + assert "provider_specific_header" not in data + + +def test_bedrock_sigv4_signature_survives_a_client_oauth_header(): + forwarded = _headers_forwarded_to(_client_headers(), "bedrock") + + signed = _signed_headers_for_bedrock({"Content-Type": "application/json", **forwarded}) + + authorizations = _authorization_values(signed) + assert len(authorizations) == 1 + assert authorizations[0].startswith(SIGV4_PREFIX) + assert signed["X-Amz-Date"] + + +def test_bedrock_sigv4_signing_is_unchanged_by_the_client_oauth_header(): + without_oauth = _signed_headers_for_bedrock( + {"Content-Type": "application/json", **_headers_forwarded_to(_client_headers(None), "bedrock")} + ) + with_oauth = _signed_headers_for_bedrock( + {"Content-Type": "application/json", **_headers_forwarded_to(_client_headers(), "bedrock")} + ) + + assert without_oauth["Authorization"].startswith(SIGV4_PREFIX) + assert _signed_headers_component(with_oauth["Authorization"], "SignedHeaders") == ( + _signed_headers_component(without_oauth["Authorization"], "SignedHeaders") + ) + + +def test_bedrock_get_request_headers_keeps_the_sigv4_signature(): + forwarded = _headers_forwarded_to(_client_headers(), "bedrock") + + with patch.dict(os.environ, {"AWS_BEARER_TOKEN_BEDROCK": ""}): + prepped = BaseAWSLLM().get_request_headers( + credentials=Credentials( + SIGV4_OPTIONAL_PARAMS["aws_access_key_id"], + SIGV4_OPTIONAL_PARAMS["aws_secret_access_key"], + ), + aws_region_name=BEDROCK_REGION, + extra_headers=forwarded, + endpoint_url=BEDROCK_ENDPOINT, + data=json.dumps(BEDROCK_REQUEST_DATA), + headers={"Content-Type": "application/json", **forwarded}, + ) + + authorizations = _authorization_values(prepped.headers) + assert len(authorizations) == 1 + assert authorizations[0].startswith(SIGV4_PREFIX) + + +def test_bedrock_api_key_deployment_keeps_its_own_bearer_token(): + forwarded = _headers_forwarded_to(_client_headers(), "bedrock") + + signed = _signed_headers_for_bedrock( + {"Content-Type": "application/json", **forwarded}, api_key=BEDROCK_API_KEY + ) + + assert _authorization_values(signed) == [f"Bearer {BEDROCK_API_KEY}"] + + +def test_deliberately_configured_authorization_still_overrides_sigv4(): + signed = _signed_headers_for_bedrock( + {"Content-Type": "application/json", "Authorization": CROSS_ACCOUNT_AUTHORIZATION} + ) + + assert _authorization_values(signed) == [CROSS_ACCOUNT_AUTHORIZATION] + + +def test_vertex_sends_exactly_one_authorization_header(): + forwarded = _headers_forwarded_to(_client_headers(), "vertex_ai") + + vertex_request_headers = { + "content-type": "application/json", + "Authorization": GOOGLE_ACCESS_TOKEN, + } + vertex_request_headers.update(forwarded) + + assert _authorization_values(vertex_request_headers) == [GOOGLE_ACCESS_TOKEN] diff --git a/tests/test_litellm/proxy/test_model_deprecations_endpoint.py b/tests/test_litellm/proxy/test_model_deprecations_endpoint.py index c942408bd14..6495cf408e1 100644 --- a/tests/test_litellm/proxy/test_model_deprecations_endpoint.py +++ b/tests/test_litellm/proxy/test_model_deprecations_endpoint.py @@ -1,11 +1,8 @@ -import os -import sys from unittest.mock import MagicMock import pytest from fastapi.testclient import TestClient -sys.path.insert(0, os.path.abspath("../../..")) import litellm from litellm.proxy import proxy_server diff --git a/tests/test_litellm/proxy/test_pricing_field_strip.py b/tests/test_litellm/proxy/test_pricing_field_strip.py index bbdddd1cd8c..1707f5bbc05 100644 --- a/tests/test_litellm/proxy/test_pricing_field_strip.py +++ b/tests/test_litellm/proxy/test_pricing_field_strip.py @@ -10,8 +10,6 @@ strips them at the boundary; an opt-in key/team flag preserves the override for operators who actually want it. """ -import os -import sys from unittest.mock import MagicMock import pytest @@ -27,7 +25,6 @@ from litellm.proxy.litellm_pre_call_utils import ( ) from litellm.types.utils import CustomPricingLiteLLMParams -sys.path.insert(0, os.path.abspath("../../..")) def _make_request_mock() -> Request: diff --git a/tests/test_litellm/proxy/test_prisma_migration.py b/tests/test_litellm/proxy/test_prisma_migration.py index 01b768ea8dc..729adcfb9e0 100644 --- a/tests/test_litellm/proxy/test_prisma_migration.py +++ b/tests/test_litellm/proxy/test_prisma_migration.py @@ -34,24 +34,22 @@ class TestPrismaMigration: mock_run_server.assert_called_once_with(("--skip_server_startup",), standalone_mode=False) + @pytest.mark.parametrize("env", [{}, {"ENFORCE_PRISMA_MIGRATION_CHECK": "false"}]) @patch("litellm.proxy.prisma_migration.subprocess.run") @patch("litellm.proxy.prisma_migration.run_server") - def test_main_returns_prisma_generate_exit_code_when_enforced( - self, mock_run_server: MagicMock, mock_subprocess_run: MagicMock + def test_main_exits_zero_when_only_prisma_generate_fails( + self, + mock_run_server: MagicMock, + mock_subprocess_run: MagicMock, + env: dict[str, str], ) -> None: - mock_subprocess_run.return_value = MagicMock(returncode=7, stdout="", stderr="") + mock_subprocess_run.return_value = MagicMock( + returncode=1, + stdout="", + stderr="PermissionError: [Errno 13] Permission denied: '/app/.venv/lib/python3.13/site-packages/prisma/schema.prisma'", + ) - with patch.dict(os.environ, {}, clear=True): - assert prisma_migration.main() == 7 - - @patch("litellm.proxy.prisma_migration.subprocess.run") - @patch("litellm.proxy.prisma_migration.run_server") - def test_main_ignores_prisma_generate_exit_code_when_disabled( - self, mock_run_server: MagicMock, mock_subprocess_run: MagicMock - ) -> None: - mock_subprocess_run.return_value = MagicMock(returncode=7, stdout="", stderr="") - - with patch.dict(os.environ, {"ENFORCE_PRISMA_MIGRATION_CHECK": "false"}, clear=True): + with patch.dict(os.environ, env, clear=True): assert prisma_migration.main() == 0 @patch("litellm.proxy.prisma_migration.subprocess.run") diff --git a/tests/test_litellm/proxy/test_provider_url_destination_guard.py b/tests/test_litellm/proxy/test_provider_url_destination_guard.py index cd993a076e8..24c4e991adf 100644 --- a/tests/test_litellm/proxy/test_provider_url_destination_guard.py +++ b/tests/test_litellm/proxy/test_provider_url_destination_guard.py @@ -6,8 +6,6 @@ an SSRF primitive — guarded centrally in ``litellm_pre_call_utils`` so SDK users keep working but proxy users default-deny. """ -import os -import sys from unittest.mock import MagicMock import pytest @@ -20,7 +18,6 @@ from litellm.proxy.litellm_pre_call_utils import ( add_litellm_data_to_request, ) -sys.path.insert(0, os.path.abspath("../../..")) class TestRejectUrlValuedDestinations: diff --git a/tests/test_litellm/proxy/test_proxy_cli.py b/tests/test_litellm/proxy/test_proxy_cli.py index 48c56a41ad5..6ea6f208bb5 100644 --- a/tests/test_litellm/proxy/test_proxy_cli.py +++ b/tests/test_litellm/proxy/test_proxy_cli.py @@ -1,6 +1,5 @@ import inspect import os -import sys from pathlib import Path from types import SimpleNamespace from unittest.mock import AsyncMock, MagicMock, patch @@ -9,9 +8,6 @@ import click import fastapi import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system-path import builtins import types diff --git a/tests/test_litellm/proxy/test_proxy_server.py b/tests/test_litellm/proxy/test_proxy_server.py index a0ca33da737..31d2a6cef98 100644 --- a/tests/test_litellm/proxy/test_proxy_server.py +++ b/tests/test_litellm/proxy/test_proxy_server.py @@ -5,7 +5,6 @@ import os import re import socket import subprocess -import sys import types from datetime import datetime, timedelta, timezone from pathlib import Path @@ -20,7 +19,6 @@ from fastapi import FastAPI from fastapi.staticfiles import StaticFiles from fastapi.testclient import TestClient -sys.path.insert(0, os.path.abspath("../../..")) # Adds the parent directory to the system-path import litellm import litellm.proxy.proxy_server as proxy_server_module diff --git a/tests/test_litellm/proxy/test_proxy_types.py b/tests/test_litellm/proxy/test_proxy_types.py index 77083af48c0..634b90e445a 100644 --- a/tests/test_litellm/proxy/test_proxy_types.py +++ b/tests/test_litellm/proxy/test_proxy_types.py @@ -1,10 +1,8 @@ import asyncio import importlib import json -import os import socket import subprocess -import sys from unittest import mock from unittest.mock import AsyncMock, MagicMock, mock_open, patch @@ -15,9 +13,6 @@ import yaml from fastapi import FastAPI from fastapi.testclient import TestClient -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system-path def test_audit_log_masking(): diff --git a/tests/test_litellm/proxy/test_proxy_utils.py b/tests/test_litellm/proxy/test_proxy_utils.py index deb49ff9f54..fb01216982f 100644 --- a/tests/test_litellm/proxy/test_proxy_utils.py +++ b/tests/test_litellm/proxy/test_proxy_utils.py @@ -1,7 +1,5 @@ import datetime as real_datetime -import os import smtplib -import sys import pytest from fastapi import HTTPException @@ -12,9 +10,6 @@ from litellm.proxy._types import ProxyErrorTypes from litellm.proxy.utils import ProxyLogging from litellm.types.guardrails import GuardrailEventHooks -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from unittest.mock import MagicMock, patch diff --git a/tests/test_litellm/proxy/test_response_model_sanitization.py b/tests/test_litellm/proxy/test_response_model_sanitization.py index 621291b8331..c20b1208e8f 100644 --- a/tests/test_litellm/proxy/test_response_model_sanitization.py +++ b/tests/test_litellm/proxy/test_response_model_sanitization.py @@ -1,7 +1,5 @@ import asyncio import json -import os -import sys from typing import AsyncGenerator from unittest.mock import AsyncMock, MagicMock @@ -9,7 +7,6 @@ import pytest import yaml from fastapi.testclient import TestClient -sys.path.insert(0, os.path.abspath("../../..")) import litellm diff --git a/tests/test_litellm/proxy/test_route_a2a_models.py b/tests/test_litellm/proxy/test_route_a2a_models.py index 0523e796543..35308474949 100644 --- a/tests/test_litellm/proxy/test_route_a2a_models.py +++ b/tests/test_litellm/proxy/test_route_a2a_models.py @@ -4,10 +4,7 @@ Test A2A model routing in proxy. Maps to: litellm/proxy/agent_endpoints/a2a_routing.py """ -import os -import sys -sys.path.insert(0, os.path.abspath("../../..")) from unittest.mock import AsyncMock, Mock, patch diff --git a/tests/test_litellm/proxy/test_route_llm_request.py b/tests/test_litellm/proxy/test_route_llm_request.py index 23e0bbfb3ee..41ba57c4615 100644 --- a/tests/test_litellm/proxy/test_route_llm_request.py +++ b/tests/test_litellm/proxy/test_route_llm_request.py @@ -1,9 +1,6 @@ -import os -import sys import pytest -sys.path.insert(0, os.path.abspath("../../..")) # Adds the parent directory to the system path from unittest.mock import MagicMock diff --git a/tests/test_litellm/proxy/ui_crud_endpoints/test_proxy_setting_endpoints.py b/tests/test_litellm/proxy/ui_crud_endpoints/test_proxy_setting_endpoints.py index a1a02ec427b..b85c70cae12 100644 --- a/tests/test_litellm/proxy/ui_crud_endpoints/test_proxy_setting_endpoints.py +++ b/tests/test_litellm/proxy/ui_crud_endpoints/test_proxy_setting_endpoints.py @@ -1,13 +1,9 @@ import json import os -import sys import pytest from fastapi.testclient import TestClient -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from litellm.proxy._types import DefaultInternalUserParams, LitellmUserRoles from litellm.proxy.proxy_server import app diff --git a/tests/test_litellm/proxy/vector_store_endpoints/test_vector_store_endpoints.py b/tests/test_litellm/proxy/vector_store_endpoints/test_vector_store_endpoints.py index 20b2f68bb0c..905928428b7 100644 --- a/tests/test_litellm/proxy/vector_store_endpoints/test_vector_store_endpoints.py +++ b/tests/test_litellm/proxy/vector_store_endpoints/test_vector_store_endpoints.py @@ -1,14 +1,9 @@ -import os -import sys from datetime import datetime, timezone from unittest.mock import AsyncMock, MagicMock, patch import pytest from fastapi import Request -sys.path.insert( - 0, os.path.abspath("../../../../..") -) # Adds the parent directory to the system path from fastapi import HTTPException diff --git a/tests/test_litellm/proxy/vector_store_files_endpoints/test_endpoints.py b/tests/test_litellm/proxy/vector_store_files_endpoints/test_endpoints.py index da5dd1934e4..4cb3a3d4c7f 100644 --- a/tests/test_litellm/proxy/vector_store_files_endpoints/test_endpoints.py +++ b/tests/test_litellm/proxy/vector_store_files_endpoints/test_endpoints.py @@ -10,15 +10,12 @@ is attached to a vector store or read back under shared provider credentials. """ import base64 -import os -import sys from dataclasses import dataclass from typing import Literal from unittest.mock import MagicMock, patch import pytest -sys.path.insert(0, os.path.abspath("../../../..")) from fastapi import HTTPException diff --git a/tests/test_litellm/proxy/video_endpoints/test_endpoints.py b/tests/test_litellm/proxy/video_endpoints/test_endpoints.py index 40a26fad3c3..a959326817c 100644 --- a/tests/test_litellm/proxy/video_endpoints/test_endpoints.py +++ b/tests/test_litellm/proxy/video_endpoints/test_endpoints.py @@ -26,8 +26,6 @@ patched with autospec so the real __init__ still stores self.data (captured via mock's call args), and a brand-new kwarg added to this layer surfaces as a failure. """ -import os -import sys from contextlib import ExitStack from dataclasses import dataclass from typing import Any, Dict, Optional @@ -36,7 +34,6 @@ from unittest.mock import AsyncMock, MagicMock, patch import orjson import pytest -sys.path.insert(0, os.path.abspath("../../../..")) import litellm.proxy.proxy_server as proxy_server import litellm.proxy.video_endpoints.endpoints as endpoints diff --git a/tests/test_litellm/proxy/video_endpoints/test_utils.py b/tests/test_litellm/proxy/video_endpoints/test_utils.py index ae22ae233b5..efbaaff5f4b 100644 --- a/tests/test_litellm/proxy/video_endpoints/test_utils.py +++ b/tests/test_litellm/proxy/video_endpoints/test_utils.py @@ -12,12 +12,9 @@ is encode_character_id_with_provider, which runs for real; encoding assertions are checked by the genuine decode round-trip. """ -import os -import sys import pytest -sys.path.insert(0, os.path.abspath("../../../..")) from litellm.proxy.video_endpoints.utils import ( encode_character_id_in_response, diff --git a/tests/test_litellm/realtime_api/test_main.py b/tests/test_litellm/realtime_api/test_main.py index 9f48d4d427b..a0c0d849e3e 100644 --- a/tests/test_litellm/realtime_api/test_main.py +++ b/tests/test_litellm/realtime_api/test_main.py @@ -1,10 +1,7 @@ import asyncio -import os -import sys import time from unittest.mock import MagicMock -sys.path.insert(0, os.path.abspath("../../..")) import pytest diff --git a/tests/test_litellm/rerank_api/test_main.py b/tests/test_litellm/rerank_api/test_main.py index 46d1461da50..85777afe81c 100644 --- a/tests/test_litellm/rerank_api/test_main.py +++ b/tests/test_litellm/rerank_api/test_main.py @@ -1,9 +1,6 @@ import logging -import os -import sys from unittest.mock import MagicMock, patch -sys.path.insert(0, os.path.abspath("../../..")) import litellm diff --git a/tests/test_litellm/responses/litellm_completion_transformation/test_handler.py b/tests/test_litellm/responses/litellm_completion_transformation/test_handler.py index 04db7192364..2cfec6a1844 100644 --- a/tests/test_litellm/responses/litellm_completion_transformation/test_handler.py +++ b/tests/test_litellm/responses/litellm_completion_transformation/test_handler.py @@ -12,13 +12,10 @@ capture the forwarded kwargs; if the flag-setting line is removed the captured kwargs lack the flag and these tests fail. """ -import os -import sys from unittest.mock import patch import pytest -sys.path.insert(0, os.path.abspath("../../../..")) from litellm.responses.litellm_completion_transformation.handler import ( LiteLLMCompletionTransformationHandler, diff --git a/tests/test_litellm/responses/litellm_completion_transformation/test_litellm_completion_responses.py b/tests/test_litellm/responses/litellm_completion_transformation/test_litellm_completion_responses.py index aae053c2e8e..5efabed4b8d 100644 --- a/tests/test_litellm/responses/litellm_completion_transformation/test_litellm_completion_responses.py +++ b/tests/test_litellm/responses/litellm_completion_transformation/test_litellm_completion_responses.py @@ -1,12 +1,7 @@ import json -import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from litellm.responses.litellm_completion_transformation.transformation import ( TOOL_CALLS_CACHE, diff --git a/tests/test_litellm/responses/litellm_completion_transformation/test_session_handler.py b/tests/test_litellm/responses/litellm_completion_transformation/test_session_handler.py index 9c354101e22..19f240fa3d4 100644 --- a/tests/test_litellm/responses/litellm_completion_transformation/test_session_handler.py +++ b/tests/test_litellm/responses/litellm_completion_transformation/test_session_handler.py @@ -1,15 +1,10 @@ import json -import os -import sys from unittest.mock import AsyncMock, patch import pytest from fastapi import HTTPException from fastapi.testclient import TestClient -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path import litellm from litellm.responses.litellm_completion_transformation import session_handler from litellm.responses.litellm_completion_transformation.session_handler import ( diff --git a/tests/test_litellm/responses/test_metadata_codex_callback.py b/tests/test_litellm/responses/test_metadata_codex_callback.py index f7d97b164da..f151f36be63 100644 --- a/tests/test_litellm/responses/test_metadata_codex_callback.py +++ b/tests/test_litellm/responses/test_metadata_codex_callback.py @@ -10,12 +10,9 @@ verifies metadata is preserved for custom callbacks via kwargs['litellm_params'] """ import asyncio -import os -import sys from typing import Optional from unittest.mock import AsyncMock, patch -sys.path.insert(0, os.path.abspath("../../..")) import pytest diff --git a/tests/test_litellm/responses/test_no_duplicate_spend_logs.py b/tests/test_litellm/responses/test_no_duplicate_spend_logs.py index 3ef5935933a..c98b519ae67 100644 --- a/tests/test_litellm/responses/test_no_duplicate_spend_logs.py +++ b/tests/test_litellm/responses/test_no_duplicate_spend_logs.py @@ -7,14 +7,9 @@ causing duplicate spend log entries for non-OpenAI providers. """ import asyncio -import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path import litellm from litellm.integrations.custom_logger import CustomLogger diff --git a/tests/test_litellm/responses/test_responses_api_bridge_flag.py b/tests/test_litellm/responses/test_responses_api_bridge_flag.py index f94c31831bf..d76fa59a888 100644 --- a/tests/test_litellm/responses/test_responses_api_bridge_flag.py +++ b/tests/test_litellm/responses/test_responses_api_bridge_flag.py @@ -6,13 +6,8 @@ Includes file_search emulation: the flag must be forwarded on inner aresponses calls so routed requests do not hit a custom api_base /v1/responses endpoint. """ -import os -import sys from unittest.mock import MagicMock, patch -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path import litellm from litellm.types.llms.openai import ResponseAPIUsage, ResponsesAPIResponse diff --git a/tests/test_litellm/responses/test_responses_router_cooldown.py b/tests/test_litellm/responses/test_responses_router_cooldown.py index 48e2d2455e7..e173c174521 100644 --- a/tests/test_litellm/responses/test_responses_router_cooldown.py +++ b/tests/test_litellm/responses/test_responses_router_cooldown.py @@ -6,14 +6,11 @@ the "No model_info found" branch and the failing deployment was never added to the cooldown set. """ -import os -import sys from unittest.mock import AsyncMock, patch import httpx import pytest -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm.router_utils.cooldown_handlers import _async_get_cooldown_deployments diff --git a/tests/test_litellm/responses/test_responses_utils.py b/tests/test_litellm/responses/test_responses_utils.py index 2f4a699d307..dddb851acf9 100644 --- a/tests/test_litellm/responses/test_responses_utils.py +++ b/tests/test_litellm/responses/test_responses_utils.py @@ -1,11 +1,8 @@ import base64 -import os -import sys from unittest.mock import MagicMock, patch import pytest -sys.path.insert(0, os.path.abspath("../../..")) # Adds the parent directory to the system path import litellm from litellm.llms.openai.responses.transformation import OpenAIResponsesAPIConfig diff --git a/tests/test_litellm/responses/test_streaming_iterator_error_events.py b/tests/test_litellm/responses/test_streaming_iterator_error_events.py index 321abe4cc6d..9c344fc6894 100644 --- a/tests/test_litellm/responses/test_streaming_iterator_error_events.py +++ b/tests/test_litellm/responses/test_streaming_iterator_error_events.py @@ -15,13 +15,10 @@ Pydantic ValidationError (previously typed as Optional[str]). """ import json -import os -import sys from unittest.mock import Mock, patch import pytest -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm.exceptions import MidStreamFallbackError diff --git a/tests/test_litellm/responses/test_text_format_conversion.py b/tests/test_litellm/responses/test_text_format_conversion.py index a48540b129b..cca7748fd3a 100644 --- a/tests/test_litellm/responses/test_text_format_conversion.py +++ b/tests/test_litellm/responses/test_text_format_conversion.py @@ -1,13 +1,8 @@ import json -import os -import sys import pytest from pydantic import BaseModel -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path import litellm from litellm.types.llms.openai import ( @@ -158,7 +153,6 @@ class TestTextFormatConversion: new=mock_handler, ): litellm._turn_on_debug() - litellm.set_verbose = True # Call aresponses with text_format parameter response = await litellm.aresponses( diff --git a/tests/test_litellm/router_strategy/test_auto_router.py b/tests/test_litellm/router_strategy/test_auto_router.py index c71a6b0e27f..36199b45847 100644 --- a/tests/test_litellm/router_strategy/test_auto_router.py +++ b/tests/test_litellm/router_strategy/test_auto_router.py @@ -1,15 +1,10 @@ import asyncio import json -import os -import sys from typing import Any, Dict, Final, List, Optional from unittest.mock import AsyncMock, MagicMock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path from litellm.router_strategy.auto_router.auto_router import AutoRouter diff --git a/tests/test_litellm/router_strategy/test_base_routing_strategy.py b/tests/test_litellm/router_strategy/test_base_routing_strategy.py index 70259605b2f..154042692d0 100644 --- a/tests/test_litellm/router_strategy/test_base_routing_strategy.py +++ b/tests/test_litellm/router_strategy/test_base_routing_strategy.py @@ -1,13 +1,8 @@ import json -import os -import sys from typing import Any, Dict, List, Optional, Set, Union import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path import asyncio from unittest.mock import MagicMock, patch diff --git a/tests/test_litellm/router_strategy/test_complexity_router.py b/tests/test_litellm/router_strategy/test_complexity_router.py index 64b60c75f87..e65d79a83f4 100644 --- a/tests/test_litellm/router_strategy/test_complexity_router.py +++ b/tests/test_litellm/router_strategy/test_complexity_router.py @@ -6,15 +6,12 @@ Tests the rule-based complexity scoring and tier assignment logic. import asyncio import logging -import os -import sys from typing import Dict, List from unittest.mock import AsyncMock, MagicMock, patch import pytest from pydantic import ValidationError -sys.path.insert(0, os.path.abspath("../../..")) # Adds the parent directory to the system path import litellm from litellm import Router diff --git a/tests/test_litellm/router_strategy/test_litellm_encoder.py b/tests/test_litellm/router_strategy/test_litellm_encoder.py index 6c934e57832..ebd6efe309c 100644 --- a/tests/test_litellm/router_strategy/test_litellm_encoder.py +++ b/tests/test_litellm/router_strategy/test_litellm_encoder.py @@ -1,12 +1,9 @@ """Tests for litellm/router_strategy/auto_router/litellm_encoder.py""" -import os -import sys from typing import Any, Final import pytest -sys.path.insert(0, os.path.abspath("../../..")) import litellm from litellm.constants import DEFAULT_AUTO_ROUTER_MAX_INPUT_CHARS diff --git a/tests/test_litellm/router_strategy/test_lowest_latency.py b/tests/test_litellm/router_strategy/test_lowest_latency.py index 4edc1e21d6b..6701f4a7aa2 100644 --- a/tests/test_litellm/router_strategy/test_lowest_latency.py +++ b/tests/test_litellm/router_strategy/test_lowest_latency.py @@ -5,15 +5,10 @@ # latency list and break the Redis cache sync). Issue #33169. import json -import os -import sys from datetime import datetime, timedelta import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path import litellm from litellm.caching.caching import DualCache diff --git a/tests/test_litellm/router_strategy/test_quality_router.py b/tests/test_litellm/router_strategy/test_quality_router.py index a54e95ff7a1..4e87652f8b3 100644 --- a/tests/test_litellm/router_strategy/test_quality_router.py +++ b/tests/test_litellm/router_strategy/test_quality_router.py @@ -9,14 +9,11 @@ Covers: - Decision metadata stash + Router.set_response_headers lift. """ -import os -import sys from typing import Any, Dict, List from unittest.mock import MagicMock import pytest -sys.path.insert(0, os.path.abspath("../../..")) from litellm.router_strategy.quality_router.config import ( DEFAULT_COMPLEXITY_TO_QUALITY, diff --git a/tests/test_litellm/router_strategy/test_router_routing_groups.py b/tests/test_litellm/router_strategy/test_router_routing_groups.py index 7d1ed796996..5599c5aad63 100644 --- a/tests/test_litellm/router_strategy/test_router_routing_groups.py +++ b/tests/test_litellm/router_strategy/test_router_routing_groups.py @@ -5,13 +5,10 @@ the implicit `"default"` group driven by the router's top-level `routing_strategy` / `routing_strategy_args`. """ -import os -import sys from unittest.mock import patch import pytest -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm import Router diff --git a/tests/test_litellm/router_strategy/test_router_tag_regex_routing.py b/tests/test_litellm/router_strategy/test_router_tag_regex_routing.py index 6591478a4e7..212c2627d88 100644 --- a/tests/test_litellm/router_strategy/test_router_tag_regex_routing.py +++ b/tests/test_litellm/router_strategy/test_router_tag_regex_routing.py @@ -6,12 +6,9 @@ patterns, verifying that regex-based header matching works correctly alongside existing tag-based routing. """ -import os -import sys import pytest -sys.path.insert(0, os.path.abspath("../..")) from unittest.mock import MagicMock diff --git a/tests/test_litellm/router_strategy/test_router_tag_routing.py b/tests/test_litellm/router_strategy/test_router_tag_routing.py index 752136f2b66..72bb6756d24 100644 --- a/tests/test_litellm/router_strategy/test_router_tag_routing.py +++ b/tests/test_litellm/router_strategy/test_router_tag_routing.py @@ -1,14 +1,10 @@ #### What this tests #### # This tests litellm router -import os -import sys import pytest -sys.path.insert(0, os.path.abspath("../..")) # Adds the parent directory to the system path import logging -import os import litellm diff --git a/tests/test_litellm/router_utils/pre_call_checks/test_deployment_affinity_check.py b/tests/test_litellm/router_utils/pre_call_checks/test_deployment_affinity_check.py index 428eb0ceafd..b3a2bdda53c 100644 --- a/tests/test_litellm/router_utils/pre_call_checks/test_deployment_affinity_check.py +++ b/tests/test_litellm/router_utils/pre_call_checks/test_deployment_affinity_check.py @@ -1,11 +1,8 @@ import asyncio -import os -import sys from unittest.mock import AsyncMock, patch import pytest -sys.path.insert(0, os.path.abspath("../..")) import json diff --git a/tests/test_litellm/router_utils/pre_call_checks/test_encrypted_content_affinity_check.py b/tests/test_litellm/router_utils/pre_call_checks/test_encrypted_content_affinity_check.py index 510dcf77afd..dac991a41c4 100644 --- a/tests/test_litellm/router_utils/pre_call_checks/test_encrypted_content_affinity_check.py +++ b/tests/test_litellm/router_utils/pre_call_checks/test_encrypted_content_affinity_check.py @@ -15,15 +15,12 @@ The mechanism works without any cache and supports two encoding strategies: encrypted_content back to their original forms before sending to the upstream provider. """ -import os -import sys import time from typing import List, Optional from unittest.mock import AsyncMock, patch import pytest -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm.responses.utils import ResponsesAPIRequestUtils diff --git a/tests/test_litellm/router_utils/pre_call_checks/test_prompt_caching_deployment_check.py b/tests/test_litellm/router_utils/pre_call_checks/test_prompt_caching_deployment_check.py index d0fff0201e3..f54a1cfa284 100644 --- a/tests/test_litellm/router_utils/pre_call_checks/test_prompt_caching_deployment_check.py +++ b/tests/test_litellm/router_utils/pre_call_checks/test_prompt_caching_deployment_check.py @@ -1,12 +1,9 @@ import asyncio import copy -import os -import sys from typing import List, cast import pytest -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm.caching.dual_cache import DualCache diff --git a/tests/test_litellm/router_utils/pre_call_checks/test_responses_api_deployment_check.py b/tests/test_litellm/router_utils/pre_call_checks/test_responses_api_deployment_check.py index 3c6a05e7786..ee7fab7d19f 100644 --- a/tests/test_litellm/router_utils/pre_call_checks/test_responses_api_deployment_check.py +++ b/tests/test_litellm/router_utils/pre_call_checks/test_responses_api_deployment_check.py @@ -1,12 +1,9 @@ import asyncio -import os -import sys from typing import Optional from unittest.mock import AsyncMock, patch import pytest -sys.path.insert(0, os.path.abspath("../..")) import json import litellm diff --git a/tests/test_litellm/router_utils/pre_call_checks/test_session_id_affinity.py b/tests/test_litellm/router_utils/pre_call_checks/test_session_id_affinity.py index 4053e6d118b..a3772a276fa 100644 --- a/tests/test_litellm/router_utils/pre_call_checks/test_session_id_affinity.py +++ b/tests/test_litellm/router_utils/pre_call_checks/test_session_id_affinity.py @@ -1,10 +1,7 @@ -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import pytest -sys.path.insert(0, os.path.abspath("../..")) import json diff --git a/tests/test_litellm/router_utils/test_cooldown_cache.py b/tests/test_litellm/router_utils/test_cooldown_cache.py index a48402684b4..68e9aeaa4fc 100644 --- a/tests/test_litellm/router_utils/test_cooldown_cache.py +++ b/tests/test_litellm/router_utils/test_cooldown_cache.py @@ -2,15 +2,12 @@ Unit tests for CooldownCache exception masking functionality """ -import os -import sys import time from unittest.mock import MagicMock import pytest # Add the parent directory to the system path -sys.path.insert(0, os.path.abspath("../../..")) from litellm.caching.dual_cache import DualCache from litellm.caching.in_memory_cache import InMemoryCache diff --git a/tests/test_litellm/secret_managers/test_base_secret_manager.py b/tests/test_litellm/secret_managers/test_base_secret_manager.py index e1ccb91c381..a9c6695eb82 100644 --- a/tests/test_litellm/secret_managers/test_base_secret_manager.py +++ b/tests/test_litellm/secret_managers/test_base_secret_manager.py @@ -3,12 +3,9 @@ Test raise_if_unsafe_secret_name, the shared guard applied before secret_name reaches a secret manager backend. """ -import os -import sys import pytest -sys.path.insert(0, os.path.abspath("../..")) # Adds the parent directory to the system path from litellm.secret_managers.base_secret_manager import raise_if_unsafe_secret_name diff --git a/tests/test_litellm/secret_managers/test_custom_secret_manager.py b/tests/test_litellm/secret_managers/test_custom_secret_manager.py index 0426c5973cc..e22af4f9a18 100644 --- a/tests/test_litellm/secret_managers/test_custom_secret_manager.py +++ b/tests/test_litellm/secret_managers/test_custom_secret_manager.py @@ -2,16 +2,11 @@ Test custom secret manager implementation """ -import os -import sys from typing import Optional, Union import httpx import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm.integrations.custom_secret_manager import CustomSecretManager diff --git a/tests/test_litellm/secret_managers/test_get_azure_ad_token_provider.py b/tests/test_litellm/secret_managers/test_get_azure_ad_token_provider.py index cee0da79802..c9ec22ab0df 100644 --- a/tests/test_litellm/secret_managers/test_get_azure_ad_token_provider.py +++ b/tests/test_litellm/secret_managers/test_get_azure_ad_token_provider.py @@ -1,11 +1,9 @@ import json import os -import sys from typing import Optional from unittest.mock import MagicMock, patch # Adds the grandparent directory to sys.path to allow importing project modules -sys.path.insert(0, os.path.abspath("../..")) import pytest diff --git a/tests/test_litellm/test_a2a_registry_lookup.py b/tests/test_litellm/test_a2a_registry_lookup.py index dd745bfe15b..54393e3ae5e 100644 --- a/tests/test_litellm/test_a2a_registry_lookup.py +++ b/tests/test_litellm/test_a2a_registry_lookup.py @@ -4,10 +4,7 @@ Test A2A provider registry lookup functionality. Maps to: litellm/llms/a2a/chat/transformation.py """ -import os -import sys -sys.path.insert(0, os.path.abspath("../..")) import pytest diff --git a/tests/test_litellm/test_acompletion_session_reuse_e2e.py b/tests/test_litellm/test_acompletion_session_reuse_e2e.py index 79b947bb146..2c0bc32f84b 100644 --- a/tests/test_litellm/test_acompletion_session_reuse_e2e.py +++ b/tests/test_litellm/test_acompletion_session_reuse_e2e.py @@ -12,13 +12,10 @@ wasting ~100-500ms per request. With reuse, connections are pooled and subsequent requests are 40-60% faster. """ -import os -import sys import inspect import pytest -sys.path.insert(0, os.path.abspath("../../..")) import litellm diff --git a/tests/test_litellm/test_add_deployment_no_master_key.py b/tests/test_litellm/test_add_deployment_no_master_key.py index f7a0e90dad0..2973f1a8f69 100644 --- a/tests/test_litellm/test_add_deployment_no_master_key.py +++ b/tests/test_litellm/test_add_deployment_no_master_key.py @@ -6,12 +6,10 @@ failed when master_key was None. [https://github.com/BerriAI/litellm/issues/1642 """ import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import pytest -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm.proxy.proxy_server import ProxyConfig diff --git a/tests/test_litellm/test_aembedding_session_reuse_e2e.py b/tests/test_litellm/test_aembedding_session_reuse_e2e.py index b24aab72fdb..15662d4d35c 100644 --- a/tests/test_litellm/test_aembedding_session_reuse_e2e.py +++ b/tests/test_litellm/test_aembedding_session_reuse_e2e.py @@ -5,11 +5,8 @@ Ensures shared_session is in all_litellm_params to prevent "Object of type ClientSession is not JSON serializable" errors. """ -import os -import sys import inspect -sys.path.insert(0, os.path.abspath("../../..")) from litellm.types.utils import all_litellm_params diff --git a/tests/test_litellm/test_command_r7b_pricing.py b/tests/test_litellm/test_command_r7b_pricing.py index b952c365910..498fc0ef55a 100644 --- a/tests/test_litellm/test_command_r7b_pricing.py +++ b/tests/test_litellm/test_command_r7b_pricing.py @@ -11,11 +11,7 @@ swap cannot silently regress. import json import os -import sys -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm diff --git a/tests/test_litellm/test_constants.py b/tests/test_litellm/test_constants.py index b3c13c6e26e..12e473f68a4 100644 --- a/tests/test_litellm/test_constants.py +++ b/tests/test_litellm/test_constants.py @@ -1,8 +1,6 @@ import ast import inspect import json -import os -import sys from unittest import mock import httpx @@ -10,7 +8,6 @@ import pytest import respx from fastapi.testclient import TestClient -sys.path.insert(0, os.path.abspath("../..")) # import importlib diff --git a/tests/test_litellm/test_cost_calculation_log_level.py b/tests/test_litellm/test_cost_calculation_log_level.py index f5c03771cd7..f8d3557c572 100644 --- a/tests/test_litellm/test_cost_calculation_log_level.py +++ b/tests/test_litellm/test_cost_calculation_log_level.py @@ -1,10 +1,7 @@ """Test that cost calculation uses appropriate log levels""" import logging -import os -import sys -sys.path.insert(0, os.path.abspath("../../..")) import litellm from litellm import completion_cost diff --git a/tests/test_litellm/test_count_tokens_public_api.py b/tests/test_litellm/test_count_tokens_public_api.py index ebd9c0c9edb..86c33c3e8f7 100644 --- a/tests/test_litellm/test_count_tokens_public_api.py +++ b/tests/test_litellm/test_count_tokens_public_api.py @@ -4,10 +4,8 @@ Tests for litellm.acount_tokens() public API. import asyncio import os -import sys from unittest.mock import AsyncMock, patch -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm.types.utils import TokenCountResponse diff --git a/tests/test_litellm/test_deepseek_model_metadata.py b/tests/test_litellm/test_deepseek_model_metadata.py index 4900af5d97d..b9eb33f0972 100644 --- a/tests/test_litellm/test_deepseek_model_metadata.py +++ b/tests/test_litellm/test_deepseek_model_metadata.py @@ -11,11 +11,7 @@ field set to ``True``. import json import os -import sys -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm.utils import ( diff --git a/tests/test_litellm/test_gpt_image_cost_calculator.py b/tests/test_litellm/test_gpt_image_cost_calculator.py index c371f7442be..d3ec0673fe3 100644 --- a/tests/test_litellm/test_gpt_image_cost_calculator.py +++ b/tests/test_litellm/test_gpt_image_cost_calculator.py @@ -10,10 +10,7 @@ gpt-image-1 uses token-based pricing: - Image Output: $40.00/1M tokens """ -import os -import sys -sys.path.insert(0, os.path.abspath("../..")) import pytest diff --git a/tests/test_litellm/test_lazy_imports.py b/tests/test_litellm/test_lazy_imports.py index f7c9cfa3074..2b16a812611 100644 --- a/tests/test_litellm/test_lazy_imports.py +++ b/tests/test_litellm/test_lazy_imports.py @@ -1,11 +1,9 @@ """Simple tests for lazy import functionality.""" -import os import sys import pytest -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm._lazy_imports import ( diff --git a/tests/test_litellm/test_logging.py b/tests/test_litellm/test_logging.py index 8551085cbd6..db8dfaa3ad6 100644 --- a/tests/test_litellm/test_logging.py +++ b/tests/test_litellm/test_logging.py @@ -1,7 +1,6 @@ import ast import asyncio import json -import os import re import sys from pathlib import Path @@ -9,9 +8,7 @@ from typing import List import pytest -sys.path.insert(0, os.path.abspath("../../..")) # Adds the parent directory to the system-path import logging -import sys import litellm from litellm._logging import ( diff --git a/tests/test_litellm/test_lowest_latency_zero_tokens.py b/tests/test_litellm/test_lowest_latency_zero_tokens.py index b9fc9b00cc7..ff60744e9ee 100644 --- a/tests/test_litellm/test_lowest_latency_zero_tokens.py +++ b/tests/test_litellm/test_lowest_latency_zero_tokens.py @@ -1,14 +1,9 @@ #### What this tests #### # This tests the router's handling of zero completion tokens in lowest latency routing -import os -import sys import time import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm.caching.caching import DualCache diff --git a/tests/test_litellm/test_main.py b/tests/test_litellm/test_main.py index 28762e61861..c05f25430c2 100644 --- a/tests/test_litellm/test_main.py +++ b/tests/test_litellm/test_main.py @@ -2,16 +2,12 @@ import contextlib import copy import json import os -import sys import httpx import pytest import respx from fastapi.testclient import TestClient -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import urllib.parse from unittest.mock import MagicMock, patch @@ -2756,6 +2752,53 @@ def test_completion_default_api_base_sends_prompt_cache_breakpoint_for_gpt_5_6() assert request_body["extra_body"]["prompt_cache_options"] == {"mode": "explicit"} +_SUBSCRIPTION_OAUTH_CREDENTIAL = "Bearer sk-ant-oat01-fake-subscription-token-for-testing-0123456789" + + +def _scoped_headers_for_oauth_request(): + from litellm.types.utils import ProviderSpecificHeader + + return [ + ProviderSpecificHeader( + custom_llm_provider="anthropic,bedrock,vertex_ai", + extra_headers={"anthropic-version": "2023-06-01"}, + ), + ProviderSpecificHeader( + custom_llm_provider="anthropic", + extra_headers={"authorization": _SUBSCRIPTION_OAUTH_CREDENTIAL}, + ), + ] + + +def _run_anthropic_hop_with_shared_headers(shared_headers): + litellm.completion( + model="anthropic/claude-3-5-sonnet-20240620", + messages=[{"role": "user", "content": "Say OK"}], + extra_headers=shared_headers, + provider_specific_header=_scoped_headers_for_oauth_request(), + api_key="sk-fake-anthropic-key", + mock_response="OK", + ) + + +def test_completion_does_not_mutate_caller_supplied_headers(): + shared_headers = {"x-tenant": "acme"} + + _run_anthropic_hop_with_shared_headers(shared_headers) + + assert shared_headers == {"x-tenant": "acme"} + + +def test_anthropic_oauth_credential_does_not_persist_into_next_provider_hop(): + shared_headers = {"x-tenant": "acme"} + + _run_anthropic_hop_with_shared_headers(shared_headers) + + leaked = [name for name, value in shared_headers.items() if value == _SUBSCRIPTION_OAUTH_CREDENTIAL] + assert leaked == [] + assert "anthropic-version" not in shared_headers + + STREAM_COST_MODEL = "gpt-4o" STREAMED_USAGE = {"prompt_tokens": 137, "completion_tokens": 42, "total_tokens": 179} diff --git a/tests/test_litellm/test_non_chat_routes_open_llm_spans.py b/tests/test_litellm/test_non_chat_routes_open_llm_spans.py new file mode 100644 index 00000000000..d62959ccd43 --- /dev/null +++ b/tests/test_litellm/test_non_chat_routes_open_llm_spans.py @@ -0,0 +1,188 @@ +"""Regression tests: every route that issues an upstream call must fire the +``pre_call`` input hook. + +Tracing integrations open their LLM-call span there (``OpenTelemetryV2`` keys the +span off ``log_pre_api_call`` and treats "no pre_call" as "the request never +reached a provider"), so a handler that skips it leaves the call with no LLM-call +span in the trace at all. Speech, async image generation and moderation each used +to skip it. +""" + +import asyncio +from typing import Any, Final + +import httpx +import pytest +from openai import AsyncAzureOpenAI, AsyncOpenAI + +import litellm +from litellm.integrations.custom_logger import CustomLogger + + +class _PreCallRecorder(CustomLogger): + def __init__(self) -> None: + super().__init__() + self.call_types: list[str] = [] # mutable-ok: test recorder of hook calls + self.api_bases: list[str] = [] # mutable-ok: test recorder of hook calls + self.request_bodies: list[Any] = [] # mutable-ok: test recorder of hook calls + + def log_pre_api_call(self, model, messages, kwargs) -> None: + self.call_types.append(str(kwargs.get("call_type"))) + self.api_bases.append(str(kwargs.get("litellm_params", {}).get("api_base"))) + self.request_bodies.append(kwargs.get("additional_args", {}).get("complete_input_dict")) + + +class _FakeSpeech: + def __init__(self) -> None: + self.calls: list[dict[str, Any]] = [] # mutable-ok: test recorder of SDK calls + + async def create(self, **kwargs: Any) -> Any: + self.calls.append(kwargs) + request: Final = httpx.Request("POST", "https://api.openai.com/v1/audio/speech") + return type( + "_Speech", + (), + {"response": httpx.Response(200, content=b"audio-bytes", request=request)}, + )() + + +class _FakeImages: + async def generate(self, **kwargs: Any) -> Any: + return type( + "_Images", + (), + { + "model_dump": lambda self: { + "created": 1, + "data": [{"url": "https://example.com/img.png"}], + } + }, + )() + + +class _FakeModerations: + async def create(self, **kwargs: Any) -> Any: + return type( + "_Moderations", + (), + { + "model_dump": lambda self: { + "id": "modr-1", + "model": "omni-moderation-latest", + "results": [ + { + "flagged": False, + "categories": {}, + "category_scores": {}, + "category_applied_input_types": {}, + } + ], + } + }, + )() + + +class _FakeAsyncOpenAI(AsyncOpenAI): + """Stands in for the injected client: a real ``AsyncOpenAI`` (``amoderation`` + type-checks it) whose resource namespaces answer without a network call.""" + + def __init__(self, base_url: str = "https://api.openai.com/v1") -> None: + super().__init__(api_key="sk-test", base_url=base_url) + self.speech = _FakeSpeech() + self.audio = type("_Audio", (), {"speech": self.speech})() + self.images = _FakeImages() + self.moderations = _FakeModerations() + + +class _FakeAsyncAzureOpenAI(AsyncAzureOpenAI): + """Same idea for the Azure entrypoint, which resolves no default endpoint of + its own when ``AZURE_API_BASE`` is unset.""" + + def __init__(self) -> None: + super().__init__( + api_key="sk-test", + api_version="2024-02-01", + azure_endpoint="https://unit-test.openai.azure.com", + ) + self.speech = _FakeSpeech() + self.audio = type("_Audio", (), {"speech": self.speech})() + + +@pytest.fixture +def recorder(monkeypatch): + recorder: Final = _PreCallRecorder() + monkeypatch.setattr(litellm, "callbacks", [recorder]) + monkeypatch.setattr(litellm, "success_callback", []) + return recorder + + +def test_async_speech_opens_an_llm_span(recorder): + asyncio.run( + litellm.aspeech( + model="openai/tts-1", + input="hello", + voice="alloy", + client=_FakeAsyncOpenAI(), + ) + ) + assert recorder.call_types == ["aspeech"] + + +def test_azure_async_speech_opens_an_llm_span_without_api_base(recorder, monkeypatch): + """Azure resolves no default endpoint, so a missing ``api_base`` used to reach + ``_get_masked_api_base`` as ``None``; the ``TypeError`` was swallowed and the + whole callback dispatch was skipped.""" + monkeypatch.delenv("AZURE_API_BASE", raising=False) + asyncio.run( + litellm.aspeech( + model="azure/tts-deployment", + input="hello", + voice="alloy", + client=_FakeAsyncAzureOpenAI(), + ) + ) + assert recorder.call_types == ["aspeech"] + assert recorder.api_bases == ["https://unit-test.openai.azure.com/openai/"] + + +def test_azure_async_speech_keeps_caller_headers_out_of_the_logged_body(recorder): + """The Azure entrypoint carries caller headers in ``optional_params``, so they reach + the provider as a request kwarg; telemetry reads the logged body, which must stay + free of them.""" + headers: Final = {"authorization": "Bearer caller-secret"} + client: Final = _FakeAsyncAzureOpenAI() + asyncio.run( + litellm.aspeech( + model="azure/tts-deployment", + input="hello", + voice="alloy", + extra_headers=headers, + client=client, + ) + ) + assert recorder.call_types == ["aspeech"] + assert "extra_headers" not in recorder.request_bodies[0] + assert client.speech.calls[0]["extra_headers"] == headers + + +def test_async_image_generation_opens_an_llm_span(recorder): + asyncio.run( + litellm.aimage_generation( + model="openai/dall-e-3", + prompt="a cat", + client=_FakeAsyncOpenAI(), + ) + ) + assert recorder.call_types == ["aimage_generation"] + + +def test_async_moderation_opens_an_llm_span(recorder): + asyncio.run( + litellm.amoderation( + model="omni-moderation-latest", + input="hello", + client=_FakeAsyncOpenAI(base_url="https://gateway.example/v1"), + ) + ) + assert recorder.call_types == ["amoderation"] + assert recorder.api_bases == ["https://gateway.example/v1/"] diff --git a/tests/test_litellm/test_project_alias_tracking.py b/tests/test_litellm/test_project_alias_tracking.py index d18989d543f..476dfba0a27 100644 --- a/tests/test_litellm/test_project_alias_tracking.py +++ b/tests/test_litellm/test_project_alias_tracking.py @@ -5,12 +5,9 @@ Verifies that project_alias flows from UserAPIKeyAuth through the metadata pipel to StandardLoggingMetadata, mirroring how team_alias already works. """ -import os -import sys import pytest -sys.path.insert(0, os.path.abspath("../..")) from litellm.litellm_core_utils.litellm_logging import StandardLoggingPayloadSetup from litellm.proxy._types import LiteLLM_VerificationTokenView, UserAPIKeyAuth diff --git a/tests/test_litellm/test_redact_string_in_error_paths.py b/tests/test_litellm/test_redact_string_in_error_paths.py index 1c4d91397d1..6404db91acf 100644 --- a/tests/test_litellm/test_redact_string_in_error_paths.py +++ b/tests/test_litellm/test_redact_string_in_error_paths.py @@ -9,14 +9,11 @@ Covers actual execution of redaction in: """ import logging -import os -import sys import traceback from unittest.mock import AsyncMock, MagicMock, patch import pytest -sys.path.insert(0, os.path.abspath("../..")) from litellm._logging import _ENABLE_SECRET_REDACTION, _redact_string diff --git a/tests/test_litellm/test_register_model_custom_pricing.py b/tests/test_litellm/test_register_model_custom_pricing.py index dd19334724d..e3f6a1a0f40 100644 --- a/tests/test_litellm/test_register_model_custom_pricing.py +++ b/tests/test_litellm/test_register_model_custom_pricing.py @@ -11,13 +11,9 @@ calculations for DB-sourced models with prompt caching pricing. import copy import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm.main import _build_custom_pricing_entry diff --git a/tests/test_litellm/test_responses_api_bridge_non_stream.py b/tests/test_litellm/test_responses_api_bridge_non_stream.py index 08d55ee8290..617b2cfc031 100644 --- a/tests/test_litellm/test_responses_api_bridge_non_stream.py +++ b/tests/test_litellm/test_responses_api_bridge_non_stream.py @@ -1,11 +1,8 @@ -import os -import sys from typing import Final, Optional from unittest.mock import Mock import pytest -sys.path.insert(0, os.path.abspath("../..")) from litellm.completion_extras.litellm_responses_transformation.handler import ( ResponsesToCompletionBridgeHandler, diff --git a/tests/test_litellm/test_retrieve_batch_bedrock_dispatch.py b/tests/test_litellm/test_retrieve_batch_bedrock_dispatch.py index aa057b7bc73..9d0daa52645 100644 --- a/tests/test_litellm/test_retrieve_batch_bedrock_dispatch.py +++ b/tests/test_litellm/test_retrieve_batch_bedrock_dispatch.py @@ -14,13 +14,10 @@ here is purely the dispatch logic that lives in ``main.py``. from __future__ import annotations -import os -import sys from unittest.mock import MagicMock, patch import pytest -sys.path.insert(0, os.path.abspath("../..")) import litellm # noqa: E402 import openai diff --git a/tests/test_litellm/test_router.py b/tests/test_litellm/test_router.py index 58a500def8e..56e00ecdad6 100644 --- a/tests/test_litellm/test_router.py +++ b/tests/test_litellm/test_router.py @@ -3,15 +3,11 @@ import copy import json import logging import os -import sys import threading from unittest.mock import AsyncMock, MagicMock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path import litellm diff --git a/tests/test_litellm/test_router_exception_redaction.py b/tests/test_litellm/test_router_exception_redaction.py index 2066352e2ce..6754775db22 100644 --- a/tests/test_litellm/test_router_exception_redaction.py +++ b/tests/test_litellm/test_router_exception_redaction.py @@ -115,14 +115,9 @@ def _router_with_credentialed_fallback() -> Router: @pytest.fixture(autouse=True) -def _reset_expose_flag(): +def _reset_expose_flag(monkeypatch: pytest.MonkeyPatch) -> None: """Each test starts with the flag in its default (on) state.""" - original = litellm.expose_router_debug_in_errors - litellm.expose_router_debug_in_errors = True - try: - yield - finally: - litellm.expose_router_debug_in_errors = original + monkeypatch.setattr(litellm, "expose_router_debug_in_errors", True) def test_flag_defaults_on(): @@ -133,8 +128,8 @@ def test_flag_defaults_on(): @pytest.mark.asyncio -async def test_flag_off_does_not_leak_received_model_group(): - litellm.expose_router_debug_in_errors = False +async def test_flag_off_does_not_leak_received_model_group(monkeypatch: pytest.MonkeyPatch): + monkeypatch.setattr(litellm, "expose_router_debug_in_errors", False) router = _router_with_rate_limit_failure() with pytest.raises(litellm.RateLimitError) as excinfo: await router.acompletion( @@ -148,8 +143,8 @@ async def test_flag_off_does_not_leak_received_model_group(): @pytest.mark.asyncio -async def test_flag_on_shows_received_model_group(): - litellm.expose_router_debug_in_errors = True +async def test_flag_on_shows_received_model_group(monkeypatch: pytest.MonkeyPatch): + monkeypatch.setattr(litellm, "expose_router_debug_in_errors", True) router = _router_with_rate_limit_failure() with pytest.raises(litellm.RateLimitError) as excinfo: await router.acompletion( @@ -166,8 +161,8 @@ async def test_flag_on_shows_received_model_group(): @pytest.mark.asyncio -async def test_flag_off_does_not_leak_context_window_fallback_hint(): - litellm.expose_router_debug_in_errors = False +async def test_flag_off_does_not_leak_context_window_fallback_hint(monkeypatch: pytest.MonkeyPatch): + monkeypatch.setattr(litellm, "expose_router_debug_in_errors", False) router = _router_with_context_window_failure() with pytest.raises(litellm.ContextWindowExceededError) as excinfo: await router.acompletion( @@ -181,8 +176,8 @@ async def test_flag_off_does_not_leak_context_window_fallback_hint(): @pytest.mark.asyncio -async def test_flag_on_shows_context_window_fallback_hint(): - litellm.expose_router_debug_in_errors = True +async def test_flag_on_shows_context_window_fallback_hint(monkeypatch: pytest.MonkeyPatch): + monkeypatch.setattr(litellm, "expose_router_debug_in_errors", True) router = _router_with_context_window_failure() with pytest.raises(litellm.ContextWindowExceededError) as excinfo: await router.acompletion( @@ -201,8 +196,8 @@ async def test_flag_on_shows_context_window_fallback_hint(): @pytest.mark.asyncio -async def test_flag_off_does_not_leak_when_no_fallback_group_found(): - litellm.expose_router_debug_in_errors = False +async def test_flag_off_does_not_leak_when_no_fallback_group_found(monkeypatch: pytest.MonkeyPatch): + monkeypatch.setattr(litellm, "expose_router_debug_in_errors", False) router = Router( model_list=[ { @@ -232,8 +227,8 @@ async def test_flag_off_does_not_leak_when_no_fallback_group_found(): @pytest.mark.asyncio -async def test_flag_on_shows_when_no_fallback_group_found(): - litellm.expose_router_debug_in_errors = True +async def test_flag_on_shows_when_no_fallback_group_found(monkeypatch: pytest.MonkeyPatch): + monkeypatch.setattr(litellm, "expose_router_debug_in_errors", True) router = Router( model_list=[ { @@ -284,8 +279,8 @@ def _router_with_plain_deployment() -> Router: @pytest.mark.asyncio -async def test_flag_off_does_not_leak_deployment_timeout_debug(): - litellm.expose_router_debug_in_errors = False +async def test_flag_off_does_not_leak_deployment_timeout_debug(monkeypatch: pytest.MonkeyPatch): + monkeypatch.setattr(litellm, "expose_router_debug_in_errors", False) router = _router_with_plain_deployment() with pytest.raises(litellm.Timeout) as excinfo: await router.acompletion( @@ -299,8 +294,8 @@ async def test_flag_off_does_not_leak_deployment_timeout_debug(): @pytest.mark.asyncio -async def test_flag_on_shows_deployment_timeout_debug(): - litellm.expose_router_debug_in_errors = True +async def test_flag_on_shows_deployment_timeout_debug(monkeypatch: pytest.MonkeyPatch): + monkeypatch.setattr(litellm, "expose_router_debug_in_errors", True) router = _router_with_plain_deployment() with pytest.raises(litellm.Timeout) as excinfo: await router.acompletion( @@ -325,8 +320,8 @@ def _content_policy_error() -> litellm.ContentPolicyViolationError: @pytest.mark.asyncio -async def test_flag_off_does_not_leak_content_policy_fallback_hint(): - litellm.expose_router_debug_in_errors = False +async def test_flag_off_does_not_leak_content_policy_fallback_hint(monkeypatch: pytest.MonkeyPatch): + monkeypatch.setattr(litellm, "expose_router_debug_in_errors", False) router = _router_with_plain_deployment() with pytest.raises(litellm.ContentPolicyViolationError) as excinfo: await router.acompletion( @@ -340,8 +335,8 @@ async def test_flag_off_does_not_leak_content_policy_fallback_hint(): @pytest.mark.asyncio -async def test_flag_on_shows_content_policy_fallback_hint(): - litellm.expose_router_debug_in_errors = True +async def test_flag_on_shows_content_policy_fallback_hint(monkeypatch: pytest.MonkeyPatch): + monkeypatch.setattr(litellm, "expose_router_debug_in_errors", True) router = _router_with_plain_deployment() with pytest.raises(litellm.ContentPolicyViolationError) as excinfo: await router.acompletion( @@ -358,8 +353,8 @@ async def test_flag_on_shows_content_policy_fallback_hint(): @pytest.mark.asyncio -async def test_flag_off_hides_fallback_credentials(): - litellm.expose_router_debug_in_errors = False +async def test_flag_off_hides_fallback_credentials(monkeypatch: pytest.MonkeyPatch): + monkeypatch.setattr(litellm, "expose_router_debug_in_errors", False) router = _router_with_credentialed_fallback() with pytest.raises(litellm.RateLimitError) as excinfo: await router.acompletion( @@ -372,8 +367,8 @@ async def test_flag_off_hides_fallback_credentials(): @pytest.mark.asyncio -async def test_flag_on_masks_fallback_credentials(): - litellm.expose_router_debug_in_errors = True +async def test_flag_on_masks_fallback_credentials(monkeypatch: pytest.MonkeyPatch): + monkeypatch.setattr(litellm, "expose_router_debug_in_errors", True) router = _router_with_credentialed_fallback() with pytest.raises(litellm.RateLimitError) as excinfo: await router.acompletion( @@ -389,14 +384,14 @@ async def test_flag_on_masks_fallback_credentials(): @pytest.mark.asyncio -async def test_flag_on_scrubs_credential_from_inner_fallback_exception_string(): +async def test_flag_on_scrubs_credential_from_inner_fallback_exception_string(monkeypatch: pytest.MonkeyPatch): """If the fallback attempt itself raises an exception whose message embeds a raw provider credential (e.g. a provider SDK echoing back the api_key it was called with), that string is re-embedded via `Error doing the fallback: ...` on the terminal raise. The router must scrub known secret patterns from it. The primary fails with a benign rate-limit; the fallback deployment fails with an exception whose text contains the secret.""" - litellm.expose_router_debug_in_errors = True + monkeypatch.setattr(litellm, "expose_router_debug_in_errors", True) inner_secret = "sk-INNERFALLBACKEXCEPTIONSECRET1234" router = Router( model_list=[ diff --git a/tests/test_litellm/test_router_google_genai.py b/tests/test_litellm/test_router_google_genai.py index 81dd7bbdc40..8a90173bb7f 100644 --- a/tests/test_litellm/test_router_google_genai.py +++ b/tests/test_litellm/test_router_google_genai.py @@ -3,15 +3,10 @@ Test to verify the new Google GenAI router methods """ import asyncio -import os -import sys from unittest.mock import AsyncMock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path import litellm from litellm.types.utils import ModelResponse diff --git a/tests/test_litellm/test_router_model_cost_isolation.py b/tests/test_litellm/test_router_model_cost_isolation.py index 1580ec7f437..b580b03574e 100644 --- a/tests/test_litellm/test_router_model_cost_isolation.py +++ b/tests/test_litellm/test_router_model_cost_isolation.py @@ -8,14 +8,13 @@ should still use the built-in pricing. """ import copy +import logging import os import re -import sys from unittest.mock import patch import pytest -sys.path.insert(0, os.path.abspath("../../..")) # Adds the parent directory to the system path import litellm from litellm import Router @@ -2007,3 +2006,127 @@ def test_a_falsy_id_is_still_scanned_for_collisions(): }, ] ) + + +# --- a reservation declared while the feature is off says so ------------------------ + + +def _ptu_warnings(caplog): + return tuple( + record.getMessage() + for record in caplog.records + if record.name == "LiteLLM Router" and record.levelno == logging.WARNING and "PTU" in record.getMessage() + ) + + +def test_a_reservation_declared_while_the_feature_is_off_is_warned_about(caplog): + """The deployment serves and bills per token, so without this the operator believes they + reserved capacity and sees no signal anywhere that nothing accrues.""" + with caplog.at_level(logging.WARNING, logger="LiteLLM Router"): + _ptu_router(ptu_enabled=False) + + warnings = _ptu_warnings(caplog) + + assert len(warnings) == 1 + assert "gpt-4o-ptu" in warnings[0] + assert "LITELLM_ENABLE_PTU_COST_ATTRIBUTION" in warnings[0] + + +def test_a_reservation_is_not_warned_about_while_the_feature_is_on(caplog): + with caplog.at_level(logging.WARNING, logger="LiteLLM Router"): + _ptu_router() + + assert _ptu_warnings(caplog) == () + + +def test_a_deployment_carrying_no_ptu_field_is_not_warned_about(caplog): + """Most of every config.yaml, so warning here would fire on proxies that never asked.""" + with caplog.at_level(logging.WARNING, logger="LiteLLM Router"): + _ptu_router(model_info={"team_id": "team-alpha"}, ptu_enabled=False) + + assert _ptu_warnings(caplog) == () + + +def test_a_half_written_reservation_is_warned_about(caplog): + """A count with no rate is not a chargeable reservation, but the operator still meant to + declare one, so what they wrote is what decides whether they hear about it.""" + half_written = {k: v for k, v in _PTU_MODEL_INFO.items() if k != "cost_per_ptu_per_hour"} + + with caplog.at_level(logging.WARNING, logger="LiteLLM Router"): + _ptu_router(model_info=half_written, ptu_enabled=False) + + assert len(_ptu_warnings(caplog)) == 1 + + +@pytest.mark.parametrize( + "typo", + [ + {"ptu_count": 0}, + {"ptu_count": 0, "cost_per_ptu_per_hour": 0, "ptu_effective_from": None}, + ], + ids=["count out of range", "every value still a zero placeholder"], +) +def test_a_reservation_dropped_by_a_typo_is_warned_about(caplog, typo): + """An out-of-range value fails ModelInfo before the flag is ever consulted, so the + deployment stops serving on a proxy that never enabled PTU. The warning is what tells the + operator which feature the entry that vanished belonged to. + + Built the way proxy_server builds it, since dropping rather than raising is what + ``ignore_invalid_deployments`` does and config.yaml is loaded with it on. + """ + with patch.dict(os.environ, {"LITELLM_ENABLE_PTU_COST_ATTRIBUTION": ""}, clear=False): + with caplog.at_level(logging.WARNING, logger="LiteLLM Router"): + router = Router( + ignore_invalid_deployments=True, + model_list=[ + { + "model_name": "gpt-4o-ptu", + "litellm_params": {"model": "azure/gpt-4o", "api_key": "k", "api_base": "https://e.azure.com"}, + "model_info": {**_PTU_MODEL_INFO, **typo}, + } + ], + ) + + assert router.model_list == [] + assert len(_ptu_warnings(caplog)) == 1 + + +def test_a_db_backed_reservation_is_not_warned_about(caplog): + """/model/new already answered the caller with a 400, so repeating it on every reload + would report the operator's own rejected write back to them as a standing problem.""" + with caplog.at_level(logging.WARNING, logger="LiteLLM Router"): + _ptu_router(model_info={**_PTU_MODEL_INFO, "db_model": True}, ptu_enabled=False) + + assert _ptu_warnings(caplog) == () + + +def test_every_declaring_deployment_is_named(caplog): + """One line naming all of them, so a reload does not bury the config in repeats.""" + with patch.dict(os.environ, {"LITELLM_ENABLE_PTU_COST_ATTRIBUTION": ""}, clear=False): + with caplog.at_level(logging.WARNING, logger="LiteLLM Router"): + Router( + model_list=[ + { + "model_name": "azure-ptu-east", + "litellm_params": {"model": "azure/gpt-4o", "api_key": "k", "api_base": "https://e.azure.com"}, + "model_info": dict(_PTU_MODEL_INFO), + }, + { + "model_name": "azure-ptu-west", + "litellm_params": {"model": "azure/gpt-4o", "api_key": "k", "api_base": "https://w.azure.com"}, + "model_info": {**_PTU_MODEL_INFO, "id": "ptu-alpha-westus"}, + }, + { + "model_name": "plain-gpt-4o", + "litellm_params": {"model": "azure/gpt-4o", "api_key": "k", "api_base": "https://p.azure.com"}, + "model_info": {"id": "plain"}, + }, + ] + ) + + warnings = _ptu_warnings(caplog) + + assert len(warnings) == 1 + assert "azure-ptu-east" in warnings[0] + assert "azure-ptu-west" in warnings[0] + assert "plain-gpt-4o" not in warnings[0] diff --git a/tests/test_litellm/test_router_retry_policy_update.py b/tests/test_litellm/test_router_retry_policy_update.py index 3fc6bc71b84..1b98b8c1ae8 100644 --- a/tests/test_litellm/test_router_retry_policy_update.py +++ b/tests/test_litellm/test_router_retry_policy_update.py @@ -20,15 +20,12 @@ This file pins both halves of the fix. """ import json -import os -import sys from dataclasses import dataclass from unittest.mock import AsyncMock, MagicMock import pytest from pydantic import ValidationError -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm.types.router import RetryPolicy, UpdateRouterConfig diff --git a/tests/test_litellm/test_shared_session_integration.py b/tests/test_litellm/test_shared_session_integration.py index 4ce704f88cb..fab356db3b6 100644 --- a/tests/test_litellm/test_shared_session_integration.py +++ b/tests/test_litellm/test_shared_session_integration.py @@ -2,14 +2,11 @@ Integration tests for shared session functionality in main.py """ -import os -import sys from unittest.mock import MagicMock, patch import pytest # Add the litellm directory to the path -sys.path.insert(0, os.path.abspath("../../..")) import litellm diff --git a/tests/test_litellm/test_streaming_connection_cleanup.py b/tests/test_litellm/test_streaming_connection_cleanup.py index 5a81a3ffb17..39fcee8d44d 100644 --- a/tests/test_litellm/test_streaming_connection_cleanup.py +++ b/tests/test_litellm/test_streaming_connection_cleanup.py @@ -3,15 +3,12 @@ Regression tests for streaming connection pool leak fix. """ import asyncio -import os -import sys from unittest.mock import MagicMock, patch import anyio import httpx import pytest -sys.path.insert(0, os.path.abspath("../..")) from litellm.litellm_core_utils.streaming_handler import CustomStreamWrapper from litellm.llms.custom_httpx.aiohttp_transport import ( diff --git a/tests/test_litellm/test_utils.py b/tests/test_litellm/test_utils.py index 55150897c52..b418c237e7a 100644 --- a/tests/test_litellm/test_utils.py +++ b/tests/test_litellm/test_utils.py @@ -1,16 +1,12 @@ import json import logging import os -import sys from typing import Final from unittest.mock import AsyncMock, MagicMock, patch import pytest from jsonschema import validate -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm._logging import ( diff --git a/tests/test_litellm/test_video_generation.py b/tests/test_litellm/test_video_generation.py index 117ca72c34f..fb167a8624e 100644 --- a/tests/test_litellm/test_video_generation.py +++ b/tests/test_litellm/test_video_generation.py @@ -2,14 +2,10 @@ import asyncio import io import json import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm.cost_calculator import default_video_cost_calculator @@ -242,7 +238,6 @@ class TestVideoGeneration: def test_video_generation_cost_calculation(self): """Test video generation cost calculation.""" import json - import os # Try to load the local model cost map, skip if not found cost_map_path = "model_prices_and_context_window.json" diff --git a/tests/test_litellm/test_xai_responses_auto_routing.py b/tests/test_litellm/test_xai_responses_auto_routing.py index a4d72bb97d9..5b1944dcb8b 100644 --- a/tests/test_litellm/test_xai_responses_auto_routing.py +++ b/tests/test_litellm/test_xai_responses_auto_routing.py @@ -2,11 +2,8 @@ Test automatic routing to xAI Responses API when tools are present """ -import os -import sys from unittest.mock import MagicMock, patch -sys.path.insert(0, os.path.abspath("../..")) import pytest import litellm diff --git a/tests/test_litellm/types/llms/test_types_llms_openai.py b/tests/test_litellm/types/llms/test_types_llms_openai.py index 569743269a5..e5e5c0183a0 100644 --- a/tests/test_litellm/types/llms/test_types_llms_openai.py +++ b/tests/test_litellm/types/llms/test_types_llms_openai.py @@ -1,12 +1,9 @@ import asyncio -import os -import sys from typing import Optional from unittest.mock import AsyncMock, patch import pytest -sys.path.insert(0, os.path.abspath("../../..")) import json import litellm diff --git a/tests/test_litellm/types/test_types_utils.py b/tests/test_litellm/types/test_types_utils.py index 672aa84cc73..c081b9e8e0d 100644 --- a/tests/test_litellm/types/test_types_utils.py +++ b/tests/test_litellm/types/test_types_utils.py @@ -1,10 +1,7 @@ -import os -import sys from typing import Final import pytest -sys.path.insert(0, os.path.abspath("../..")) from litellm.types.utils import HiddenParams, all_litellm_params diff --git a/tests/test_litellm/vector_stores/test_vector_store_create_provider_logic.py b/tests/test_litellm/vector_stores/test_vector_store_create_provider_logic.py index bfb084e7dd2..4044e3dcc0e 100644 --- a/tests/test_litellm/vector_stores/test_vector_store_create_provider_logic.py +++ b/tests/test_litellm/vector_stores/test_vector_store_create_provider_logic.py @@ -1,12 +1,7 @@ -import os -import sys from unittest.mock import Mock, patch import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from litellm.llms.openai.vector_stores.transformation import OpenAIVectorStoreConfig diff --git a/tests/test_litellm/vector_stores/test_vector_store_registry.py b/tests/test_litellm/vector_stores/test_vector_store_registry.py index 85ff8a1bcae..f19c3706845 100644 --- a/tests/test_litellm/vector_stores/test_vector_store_registry.py +++ b/tests/test_litellm/vector_stores/test_vector_store_registry.py @@ -1,6 +1,4 @@ import json -import os -import sys from unittest.mock import patch import httpx @@ -8,9 +6,6 @@ import pytest import respx from fastapi.testclient import TestClient -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path from datetime import datetime, timezone from unittest.mock import MagicMock diff --git a/tests/test_litellm/videos/test_main.py b/tests/test_litellm/videos/test_main.py index 38667e93eee..22e1e5c05eb 100644 --- a/tests/test_litellm/videos/test_main.py +++ b/tests/test_litellm/videos/test_main.py @@ -30,8 +30,6 @@ helper runs for real against genuinely-encoded ids, so the provider assertions reflect production. """ -import os -import sys from contextlib import ExitStack from dataclasses import dataclass from typing import Any, Dict @@ -39,7 +37,6 @@ from unittest.mock import MagicMock, patch import pytest -sys.path.insert(0, os.path.abspath("../../..")) import litellm from litellm.llms.custom_httpx.llm_http_handler import BaseLLMHTTPHandler diff --git a/tests/test_litellm/videos/test_utils.py b/tests/test_litellm/videos/test_utils.py index 09975829531..57fb549c23d 100644 --- a/tests/test_litellm/videos/test_utils.py +++ b/tests/test_litellm/videos/test_utils.py @@ -9,12 +9,9 @@ runs for real, so the "litellm-internal params get stripped" assertions reflect production. Every test asserts the exact resulting dict, never "ran without error". """ -import os -import sys from unittest.mock import MagicMock -sys.path.insert(0, os.path.abspath("../../..")) import litellm from litellm.videos.utils import VideoGenerationRequestUtils diff --git a/tests/test_new_vector_store_endpoints.py b/tests/test_new_vector_store_endpoints.py index 4748d8e9947..c44723937ac 100644 --- a/tests/test_new_vector_store_endpoints.py +++ b/tests/test_new_vector_store_endpoints.py @@ -4,13 +4,10 @@ Tests both basic functionality and complex scenarios including target_model_name """ import asyncio -import os -import sys from unittest.mock import AsyncMock, MagicMock, patch import pytest -sys.path.insert(0, os.path.abspath("../..")) import litellm from litellm.proxy._types import UserAPIKeyAuth diff --git a/tests/test_ratelimit.py b/tests/test_ratelimit.py index 121dfbd99b7..7959f182a3a 100644 --- a/tests/test_ratelimit.py +++ b/tests/test_ratelimit.py @@ -4,14 +4,10 @@ import os import pytest import random from typing import Any -import sys from dotenv import load_dotenv load_dotenv() -sys.path.insert( - 0, os.path.abspath("../") -) # Adds the parent directory to the system path import litellm from pydantic import BaseModel diff --git a/tests/unified_google_tests/base_google_test.py b/tests/unified_google_tests/base_google_test.py index c4d8bb0d5aa..b7134962a0c 100644 --- a/tests/unified_google_tests/base_google_test.py +++ b/tests/unified_google_tests/base_google_test.py @@ -1,14 +1,10 @@ import asyncio import json -import sys import os import tempfile from typing import Any, AsyncIterator, Dict, List, Optional, Union import pytest -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path import litellm from litellm.google_genai import ( diff --git a/tests/unified_google_tests/conftest.py b/tests/unified_google_tests/conftest.py index d2c6830c273..a4df8d03605 100644 --- a/tests/unified_google_tests/conftest.py +++ b/tests/unified_google_tests/conftest.py @@ -4,7 +4,6 @@ import asyncio import importlib import os import socket -import sys import threading import time from pathlib import Path @@ -16,9 +15,6 @@ from dotenv import load_dotenv load_dotenv() -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm # noqa: E402,F401 from tests._vcr_conftest_common import ( # noqa: E402,F401 @@ -146,9 +142,6 @@ def setup_and_teardown(request): """ This fixture reloads litellm before every function. To speed up testing by removing callbacks being chained. """ - sys.path.insert( - 0, os.path.abspath("../..") - ) # Adds the project directory to the system path if "google_genai_proxy_url" not in request.fixturenames: diff --git a/tests/unified_google_tests/test_google_ai_studio.py b/tests/unified_google_tests/test_google_ai_studio.py index 3e40fa41089..6d4c3725080 100644 --- a/tests/unified_google_tests/test_google_ai_studio.py +++ b/tests/unified_google_tests/test_google_ai_studio.py @@ -1,11 +1,6 @@ from base_google_genai_proxy_sdk_test import BaseGoogleGenAIProxySDKTest from base_google_test import BaseGoogleGenAITest -import sys -import os -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path import pytest import litellm import unittest.mock diff --git a/tests/unified_google_tests/test_vertex_anthropic.py b/tests/unified_google_tests/test_vertex_anthropic.py index 71dad3a5cf9..f11ee28aacb 100644 --- a/tests/unified_google_tests/test_vertex_anthropic.py +++ b/tests/unified_google_tests/test_vertex_anthropic.py @@ -1,15 +1,10 @@ import asyncio import json -import sys -import os from typing import Any, AsyncIterator, Dict, List, Optional, Union import pytest from unittest.mock import MagicMock, AsyncMock, patch import httpx -sys.path.insert( - 0, os.path.abspath("../../..") -) # Adds the parent directory to the system path import litellm from litellm.google_genai import agenerate_content, agenerate_content_stream diff --git a/tests/vector_store_tests/base_vector_store_test.py b/tests/vector_store_tests/base_vector_store_test.py index 4093ea7b43b..926fe98b6ec 100644 --- a/tests/vector_store_tests/base_vector_store_test.py +++ b/tests/vector_store_tests/base_vector_store_test.py @@ -1,17 +1,12 @@ import httpx import json import pytest -import sys from typing import Any, Dict, List from unittest.mock import MagicMock, Mock, patch -import os from litellm._uuid import uuid import time import base64 -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm from abc import ABC, abstractmethod from litellm.integrations.custom_logger import CustomLogger diff --git a/tests/vector_store_tests/conftest.py b/tests/vector_store_tests/conftest.py index 41da685895b..8c1e70b14bc 100644 --- a/tests/vector_store_tests/conftest.py +++ b/tests/vector_store_tests/conftest.py @@ -2,13 +2,9 @@ import importlib import os -import sys import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path import litellm @@ -18,9 +14,6 @@ def setup_and_teardown(): This fixture reloads litellm before every function. To speed up testing by removing callbacks being chained. """ curr_dir = os.getcwd() # Get the current working directory - sys.path.insert( - 0, os.path.abspath("../..") - ) # Adds the project directory to the system path from litellm import Router @@ -28,8 +21,6 @@ def setup_and_teardown(): try: if hasattr(litellm, "proxy") and hasattr(litellm.proxy, "proxy_server"): - import litellm.proxy.proxy_server - importlib.reload(litellm.proxy.proxy_server) except Exception as e: print(f"Error reloading litellm.proxy.proxy_server: {e}") diff --git a/tests/vector_store_tests/rag/base_rag_tests.py b/tests/vector_store_tests/rag/base_rag_tests.py index 2c5a2540a7e..caeb7651085 100644 --- a/tests/vector_store_tests/rag/base_rag_tests.py +++ b/tests/vector_store_tests/rag/base_rag_tests.py @@ -4,15 +4,12 @@ Base RAG test class that enforces common tests across all providers. Providers should inherit from BaseRAGTest and implement the abstract methods. """ -import os -import sys import uuid from abc import ABC, abstractmethod from typing import Any, Dict, Optional import pytest -sys.path.insert(0, os.path.abspath("../../..")) import litellm from litellm.types.rag import ( diff --git a/tests/vector_store_tests/rag/test_rag_bedrock.py b/tests/vector_store_tests/rag/test_rag_bedrock.py index 7e788ed32f1..90cf4a3a44e 100644 --- a/tests/vector_store_tests/rag/test_rag_bedrock.py +++ b/tests/vector_store_tests/rag/test_rag_bedrock.py @@ -11,12 +11,10 @@ Optional (for using existing KB instead of auto-creating): """ import os -import sys from typing import Any, Dict, Optional import pytest -sys.path.insert(0, os.path.abspath("../../..")) import litellm from litellm.types.rag import RAGIngestOptions, BedrockVectorStoreOptions diff --git a/tests/vector_store_tests/rag/test_rag_openai.py b/tests/vector_store_tests/rag/test_rag_openai.py index d948e86fcf4..368e4e471b1 100644 --- a/tests/vector_store_tests/rag/test_rag_openai.py +++ b/tests/vector_store_tests/rag/test_rag_openai.py @@ -2,13 +2,10 @@ OpenAI RAG ingestion tests. """ -import os -import sys from typing import Any, Dict, Optional import pytest -sys.path.insert(0, os.path.abspath("../../..")) import litellm from litellm.types.rag import RAGIngestOptions, OpenAIVectorStoreOptions diff --git a/tests/vector_store_tests/rag/test_rag_s3_vectors.py b/tests/vector_store_tests/rag/test_rag_s3_vectors.py index cd8a362a7bf..d950bc0f644 100644 --- a/tests/vector_store_tests/rag/test_rag_s3_vectors.py +++ b/tests/vector_store_tests/rag/test_rag_s3_vectors.py @@ -11,12 +11,10 @@ Optional: """ import os -import sys from typing import Any, Dict, Optional import pytest -sys.path.insert(0, os.path.abspath("../../..")) import litellm from litellm.types.rag import RAGIngestOptions diff --git a/tests/vector_store_tests/rag/test_rag_vertex_ai.py b/tests/vector_store_tests/rag/test_rag_vertex_ai.py index c99840bb0fe..ae5891ed3ff 100644 --- a/tests/vector_store_tests/rag/test_rag_vertex_ai.py +++ b/tests/vector_store_tests/rag/test_rag_vertex_ai.py @@ -17,12 +17,10 @@ Environment variables: """ import os -import sys from typing import Any, Dict, Optional import pytest -sys.path.insert(0, os.path.abspath("../../..")) import litellm from litellm.types.rag import RAGIngestOptions diff --git a/tests/vector_store_tests/test_gemini_vector_store.py b/tests/vector_store_tests/test_gemini_vector_store.py index 8e30c94de51..2aa2c1741a8 100644 --- a/tests/vector_store_tests/test_gemini_vector_store.py +++ b/tests/vector_store_tests/test_gemini_vector_store.py @@ -3,9 +3,7 @@ Minimal Gemini File Search vector store tests. """ import os -import sys -sys.path.insert(0, os.path.abspath("../..")) from base_vector_store_test import BaseVectorStoreTest diff --git a/tests/vector_store_tests/test_ragflow_vector_store.py b/tests/vector_store_tests/test_ragflow_vector_store.py index 46751b64cce..0af821da98a 100644 --- a/tests/vector_store_tests/test_ragflow_vector_store.py +++ b/tests/vector_store_tests/test_ragflow_vector_store.py @@ -3,13 +3,11 @@ Test RAGFlow Vector Store helper functions and transformation. """ import os -import sys import json import pytest from unittest.mock import Mock, patch, MagicMock import httpx -sys.path.insert(0, os.path.abspath("../..")) import litellm from tests.vector_store_tests.base_vector_store_test import BaseVectorStoreTest diff --git a/tests/windows_tests/test_litellm_on_windows.py b/tests/windows_tests/test_litellm_on_windows.py index 8810cc78929..0a6058d6784 100644 --- a/tests/windows_tests/test_litellm_on_windows.py +++ b/tests/windows_tests/test_litellm_on_windows.py @@ -1,16 +1,11 @@ import asyncio -import os import subprocess -import sys import time import traceback import platform import pytest -sys.path.insert( - 0, os.path.abspath("../..") -) # Adds the parent directory to the system path def test_using_litellm_on_windows(): diff --git a/ui/litellm-dashboard/src/app/(dashboard)/playground/components/chat_ui/EndpointUtils.test.tsx b/ui/litellm-dashboard/src/app/(dashboard)/playground/components/chat_ui/EndpointUtils.test.tsx index 778effdaea6..c528071fa8a 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/playground/components/chat_ui/EndpointUtils.test.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/playground/components/chat_ui/EndpointUtils.test.tsx @@ -247,6 +247,13 @@ describe("isModelCompatibleWithEndpoint / filterModelsForEndpoint", () => { expect(isModelCompatibleWithEndpoint(batchModel, EndpointType.REALTIME)).toBe(false); }); + it("keeps completion-mode models for the chat endpoint", () => { + const completionModel: ModelGroup = { model_group: "davinci-002", mode: "completion" }; + expect(isModelCompatibleWithEndpoint(completionModel, EndpointType.CHAT)).toBe(true); + expect(isModelCompatibleWithEndpoint(completionModel, EndpointType.RESPONSES)).toBe(true); + expect(isModelCompatibleWithEndpoint(completionModel, EndpointType.SPEECH)).toBe(false); + }); + it("keeps image-edit models for the image-edits endpoint using the mode the backend sends", () => { const imageEditModel: ModelGroup = { model_group: "gpt-image-1", mode: "image_edit" }; const imageModel: ModelGroup = { model_group: "dall-e-3", mode: "image_generation" }; diff --git a/ui/litellm-dashboard/src/components/chat_ui/mode_endpoint_mapping.tsx b/ui/litellm-dashboard/src/components/chat_ui/mode_endpoint_mapping.tsx index 18e44e06efe..930ded5d1a5 100644 --- a/ui/litellm-dashboard/src/components/chat_ui/mode_endpoint_mapping.tsx +++ b/ui/litellm-dashboard/src/components/chat_ui/mode_endpoint_mapping.tsx @@ -7,6 +7,7 @@ export enum ModelMode { IMAGE_GENERATION = "image_generation", VIDEO_GENERATION = "video_generation", CHAT = "chat", + COMPLETION = "completion", RESPONSES = "responses", IMAGE_EDITS = "image_edit", ANTHROPIC_MESSAGES = "anthropic_messages", @@ -36,6 +37,7 @@ export const litellmModeMapping: Record = { [ModelMode.IMAGE_GENERATION]: EndpointType.IMAGE, [ModelMode.VIDEO_GENERATION]: EndpointType.VIDEO, [ModelMode.CHAT]: EndpointType.CHAT, + [ModelMode.COMPLETION]: EndpointType.CHAT, [ModelMode.RESPONSES]: EndpointType.RESPONSES, [ModelMode.IMAGE_EDITS]: EndpointType.IMAGE_EDITS, [ModelMode.ANTHROPIC_MESSAGES]: EndpointType.ANTHROPIC_MESSAGES, diff --git a/ui/litellm-dashboard/src/lib/http/schema.d.ts b/ui/litellm-dashboard/src/lib/http/schema.d.ts index cf55dc69e86..d311bfa3cbc 100644 --- a/ui/litellm-dashboard/src/lib/http/schema.d.ts +++ b/ui/litellm-dashboard/src/lib/http/schema.d.ts @@ -43144,6 +43144,8 @@ export interface operations { provider?: string | null; target_model_names?: string | null; purpose?: string | null; + limit?: number | null; + after?: string | null; }; header?: never; path?: never; @@ -58015,6 +58017,8 @@ export interface operations { provider?: string | null; target_model_names?: string | null; purpose?: string | null; + limit?: number | null; + after?: string | null; }; header?: never; path?: never; @@ -64268,6 +64272,8 @@ export interface operations { query?: { target_model_names?: string | null; purpose?: string | null; + limit?: number | null; + after?: string | null; }; header?: never; path: { diff --git a/uv.lock b/uv.lock index 6b18be68c92..628483c0117 100644 --- a/uv.lock +++ b/uv.lock @@ -10,7 +10,7 @@ resolution-markers = [ ] [options] -exclude-newer = "2026-08-17T21:26:36.028845Z" +exclude-newer = "2026-08-19T15:53:37.294198Z" exclude-newer-span = "P3D" [manifest] @@ -4661,12 +4661,12 @@ proxy-dev = [ [[package]] name = "litellm-enterprise" -version = "0.1.58" +version = "0.1.59" source = { editable = "enterprise" } [[package]] name = "litellm-proxy-extras" -version = "0.4.88" +version = "0.4.89" source = { editable = "litellm-proxy-extras" } [[package]]