Skip to content

refactor(e2e): type the claude_code suite and drop its basedpyright exclusion - #33480

Open
mateo-berri wants to merge 2 commits into
litellm_internal_stagingfrom
litellm_claude_code_suite_typing
Open

refactor(e2e): type the claude_code suite and drop its basedpyright exclusion#33480
mateo-berri wants to merge 2 commits into
litellm_internal_stagingfrom
litellm_claude_code_suite_typing

Conversation

@mateo-berri

Copy link
Copy Markdown
Contributor

Relevant issues

Resolves caveat 7 of #32548: tests/e2e/claude_code predated the zero-error tests/e2e basedpyright gate and was excluded in pyrightconfig.json with ~1,800 strict-mode errors. This PR types the whole suite and drops the exclusion, so the suite is now covered by the same zero-error gate as the rest of tests/e2e

Linear ticket

Pre-Submission checklist

Please complete all items before asking a LiteLLM maintainer to review your PR

  • I have added meaningful tests (typing-only refactor; the regression net is the make lint-e2e-basedpyright gate itself, which now covers the suite at zero errors)
  • My PR passes all CI/CD checks (e.g., lint, format, unit tests)
  • My PR's scope is as isolated as possible; it only solves 1 specific problem
  • I have received a Greptile Confidence Score of at least 4/5 before requesting a maintainer review (Greptile reviews automatically once the PR is opened; only comment @greptileai to re-request a review after pushing changes)

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

This change has no proxy runtime surface; nothing an end user calls changes behavior. The user-visible surface is the lint gate itself, so the proof is the gate flipping from ~1,839 errors to zero with the exclusion removed, while the suite's non-live structural tests pass identically before and after

Before, at base commit ff4a40f with only the "tests/e2e/claude_code" exclude entry removed from pyrightconfig.json:

$ uv run --no-sync basedpyright tests/e2e
1839 errors, 0 warnings, 0 notes

After, at cfa7f54, the real gate invocation:

$ make lint-e2e-basedpyright
uv run --no-sync basedpyright tests/e2e
0 errors, 0 warnings, 0 notes

Structural (non-live) suites, identical results at ff4a40f and at cfa7f54:

$ uv run --no-sync pytest tests/e2e/claude_code/_driver_unit_tests tests/e2e/claude_code/_builder_unit_tests \
    tests/e2e/claude_code/_publisher_unit_tests tests/e2e/claude_code/_pr_gate_unit_tests -q
2 failed, 337 passed

The 2 failures are pre-existing at the base commit and unrelated to this PR: _publisher_unit_tests/test_run_daily_release_pagination.py shells out to curl https://api.github.com/..., which this sandboxed environment blocks; they fail with the same CalledProcessError before and after

Collection is also unchanged at both commits:

$ uv run --no-sync pytest tests/e2e/claude_code --collect-only -q
414 tests collected

The repo-wide budget gate is unaffected (its include is scoped to litellm/), verified at cfa7f54:

$ make lint-basedpyright
OK: every rule is within its basedpyright limit or no higher than base (156150 errors total)

Type

🧹 Refactoring

Changes

Removes "tests/e2e/claude_code" from the pyrightconfig.json exclude array and brings all 116 files of the suite to zero errors under typeCheckingMode: strict with reportAny/reportExplicitAny as errors. Annotation and boundary-validation work only; no behavior, prompts, model lists, assertion semantics, or public helper names changed

A new tests/e2e/claude_code/json_types.py provides the shared vocabulary: a recursive JSONValue alias (str | int | float | bool | None | list[JSONValue] | dict[str, JSONValue]), JSONObject = dict[str, JSONValue], and pydantic TypeAdapters used to validate every untyped boundary (json.loads, yaml.safe_load, HTTP bodies, CLI stream-json lines) into the typed shape instead of letting Any leak. Everything JSON-shaped the suite touches (stream-json events, npm packuments, manifest YAML, results artifacts, rate-limiter state files) flows through it, and isinstance checks narrow it where the code already defensively branched

Core modules define the typed contract: cli_driver.py gains a CommandRunner protocol for the injected subprocess runner (with a _run_subprocess default satisfying it) and DriverResult.events: list[JSONObject]; conftest.py types CompatResult payloads as Mapping[str, JSONValue], the pytest hooks (pluggy.Result[pytest.TestReport] hookwrapper, pytest.Session, pytest.Function.funcargs), and models the rate-limit summary as a TypedDict; rate_limiter.py, matrix_builder.py, http_probe.py, _basic_messaging.py, pr_gate_version_resolver.py, and cron_vm/build_matrix.py get fully typed signatures with pydantic validation at their file/wire boundaries. The 75 per-feature provider test files and the four _*_unit_tests/ trees were then annotated against that contract (typed compat_result: CompatResult fixtures, Mapping[str, JSONValue] event helpers, annotated fixture literals, narrowing helpers in the golden-file builder tests)

# type: ignore count is zero. Eight # pyright: ignore[exactRule] suppressions remain, each with a named rule and reason: two tests that deliberately pass a wrong type to assert a runtime TypeError, two autouse fixtures pytest invokes by name, one private-helper import a unit test exercises on purpose, two pytest.approx calls (unannotated upstream), and one urllib.request.urlopen boundary that typeshed types as Any

QA runbook

No e2e test was added and none changed behavior; every diff in tests/e2e/claude_code is annotations, isinstance narrowing, or boundary validation with identical runtime semantics, so there are no new manual steps to reproduce. The verification that matters is in the proof section above: the gate at zero errors, the four structural unit-test trees passing identically at the base and head commits, and unchanged test collection

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

@codecov

codecov Bot commented Jul 16, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@codspeed-hq

codspeed-hq Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 31 untouched benchmarks


Comparing litellm_claude_code_suite_typing (cfa7f54) with litellm_internal_staging (923c325)

Open in CodSpeed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant