What is going on
Three things are inconsistent, which is why this looks confusing:
-
The package advertises inline type information. src/src_method/py.typed
exists and pyproject.toml declares the Typing :: Typed classifier. Both
are a promise to downstream users that they can type-check their code
against our annotations (PEP 561).
-
Nothing verifies that promise. No type checker runs in CI, in
pre-commit, or anywhere else.
-
There is a leftover config for a checker that is never invoked.
pyproject.toml contains a 20-line [tool.pyright] block — inherited from
the project template — but pyright is not in any dependency group and is
never executed. It is dead configuration that makes it look like type
checking is covered when it is not.
So we ship a typing guarantee we do not test. If an annotation drifts out of
sync with the implementation, nobody finds out; the downstream user does.
Good news
I ran a checker against the package as it stands and it is essentially already
clean:
$ uvx ty check src/
error[unresolved-import]: Cannot resolve imported module `cupy`
--> src/src_method/utils/_backend.py:37
Found 1 diagnostic
The single diagnostic is the deliberately lazy, optional cupy import. So
enforcing this is cheap — it is a matter of wiring, not of fixing a backlog.
Proposed fix
Use the modern Astral toolchain, consistent with the uv + ruff setup
already in place:
- Adopt
ty as the type checker and add it
to the dev dependency group.
- Replace the dead
[tool.pyright] block with a [tool.ty] section:
target Python 3.11, check src/, and silence the optional cupy import
(via an ignore rule or a TYPE_CHECKING stub) rather than leaving a real
error in the baseline.
- Add a
ty check step to the lint workflow and to .pre-commit-config.yaml
so it gates pull requests.
- Tighten the annotations that are currently loose while we are here:
dtype: type should be numpy.typing.DTypeLike, and the bare NDArray in
utils/linalg.py should carry its generic parameter.
One caveat worth stating openly: ty is pre-1.0 and still moving. If we would
rather have stability than novelty, mypy is the conservative choice and the
rest of this issue is unchanged. Either is better than the current situation.
Acceptance criteria
What is going on
Three things are inconsistent, which is why this looks confusing:
The package advertises inline type information.
src/src_method/py.typedexists and
pyproject.tomldeclares theTyping :: Typedclassifier. Bothare a promise to downstream users that they can type-check their code
against our annotations (PEP 561).
Nothing verifies that promise. No type checker runs in CI, in
pre-commit, or anywhere else.There is a leftover config for a checker that is never invoked.
pyproject.tomlcontains a 20-line[tool.pyright]block — inherited fromthe project template — but
pyrightis not in any dependency group and isnever executed. It is dead configuration that makes it look like type
checking is covered when it is not.
So we ship a typing guarantee we do not test. If an annotation drifts out of
sync with the implementation, nobody finds out; the downstream user does.
Good news
I ran a checker against the package as it stands and it is essentially already
clean:
The single diagnostic is the deliberately lazy, optional
cupyimport. Soenforcing this is cheap — it is a matter of wiring, not of fixing a backlog.
Proposed fix
Use the modern Astral toolchain, consistent with the
uv+ruffsetupalready in place:
tyas the type checker and add itto the
devdependency group.[tool.pyright]block with a[tool.ty]section:target Python 3.11, check
src/, and silence the optionalcupyimport(via an ignore rule or a
TYPE_CHECKINGstub) rather than leaving a realerror in the baseline.
ty checkstep to thelintworkflow and to.pre-commit-config.yamlso it gates pull requests.
dtype: typeshould benumpy.typing.DTypeLike, and the bareNDArrayinutils/linalg.pyshould carry its generic parameter.One caveat worth stating openly:
tyis pre-1.0 and still moving. If we wouldrather have stability than novelty,
mypyis the conservative choice and therest of this issue is unchanged. Either is better than the current situation.
Acceptance criteria
[tool.pyright]block is gone.cupyimport is handled without leaving an error in the baseline.dtypeandNDArrayannotations are precise.