Problem
The SDK itself runs mypy --strict (pyproject.toml [tool.mypy] strict = true) and ships type-check tests under tests/test_*_types.py. Those tests validate the SDK's internal types — they don't validate that adopter extension patterns type-check cleanly under the same strictness.
This means: the SDK can be internally strict-clean while still forcing every adopter who follows the recommended patterns to carry # type: ignore comments. We do — ~50 of them across our schema package, and a handful of [arg-type] / [attr-defined] ignores at SDK call sites. Each one is "the docs told me to do this; mypy disagrees; I shrug and silence it."
Without an adopter-pattern test suite, regressions can ship silently — the SDK passes its own tests, but downstream mypy --strict runs go from "100 ignores" to "150 ignores" between releases and nobody notices.
What the JS SDK has
@adcp/sdk (TypeScript) has dedicated *.type-checks.ts files alongside its runtime tests:
src/lib/server/adcp-server.type-checks.ts
src/lib/server/decisioning.type-checks.ts
src/lib/server/decisioning.type-checks.ts
These exercise extension patterns under TypeScript's strict mode, with the test passing iff the file compiles. tsc-equivalent CI gate.
Proposed SDK shape
A tests/type_checks/ directory of small, self-contained Python files that:
- Exercise documented adopter patterns (extend
LibraryProduct, override model_dump, return CreateMediaBuySubmittedResponse | CreateMediaBuySuccessResponse | CreateMediaBuyErrorResponse from a handler, construct BearerTokenAuth(validate_token=...) callbacks, etc.).
- Are run through
mypy --strict as a CI gate.
- Have zero
# type: ignore lines — that's the contract. If a pattern needs an ignore, the pattern is broken.
tests/type_checks/
├── extend_library_product.py # subclass + add internal field
├── extend_response_with_override.py # the pattern in #620
├── handler_three_branch_return.py # PlatformHandler.create_media_buy union
├── bearer_token_auth_callback.py # BearerTokenAuth(validate_token=...)
├── webhook_payload_construction.py # create_mcp_webhook_payload usage
├── lazy_platform_router_factory.py # async factory signature
└── nested_model_dump_subclass.py # the pattern in #615
CI step (Makefile target):
test-type-checks:
mypy --strict tests/type_checks/
How adopters contribute
Adopters who hit a strictness wall can submit a failing tests/type_checks/<my_pattern>.py as a reproducer. The SDK either:
- Fixes the typing so the pattern is clean (becomes part of CI), or
- Documents that the pattern requires a specific
cast(...) / explicit annotation (and adds the documented form to the test).
Either outcome is better than "shrug and silence" — the gap becomes visible.
Why this matters
Type ergonomics compound over time. If the SDK ships v5.0 and we discover at upgrade time that 30 new type: ignore lines are required, that's a high-friction migration. With an adopter-pattern test suite, those would surface during SDK PR review, not during downstream upgrades.
Concrete examples this would have caught (or made trivially diagnosable):
We can contribute the initial test files based on patterns we've already validated in production. Happy to send a draft PR if you like the shape.
Related
Problem
The SDK itself runs
mypy --strict(pyproject.toml [tool.mypy] strict = true) and ships type-check tests undertests/test_*_types.py. Those tests validate the SDK's internal types — they don't validate that adopter extension patterns type-check cleanly under the same strictness.This means: the SDK can be internally strict-clean while still forcing every adopter who follows the recommended patterns to carry
# type: ignorecomments. We do — ~50 of them across our schema package, and a handful of[arg-type]/[attr-defined]ignores at SDK call sites. Each one is "the docs told me to do this; mypy disagrees; I shrug and silence it."Without an adopter-pattern test suite, regressions can ship silently — the SDK passes its own tests, but downstream
mypy --strictruns go from "100 ignores" to "150 ignores" between releases and nobody notices.What the JS SDK has
@adcp/sdk(TypeScript) has dedicated*.type-checks.tsfiles alongside its runtime tests:src/lib/server/adcp-server.type-checks.tssrc/lib/server/decisioning.type-checks.tssrc/lib/server/decisioning.type-checks.tsThese exercise extension patterns under TypeScript's strict mode, with the test passing iff the file compiles. tsc-equivalent CI gate.
Proposed SDK shape
A
tests/type_checks/directory of small, self-contained Python files that:LibraryProduct, overridemodel_dump, returnCreateMediaBuySubmittedResponse | CreateMediaBuySuccessResponse | CreateMediaBuyErrorResponsefrom a handler, constructBearerTokenAuth(validate_token=...)callbacks, etc.).mypy --strictas a CI gate.# type: ignorelines — that's the contract. If a pattern needs an ignore, the pattern is broken.CI step (Makefile target):
test-type-checks: mypy --strict tests/type_checks/How adopters contribute
Adopters who hit a strictness wall can submit a failing
tests/type_checks/<my_pattern>.pyas a reproducer. The SDK either:cast(...)/ explicit annotation (and adds the documented form to the test).Either outcome is better than "shrug and silence" — the gap becomes visible.
Why this matters
Type ergonomics compound over time. If the SDK ships v5.0 and we discover at upgrade time that 30 new
type: ignorelines are required, that's a high-friction migration. With an adopter-pattern test suite, those would surface during SDK PR review, not during downstream upgrades.Concrete examples this would have caught (or made trivially diagnosable):
extract_webhook_result_datatyping mismatch (Type-annotation fixes for webhook helpers #598) — return-type test would have failed.create_mcp_webhook_payloaddictreturn type (feat(webhooks): create_mcp_webhook_payload should return McpWebhookPayload #607) — same._resolve_params_pydantic_modelbase-class resolution bug (_resolve_params_pydantic_modelresolves base-class annotation, breaking subclass-extended request validation #596) — extension-pattern test would have failed.We can contribute the initial test files based on patterns we've already validated in production. Happy to send a draft PR if you like the shape.
Related
model_dump()overridestype: ignore[assignment]mypy --stricton its own code; this proposes extending the strictness contract to adopter patterns.