developmentseed / developmentseed/titiler-covjson
Add a tests/typing/ consumer typing-conformance suite (+ negative tests)
- Dominant language
- Python
- Stars
- 1
- Forks
- 1
- Avg merge
- 2d 1h
- Merged PRs (30d)
- 12
Description
**Depends on #30** (the multi-checker type-check matrix). The conformance tests are only meaningful once mypy + basedpyright run as blocking strict gates across the matrix.
## Summary
Add a `tests/typing/` suite that imports `titiler-covjson` exactly as a downstream consumer would and asserts the **types the public API presents**, using `typing.assert_type`. Include **negative tests** that fail if a public signature ever silently *weakens*. Because `assert_type` is a runtime no-op, these are ordinary pytest tests (they run under the suite) and are simultaneously analyzed by every checker in the matrix.
## Motivation
The matrix from #30 checks the package's **internal self-consistency** -- that our own code type-checks under multiple checkers. It does not check what types a *consumer* observes when they `import titiler_covjson...` and call public functions. Those can differ (stub resolution, re-exported third-party types, inferred returns). `stubtest` is not the right tool -- it works only against separate `.pyi` stubs, and this package ships inline PEP 561 annotations (`py.typed`). A consumer module that exercises the API and asserts inferred types is the correct approach, and running it under the multi-checker matrix means all blocking checkers must agree on the public guarantees.
Separately, nothing currently fails CI if a public signature silently *widens* (a parameter type loosens). Negative tests guarded by `warn_unused_ignores` turn that silent regression into a CI failure.
## Scope
### 1. `tests/typing/` conformance tests (real pytest tests using `assert_type`)
- Add `tests/typing/test_typing_*.py` files importing the public API as a consumer would (`from titiler_covjson.input import ...`, `from titiler_covjson.helpers import ...` -- the package root deliberately re-exports nothing) and asserting inferred types with `typing.assert_type`.
- Use `reveal_type` only as a development aid, not in committed assertions.
Initial public surface to cover:
- `titiler_covjson.input`: `BandInfo`, `GridInput`, `CoverageInput` (the alias), `band_info_from_reader_info(info: Info) -> list[BandInfo]`, `imagedata_to_coverage_input(...)`.
- `titiler_covjson.helpers`: `create_spatial_2d_reference`, `create_temporal_reference`, `create_unit(...) -> Unit | None`, `crs_to_ogc_uri`, `numpy_dtype_to_ndarray`, `numpy_to_covjson_dtype`.
Expand incrementally as the public API grows (Point/PointSeries, `to_coverage_collection`, the endpoints).
### 2. Negative tests (guard against signature weakening)
- Add at least one test that deliberately passes a wrong-typed argument to a public function, silenced by mypy's precise `# type: ignore[arg-type]`. With `warn_unused_ignores` (on under `strict`), the ignore *trips* if the public signature ever weakens to accept that argument.
- For checkers that do not honor mypy's error code (`ty`), relax just that one rule for just those files via `[[tool.ty.overrides]]`, so mypy + basedpyright stay fully strict and cannot mask a real weakness.
### 3. Strictness
- `tests/typing/` is checked under the same **uniform strict** settings as the rest of the tree (#30). It must **not** be added to the existing `[[tool.mypy.overrides]]` that relaxes `disallow_untyped_calls` for the older test modules -- the conformance tests need full strictness or `assert_type` would not genuinely verify the surface.
## Acceptance criteria
- `tests/typing/` exists with `assert_type`-based conformance tests importing the package as an external consumer, plus at least one negative (weakening-guard) test.
- All blocking checkers (mypy + basedpyright) pass on `tests/typing/` across 3.11--3.13.
- Deliberately weakening a public signature causes the blocking checks to fail.
- `pytest` (incl. `--doctest-modules`) stays green and the conformance tests are collected and pass.
## Out of scope
- Runtime/behavioral testing of the converters (covered by the existing suite). This issue is purely about the *type* surface a consumer observes and cross-checker agreement on it.
Follow-up to #27 / PR #29; depends on #30.
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.