Skip to content

fix: restore Python compatibility and test 3.10 through 3.14 - #39399

Merged
mateo-berri merged 18 commits into
litellm_internal_stagingfrom
litellm_python_version_ci
Sep 4, 2026
Merged

mateo-berri merged 18 commits into
litellm_internal_stagingfrom
litellm_python_version_ci

Conversation

@yujonglee-berri

@yujonglee-berri yujonglee-berri commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

TLDR

Problem this solves:

  • Python 3.10 cannot import several SDK and proxy modules
  • Normal and streaming responses fail during Pydantic validation
  • CI tests only Python 3.12 despite supporting five versions
  • Generated Prisma types stall imports on Python 3.14
  • Deferred annotations break OCR, vector search, and client introspection
  • The proxy cannot start on Python 3.14 because uvloop fails to import
  • UTC timestamps and test tooling differ across supported versions

How it solves it:

  • Import newer typing names from typing_extensions
  • Resolve the reasoning-summary type directly instead of by name
  • Test normal and streaming reasoning-summary serialization
  • Run existing unit-test shards on Python 3.10 through 3.14
  • Generate recursive Prisma types and use fresh virtual environments
  • Return aware UTC timestamps consistently and repair portable tests
  • Qualify annotations so fields and methods cannot shadow builtins
  • Require the uvloop release that supports Python 3.14

The import changes incorporate all six runtime fixes proposed in #38512 and #39374, plus the same fix for general upload validation added to staging while this PR was running. The additional response fix removes an unnecessary quoted reference to a type already defined above it. On Python 3.10, Pydantic otherwise resolves that name in the consuming model's namespace and leaves both Message and Delta incomplete

The existing reusable unit workflow runs each of its 26 SDK and proxy shards on all five supported versions. Both setup-python and uv use the selected interpreter. Only uv downloads/build artifacts are cached, using the actual UV_CACHE_DIR and version-specific keys. Each job builds a fresh virtual environment. Older interpreters use coverage's C tracer, and existing Python 3.12 check names and Codecov reports remain intact. There is no separate compatibility workflow

User Flow

Before: supported Python versions fail at different points in an SDK or proxy request

  1. They install LiteLLM on Python 3.10 or 3.14
  2. They start the proxy or use chat completions, OCR, or vector-store search
  3. On 3.10, proxy loading or completion responses fail. On 3.14, litellm --config config.yaml exits with ImportError: cannot import name 'BaseDefaultEventLoopPolicy' from 'asyncio.events', OCR returns an incomplete-model error, and vector search can raise TypeError: 'function' object is not subscriptable

After: those imports and response paths work on the same Python versions

  1. They install LiteLLM on Python 3.10 or 3.14
  2. They start the proxy or use chat completions, OCR, or vector-store search
  3. Proxy imports and completion responses succeed on 3.10. The proxy serves /v1/chat/completions on 3.14, and OCR response validation and vector-search cache handling succeed there too

Relevant issues

Fixes #38202
Fixes #36384

Includes the import-source fixes proposed in #38512 and #39374

Compatibility findings and fixes

These are observed failures and constraints, not a claim that the matrix catches every possible compatibility problem

Gotcha Cause and fix
New typing names break Python 3.10 imports assert_never, Never, and Required must come from typing_extensions. Fix every affected module because an early import failure masks the next one. compact.py was already fixed upstream
Import success does not prove response construction works A quoted reasoning-summary type left Pydantic's Message and Delta incomplete on 3.10. Resolve the already-defined type directly and test normal and streaming serialization
Python 3.14 Prisma jobs all timed out before tests Prisma's default bounded expansion generated 672,251 lines of types. Local traces showed annotation evaluation inside typing_extensions while importing those types. recursive_type_depth = -1, the documented setting for Pyright, reduces this to 164,539 lines. Import and construction took about eight seconds locally. Both first generation and regeneration were verified
Restoring .venv restores the old generated Prisma client The Prisma CLI imports the installed client before regenerating it, so an old client can prevent the fix from taking effect. Cache downloads rather than the environment. The effective uv cache is UV_CACHE_DIR, not necessarily ~/.cache/uv
Prisma schema copies must stay identical Root schema.prisma is canonical; the SDK proxy and proxy-extras copies must match byte-for-byte. Update all three even for a generator-only setting. The first follow-up CI run caught this drift
A generator setting is not a database migration prisma migrate diff between the old and new schemas reports an empty migration. The change affects generated Python types
UTC expiry comparisons fail only on 3.10 datetime.UTC is absent on 3.10; the fallback returned naive utcnow(). Use datetime.now(timezone.utc) on every version and verify an aware current timestamp
Dotted mock targets traverse exported values instead of packages Python 3.10 can reach the responses function or caching boolean instead of the same-named package. Import the actual module with import_module and patch its attribute. The same target can fail only after another test changes the exported value
CI tests the merge result, not only the branch tip Staging added general_upload_validation.py with a new stdlib assert_never import while this PR was open. Local checks at the old base passed, but CI merged with 1bb9b175e2 and failed on 3.10. Bring in that base, fix the import, and rerun against the actual merged code
Early failures conceal later failures The existing --maxfail limit stopped shards before they reached more mock targets, OCR behavior, and dependency-specific tests. After fixing a blocker, rerun the complete affected shard; one green targeted test is insufficient. Swallowed import errors also produced misleading mock-call and metrics assertions, so inspect the earliest traceback
Python 3.14 evaluates annotations in class scope OCRResponse.object = "ocr" shadowed builtin object in annotations for tables and key-value pairs, leaving Pydantic with an unresolved ocr reference. Use builtins.object and verify nested strings, numbers, and booleans survive the proxy response
Methods named list also shadow annotation builtins on 3.14 The vector-store module exposes list(), so deferred list[...] annotations resolve to that function. Search then fails when cache handling calls inspect.signature, also breaking RAG billing tests. The models and teams management clients reproduce the same signature failure. Use builtins.list; verify string and multi-query searches, downstream RAG billing, and the public call signatures
Catching a test setup error can hide the real failure One exception-tree test used builtin ExceptionGroup on 3.10, caught the resulting NameError, and then failed an unrelated assertion. Import the exceptiongroup backport on 3.10 so it exercises the intended tree
Schedulers inspect mocked callables Bare AsyncMock exposes mock code/name attributes that Python 3.10's inspect and APScheduler cannot use. Build the scheduled async functions with create_autospec so signatures and names are real
Mocking asyncio.get_running_loop globally breaks Redis tests On 3.10, Redis uses async_timeout, which needs that function. Construct the clients in a worker thread to avoid startup tasks, then exercise real Redis failures on the actual event loop
Enum formatting and typing introspection vary by version Assert the meaningful guardrail error text without depending on the enum prefix. Use typing_extensions.get_type_hints to unwrap backported Required consistently
Concurrent writes have no guaranteed call order S3 pipeline and concurrent-write tests asserted submission order. Compare all expected keys, buckets, and payloads without requiring an order
Development scripts also run during test collection Four test/tool modules imported 3.11-only tomllib. Use tomli on 3.10 and declare the existing locked version as a direct development dependency
An optional extra is already unavailable on 3.14 Metadata excludes semantic-router and aurelio-sdk on 3.14. The encoder module and 35 dependency-specific routing/MCP tests follow that exclusion and remain tested on 3.10–3.13. The same routing/MCP files still run 672 dependency-independent tests on 3.14. This is a documented feature and coverage gap
Full-tree collection is not equivalent to the CI shards Combining unrelated shards causes duplicate test-module names and shared mock-module contamination. Validate those failures using the actual shard boundaries before changing product code
Coverage and required checks have version assumptions Python 3.10/3.11 need the C tracer. Keep existing 3.12 check names and upload only 3.12 coverage to avoid artifact collisions
Budget updates are not idempotent The updater subtracts branch reductions from its input ceilings. Recompute once from branch-base budgets on the finished changes to avoid counting the same reduction twice. All final ceilings only decrease
Importable does not mean bootable on 3.14 Python 3.14 removed asyncio.events.BaseDefaultEventLoopPolicy, which uvloop 0.21.0 imports at module scope. uvicorn only imports its loop factory when the server starts, so every import and unit-test check passed while litellm --config died at boot. Require uvloop>=0.22.1 and assert the selected loop factory imports on the running interpreter
co_qualname does not exist before 3.11 The SDK function-trace harness matched steps such as ProviderConfigManager.get_provider_chat_config against bare code names on 3.10, so five parity tests failed there. Rebuild the qualified name from module declarations and enclosing frames, following classes, accessors, wrappers, and nested functions. Resolve explicit function references from portable __qualname__
Lockfile writer versions can change unrelated metadata The local uv version rewrote the older client's exclude-newer fallback. Preserve the existing cutoff metadata; the only dependency change is declaring already-locked tomli

Coverage boundaries

The matrix tests normal CPython 3.10–3.14 on Linux with locked dependencies, fresh virtual environments, Prisma generation, and the existing SDK/proxy behavior tests. The minor-version selectors track the patch version supplied by setup-python, and each job prints and verifies its actual interpreter. Local checks used 3.10.20 and 3.14.5; the initial CI failures used 3.10.21 and 3.14.7

This does not test every patch release, free-threaded 3.13t/3.14t builds, macOS/Windows, fresh dependency resolution, lowest dependencies, or an installed release wheel outside the checkout. Metadata already selects different Lunary releases on 3.10 and newer Python versions

The Python 3.14 porting notes also call out annotation evaluation and Linux's default forkserver behavior. No direct multiprocessing/ProcessPoolExecutor use was found in litellm/; xdist passing would not independently prove multi-process server startup. The custom-code guardrail already supplies an explicit namespace to exec, avoiding implicit-locals assumptions

Other dependency combinations can still encounter removed standard-library modules, native-extension ABI changes, or older ASGI/async libraries. Those are coverage considerations, not failures established here. Pydantic's 2.12 announcement adds 3.14 support to V2 and explicitly says V1 is unsupported on 3.14

Findings carried over from #38512

Compared against #38512 at 0748f4f01772ed1d76ccc1c742d7f9c3d95e2415, including its discussion and inline reviews

All six remaining runtime import fixes are included: websearch interception, MCP tool search, agent endpoints, budget resets, batch-file validation, and Gemini transcription types. The earlier compact.py fix is already in our base

The contributor's rebase findings show why a one-time import fix is insufficient: typing cleanups introduced new incompatible imports while that PR was open, and the first import failure concealed later ones. Our supported-version matrix runs the existing SDK and proxy test suites, covering imports and behavior such as the separate Pydantic response failure

Their static scanner adds something the runtime matrix cannot guarantee: checking imports in files and functions tests never execute. It is not included here because its version-guard handling accepts imports in the wrong branch, and its API catalog omits asyncio.timeout and timeout_at. Local probes confirmed those misses, plus qualified typing.assert_never access and silently ignored syntax errors. Its fixed-schema violation records also need precise types, as the third review comment notes

The compatibility gate in this PR is the actual Python 3.10 through 3.14 test run. No hard-coded API scanner or replacement scanner is planned. Running on each interpreter exercises its real standard library, installed dependencies, import paths, and runtime behavior without maintaining a separate list of incompatible names

Coverage still matters: an import inside a function only fails when that function executes. Missing coverage should be addressed with tests that exercise the affected behavior. The matrix does not prove compatibility for untested paths or dependency combinations

basedpyright still targets 3.12. Targeting the minimum supported version could provide additional static feedback, but it is not a prerequisite for replacing #38512's import fixes and is outside this PR

Linear ticket

Resolves LIT-6777

Pre-Submission checklist

  • I have added meaningful tests
  • The handful of test files covering my change pass locally
  • My PR passes all required CI/CD checks
  • My PR's scope is as isolated as possible
  • I have received a Greptile Confidence Score of at least 4/5 before requesting a maintainer review

Greptile scored this 5/5 at a581399027. Bugbot re-reviewed the earlier staging-merged tip 71f5b89499 directly and found no new issues. The current staging merge relocates the profiler fix into the replacement Rust/Python harness and preserves Python 3.10 support there

All 130 matrix jobs pass at 71f5b89499, the tip that merges litellm_internal_staging in, and they passed at a581399027 before it. On the merge's first run seven shards failed on Install dependencies has timed out after 8 minutes with zero test failures. That 8-minute step timeout is pre-existing on the base branch and uv.lock is byte-identical across the merge, so the download cache key never changed; all seven went green on re-run with no code change, which is what puts the tip at 200 passing checks and no failures. The matrix is 26 SDK/proxy shards on each of Python 3.10, 3.11, 3.12, 3.13, and 3.14. The three container checks (ui-image, runtime-image, image-scan) failed at a581399027 on the base branch's dashboard build rather than on anything here: npm run build inside the ui image could not resolve ../../../../litellm/proxy/public_endpoints/autorouter_presets.json from its Docker context, and the other two images depend on it. Merging litellm_internal_staging in picked up the fix for that, so all three pass at 71f5b89499

CircleCI was re-run at 71f5b89499 and 39 of its 43 jobs pass. build_docker_database_image goes green here, which is what lets the eleven jobs downstream of it run at all; they were all skipped on the earlier run. The three red jobs are red on litellm_internal_staging itself, one test each and the same test name on both sides: litellm_router_testing on test_router::test_router_timeout, local_testing_part2 on test_timeout::test_timeout_streaming, and e2e_openai_endpoints on test_e2e_openai_responses_api::test_cancel_streaming_response. None of the three is a required check

The unit matrix does not reach tests/llm_translation or the bulk of tests/local_testing; those run only on CircleCI, which builds one Python version. So both were collected locally on 3.10 and on 3.14 at 71f5b89499, and each collects the same set on both: 2,799 tests in tests/llm_translation and 1,576 in tests/local_testing, with no collection errors. tests/local_testing/test_tpm_rpm_routing_v2.py is the only CircleCI-only file that calls the one function whose behavior changed, get_utc_datetime, and it reports 10 passed on both versions. Its two failures are the Redis-backed cases, which need REDIS_HOST and are the same on either version

The previously failing Python 3.14 miscellaneous shard now reports 5,388 passed and 37 skipped. The nine vector-store/RAG failures are resolved. The version-specific semantic-router exclusions are described above

The final local checks include 19 vector-store/RAG tests on both 3.10 and 3.14, 46 management-client tests on 3.14, and the five direct runtime reproductions below. After the current staging merge, the affected harness suites report 50 passed on both Python 3.10 and 3.12. make check passes, including lint/type/quality gates, import safety, and API-schema synchronization. The Prisma generator change has an empty database migration diff. All budget changes lower existing ceilings

Delays in PR merge?

If you're seeing a delay in your PR being merged, ping the LiteLLM Team on Slack (#pr-review).

Screenshots / Proof of Fix

Commands below use Python 3.10.20 for the first three cases and Python 3.14.7 for OCR, runtime annotations, and proxy boot, with locked dependencies and LITELLM_LOCAL_MODEL_COST_MAP=True. Each run imports the source from the indicated revision. The proxy runs use this config and a real OpenAI key:

model_list:
  - model_name: gpt-5.6
    litellm_params:
      model: openai/gpt-5.6
      api_key: os.environ/OPENAI_API_KEY
general_settings:
  master_key: sk-lit6777-qa

Before (1bb9b17)

1bb9b175e2 was the merge base when these were captured. Every symptom below still reproduces at the current merge base 3cac5e5cd4 on both 3.10.20 and 3.14.7

Proxy import

  1. Run python -c 'import litellm.proxy.proxy_server; print("Proxy import OK")'
  2. Output: ImportError: cannot import name 'assert_never' from 'typing'

Completion responses

  1. Run python -c 'from litellm.types.utils import ModelResponse, ModelResponseStream; ModelResponse(); ModelResponseStream(); print("Normal and streaming responses OK")'
  2. Output: PydanticUserError: Message is not fully defined

UTC timestamps

  1. Run python -c 'from litellm.utils import get_utc_datetime; print(get_utc_datetime().utcoffset())'
  2. Output: None, a timezone-naive timestamp

OCR response

  1. Run python -c 'from litellm.llms.base_llm.ocr.transformation import OCRResponse; print(OCRResponse(pages=[], model="test", tables=[{"amount": 42}], keyValuePairs=[{"approved": True}]).model_dump_json(exclude_none=True))'
  2. Output: PydanticUserError: OCRResponse is not fully defined; you should define ocr

Runtime annotations

  1. Run this with Python 3.14:

    python - <<'PYTHON'
    from inspect import signature
    from litellm.vector_stores.main import search
    from litellm.proxy.client.models import ModelsManagementClient
    from litellm.proxy.client.teams import TeamsManagementClient
    for function in (search, ModelsManagementClient.list, TeamsManagementClient.list):
        try:
            signature(function)
            print(function.__qualname__, "OK")
        except TypeError as error:
            print(function.__qualname__, type(error).__name__, str(error))
    PYTHON
  2. Output:

    search TypeError 'function' object is not subscriptable
    ModelsManagementClient.list TypeError 'function' object is not subscriptable
    TeamsManagementClient.list TypeError 'function' object is not subscriptable
    

Proxy boot on Python 3.14

  1. Run python litellm/proxy/proxy_cli.py --config config.yaml --port <port> on Python 3.14

  2. The proxy exits before serving anything:

      File ".../uvicorn/server.py", line 74, in run
        return asyncio_run(self.serve(sockets=sockets), loop_factory=self.config.get_loop_factory())
      File ".../uvicorn/config.py", line 539, in get_loop_factory
        loop_factory: Callable[..., Any] | None = import_from_string(LOOP_FACTORIES[self.loop])
      File ".../uvicorn/loops/uvloop.py", line 6, in <module>
        import uvloop
      File ".../uvloop/__init__.py", line 6, in <module>
        from asyncio.events import BaseDefaultEventLoopPolicy as __BasePolicy
    ImportError: cannot import name 'BaseDefaultEventLoopPolicy' from 'asyncio.events'
    

After (71f5b89)

Proxy import

  1. Run python -c 'import litellm.proxy.proxy_server; print("Proxy import OK")'
  2. Output: Proxy import OK

Completion responses

  1. Run python -c 'from litellm.types.utils import ModelResponse, ModelResponseStream; ModelResponse(); ModelResponseStream(); print("Normal and streaming responses OK")'
  2. Output: Normal and streaming responses OK

UTC timestamps

  1. Run python -c 'from litellm.utils import get_utc_datetime; print(get_utc_datetime().utcoffset())'
  2. Output: 0:00:00, an aware UTC timestamp

OCR response

  1. Run python -c 'from litellm.llms.base_llm.ocr.transformation import OCRResponse; print(OCRResponse(pages=[], model="test", tables=[{"amount": 42}], keyValuePairs=[{"approved": True}]).model_dump_json(exclude_none=True))'
  2. Output: {"pages":[],"model":"test","tables":[{"amount":42}],"keyValuePairs":[{"approved":true}],"object":"ocr"}

Runtime annotations

  1. Run this with Python 3.14:

    python - <<'PYTHON'
    from inspect import signature
    from litellm.vector_stores.main import search
    from litellm.proxy.client.models import ModelsManagementClient
    from litellm.proxy.client.teams import TeamsManagementClient
    for function in (search, ModelsManagementClient.list, TeamsManagementClient.list):
        try:
            signature(function)
            print(function.__qualname__, "OK")
        except TypeError as error:
            print(function.__qualname__, type(error).__name__, str(error))
    PYTHON
  2. Output:

    search OK
    ModelsManagementClient.list OK
    TeamsManagementClient.list OK
    

Proxy boot and live completions on Python 3.10 and 3.14

  1. Start the proxy on each interpreter: LITELLM_LOCAL_MODEL_COST_MAP=True python litellm/proxy/proxy_cli.py --config config.yaml --port <port>

  2. curl -s http://127.0.0.1:<port>/health/liveliness returns "I'm alive!" on both

  3. Send a real completion:

    curl -s -D headers.txt http://127.0.0.1:<port>/v1/chat/completions \
      -H "Authorization: Bearer sk-lit6777-qa" -H "Content-Type: application/json" \
      -d '{"model":"gpt-5.6","messages":[{"role":"user","content":"Reply with exactly: proxy ok"}]}'
  4. Output on Python 3.10.20 (port 27431) and Python 3.14.7 (port 31882):

    3.10.20 {"id": "chatcmpl-EJw4wTnTf7A8duTpbegI5p8EZdoSH", "model": "gpt-5.6", "content": "proxy ok", "usage": 17}
    3.10.20 x-litellm-response-cost: 0.00014800000000000002
    3.14.7  {"id": "chatcmpl-EJw4xSgaR7CU33NLnvFrGWVJT6YOR", "model": "gpt-5.6", "content": "proxy ok", "usage": 17}
    3.14.7  x-litellm-response-cost: 0.00014800000000000002
    
  5. Repeat with "stream": true; both interpreters stream chunks and finish with data: [DONE]

Type

Bug Fix

Infrastructure

Test

Caveats (if any)

Medium

  • Unit-test execution grows to five runs per existing shard: measured at a581399027, the two unit workflows cost 503 runner-minutes across 157 jobs against 87 minutes before, so the four added interpreters are about 416 extra runner-minutes per push. Dropping 3.11 and 3.13 to post-merge runs is the knob if that spend ever outweighs catching a break pre-merge
  • Five times as many jobs contend for the same uv download cache, so a cold or throttled cache makes the pre-existing 8-minute Install dependencies step timeout easier to hit. The staging-merge run showed this: seven shards timed out on that step with no test failures and went green on re-run. Raising that step timeout is the knob if it recurs
  • Untested paths and dependency combinations remain uncovered
  • basedpyright still targets 3.12; runtime coverage provides compatibility checks
  • Dependencies remain locked; fresh resolution is outside this change
  • semantic-router-dependent tests exclude 3.14, matching dependency metadata
  • Free-threaded builds and other operating systems remain untested

Final Attestation

  • The tests check the right things, including the edge cases, and regressions in the respective real-world customer use-cases are not possible after this PR

  • a581399 passes /live-pr-risk

  • 71f5b89 passes /live-pr-risk: the staging merge leaves every litellm/ contribution byte-identical to a581399027, so that graph walk still holds. The delta is two conflict-resolved test files, both re-run on 3.10, 3.12 and 3.14 and re-driven against a live proxy on 3.10 and 3.14

  • 6675e1f merges the current staging base, passes make check, and passes the affected harness suites on Python 3.10 and 3.12


Note

Medium Risk
Touches proxy boot dependencies, Prisma client generation, and broad CI matrix expansion; changes are mostly compatibility and test infrastructure but affect every unit shard and generated DB client types.

Overview
Expands the reusable unit-test workflow so each SDK/proxy shard runs on Python 3.10 through 3.14 (matrix, per-version UV_PYTHON, version-scoped uv download cache, interpreter assertion after sync). Coverage upload stays on 3.12 only, with ctrace on 3.10/3.11 and sysmon on newer interpreters.

Runtime and dependency fixes for those versions: Prisma generator recursive_type_depth = -1 on all schema copies; get_utc_datetime() always returns timezone-aware UTC; OCR/vector-store/proxy client annotations use builtins.object / builtins.list so methods named list and object fields do not break 3.14; reasoning summary typing uses ReadOnly[...] with new serialization tests; proxy extra requires uvloop>=0.22.1 for 3.14 boot; dev adds tomli on Python < 3.11 for scripts/tests that read pyproject.toml.

Tests and tooling are adjusted for portability: import_module + patch.object for stable mocks on 3.10, Redis circuit-breaker tests construct clients off-loop, semantic-router suites skip on 3.14, SDK function-trace profiler resolves qualified names without co_qualname, and lint/type budget JSON ceilings are ratcheted down slightly.

Reviewed by Cursor Bugbot for commit a581399. Bugbot is set up for automated code reviews on this repo. Configure here.

@codecov

codecov Bot commented Sep 2, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@yujonglee-berri yujonglee-berri linked an issue Sep 2, 2026 that may be closed by this pull request
1 task
@yujonglee-berri yujonglee-berri changed the title ci: test Python 3.10 through 3.14 compatibility fix: restore Python 3.10 compatibility and test supported versions Sep 2, 2026
@codspeed

codspeed Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 31 untouched benchmarks


Comparing litellm_python_version_ci (6675e1f) with litellm_internal_staging (b75ac5c)

Open in CodSpeed

@yujonglee-berri yujonglee-berri changed the title fix: restore Python 3.10 compatibility and test supported versions fix: restore Python compatibility and test 3.10 through 3.14 Sep 2, 2026
@yujonglee-berri
yujonglee-berri marked this pull request as ready for review September 2, 2026 21:59
@yujonglee-berri
yujonglee-berri requested a review from a team September 2, 2026 21:59
@greptile-apps

greptile-apps Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR restores runtime compatibility across Python 3.10 through 3.14 and expands existing unit-test shards to cover all supported versions.

  • Moves compatibility-sensitive typing constructs to supported forms and repairs annotation resolution for response, OCR, vector-store, and management-client models.
  • Uses consistently timezone-aware UTC timestamps and updates portable tests and tooling.
  • Updates Prisma generation, uvloop, and development dependencies for Python 3.14 and Python 3.10 compatibility.
  • Introduces version-specific dependency caching, fresh environments, and five-version CI execution while retaining Python 3.12 coverage reporting.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
.github/workflows/_test-unit-base.yml Expands every reusable unit-test shard across Python 3.10–3.14, scopes dependency caches by interpreter, and retains coverage publication from Python 3.12.
litellm/types/llms/openai.py Resolves the reasoning-summary TypedDict directly and marks the summary field read-only to avoid incomplete Pydantic models.
litellm/llms/base_llm/ocr/transformation.py Qualifies object annotations through builtins so the OCR model's object field cannot shadow their runtime resolution.
litellm/vector_stores/main.py Qualifies list annotations through builtins to preserve runtime introspection when the module also exports a list function.
litellm/utils.py Simplifies UTC timestamp construction to consistently return timezone-aware datetime values.
pyproject.toml Raises the proxy uvloop floor for Python 3.14 and declares the Python 3.10 tomli development dependency.
schema.prisma Configures recursive Prisma type generation to avoid excessive bounded expansion on newer Python versions.
tests/sdk_function_trace/profiler.py Reconstructs qualified function names on Python versions without code-object co_qualname support.

Reviews (5): Last reviewed commit: "Merge remote-tracking branch 'origin/lit..." | Re-trigger Greptile

@mateo-berri

Copy link
Copy Markdown
Contributor

@greptileai

@mateo-berri

Copy link
Copy Markdown
Contributor

@greptileai

@mateo-berri

Copy link
Copy Markdown
Contributor

@greptileai

@mateo-berri

Copy link
Copy Markdown
Contributor

bugbot run

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit a581399. Configure here.

@mateo-berri mateo-berri left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks!

…itellm_python_version_ci

Resolves two conflicts:

- tests/test_litellm/vector_stores/test_main.py: staging moved search() to a
  RouterVectorStoreEmbeddingExecutor while this branch parametrized the same
  test over query; keep both the executor assertions and the parametrize.
- tests/logging_callback_tests/test_bedrock_knowledgebase_hook.py: staging
  carries a duplicate embedding_executor kwarg that makes the file a
  SyntaxError; drop the trailing duplicate.
@mateo-berri

Copy link
Copy Markdown
Contributor

bugbot run

@mateo-berri

Copy link
Copy Markdown
Contributor

@greptileai

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 71f5b89. Configure here.

@mateo-berri mateo-berri added run-ci and removed run-ci labels Sep 3, 2026
…itellm_python_version_ci

# Conflicts:
#	basedpyright-code-budget.json
#	tests/sdk_function_trace/profiler.py
#	tests/sdk_function_trace/test_profiler.py
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: LiteLLM is not compat with Python 3.10 [Bug]: pydantic.errors.PydanticUserError: Message is not fully defined

3 participants