mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-14 04:09:09 +00:00
* fix: support OpenAI SDK 3.x while retaining 2.x compatibility * fix: preserve HTTPX compatibility across OpenAI SDK versions * refactor: trim OpenAI SDK compatibility patch * refactor: simplify SDK client defaults * test: cover SDK compatibility across provider routes * fix: use shared names for SDK transport helpers * fix: address SDK compatibility review feedback * test(openai): send requests through the SDK API factory clients * fix(exceptions): keep the provider response on PaymentRequiredError under httpx 2 * ci(base-sdk): count httpx2 as base-only when a base dependency brings it in OpenAI SDK 3 depends on httpx2, so the litellm-core install at highest resolution pulls it in through openai. The base-only check now resolves the declared base dependency closure of litellm and litellm-core and accepts extras-only modules owned by a distribution inside that closure * test: cover OpenAI SDK 3 client paths end to end and read SDK HTTP headers case-insensitively * test: read C02 spend rows once, wait out the worker healthcheck on respawn, and resolve module owners on Python 3.10 --------- Co-authored-by: Marcus Wood <marcuswood@openai.com> Co-authored-by: mateo-berri <277851410+mateo-berri@users.noreply.github.com>
66 lines
2.5 KiB
Python
66 lines
2.5 KiB
Python
from typing import Final
|
|
|
|
import httpx
|
|
from openai import DefaultAsyncHttpxClient, DefaultHttpxClient
|
|
from openai import HttpxBinaryResponseContent as SDKBinaryResponse
|
|
from openai import Timeout as SDKTimeout
|
|
from openai._types import Response as SDKResponse
|
|
from typing_extensions import assert_type
|
|
|
|
import litellm
|
|
from litellm.exceptions import (
|
|
APIConnectionError,
|
|
APIResponseValidationError,
|
|
BadGatewayError,
|
|
InternalServerError,
|
|
InvalidRequestError,
|
|
RateLimitError,
|
|
Timeout,
|
|
)
|
|
from litellm.litellm_core_utils.completion_timeout import CompletionTimeout
|
|
from litellm.types.llms.openai import HttpxBinaryResponseContent
|
|
from litellm.types.router import GenericLiteLLMParams, LiteLLMParamsTypedDict
|
|
|
|
|
|
def consume_binary_response(response: HttpxBinaryResponseContent) -> httpx.Response:
|
|
assert_type(response.response, httpx.Response)
|
|
assert_type(response.response.request, httpx.Request)
|
|
return response.response
|
|
|
|
|
|
def binary_response_types(legacy_response: httpx.Response, sdk_response: SDKResponse) -> None:
|
|
legacy: Final = HttpxBinaryResponseContent(legacy_response)
|
|
native: Final = HttpxBinaryResponseContent(sdk_response)
|
|
|
|
assert_type(legacy.response, httpx.Response)
|
|
assert_type(native.response, SDKResponse)
|
|
assert_type(legacy.read(), bytes)
|
|
assert_type(native.read(), bytes)
|
|
assert_type(consume_binary_response(legacy), httpx.Response)
|
|
|
|
sdk_wrapper: Final[SDKBinaryResponse] = legacy
|
|
assert_type(sdk_wrapper.read(), bytes)
|
|
|
|
|
|
def synthesized_response_types(
|
|
error: RateLimitError | BadGatewayError | InternalServerError | APIResponseValidationError | InvalidRequestError,
|
|
) -> None:
|
|
assert_type(error.response, httpx.Response)
|
|
assert_type(error.request, httpx.Request)
|
|
|
|
|
|
def synthesized_request_types(error: APIConnectionError | Timeout) -> None:
|
|
assert_type(error.request, httpx.Request)
|
|
|
|
|
|
def configured_clients(
|
|
sync_client: httpx.Client | DefaultHttpxClient,
|
|
async_client: httpx.AsyncClient | DefaultAsyncHttpxClient,
|
|
timeout: httpx.Timeout | SDKTimeout,
|
|
) -> None:
|
|
litellm.client_session = sync_client # test-quality-ok: [TQ005] Type-check-only fixture; never executed
|
|
litellm.aclient_session = async_client # test-quality-ok: [TQ005] Type-check-only fixture; never executed
|
|
assert_type(CompletionTimeout.normalize(timeout), httpx.Timeout)
|
|
params: Final[LiteLLMParamsTypedDict] = {"timeout": 1.0}
|
|
params["timeout"] = timeout
|
|
GenericLiteLLMParams(timeout=timeout)
|