Type Checking with MyPy
The Abstract Backend ships with a minimal types.py module and py.typed marker to show how to distribute type information (PEP 561) from the start. This page explains how to adapt that example for your project, keep your annotations healthy, and run MyPy with uv.
PEP Support Out of the Boxβ
The template configuration aligns with common typing standards:
- PEP 484 β Type hints
- PEP 585 β Generic type hints for built-ins
- PEP 561 β Distributing type information via
py.typed - PEP 695 β Modern
typestatement alias syntax (Python β₯3.12)
Where Types Liveβ
- Default location:
src/<your_package>/types.py - Marker file:
src/<your_package>/py.typed - Public exports: declare symbols in
__all__so type checkers know whatβs available.
type Percentage = float
type JSONDict = dict[str, "JSONValue"]
type JSONValue = str | int | float | bool | None | JSONDict | list["JSONValue"]
__all__ = ["Percentage", "JSONDict", "JSONValue"]
When you rename the package directory, update the paths in pyproject.toml, .github/workflows/type-check.yml, and any imports to match your chosen package name.
Running MyPy with uvβ
The template keeps tooling simple:
# Install dependencies declared in pyproject.toml
uv sync
# Run mypy on the entire package
uv run mypy src/
# Target a submodule or run strict mode on demand
uv run mypy src/your_package/types.py
uv run mypy --strict src/your_package/
pyproject.toml contains default MyPy settings β adjust mypy.ini or pyproject.toml if you prefer a different configuration style.
Pre-commit Hook Integrationβ
A MyPy hook is already listed in .pre-commit-config.yaml. After running uv sync, enable the hooks:
pre-commit install
pre-commit run mypy --all-files
This mirrors what happens in CI and prevents untyped or mis-typed code from landing in the main branch.
Publishing Types (PEP 561)β
To ensure consumers receive your type information when installing from PyPI:
- Keep
py.typedin the root of your package. - Export symbols through
__all__intypes.py(or via your package root__init__.py). - If you restructure files, update
.github/workflows/type-check.ymlso the workflow monitors the correct paths. - Uncomment and adjust the
artifactsentries inpyproject.toml(wheel/sdist targets) if you rely on Hatch to copy additional files.
Customizing the Exampleβ
- Rename the package β Replace
your_packageeverywhere with your actual package name. - Expand
types.pyβ Add Protocols, TypedDicts, Literal types, etc., that match your domain. - Document Types β Reference your new definitions in docstrings or docs so teammates know they exist.
- Add tests β Validate runtime helpers (type guards, validator helpers) just like any other logic.
Type Distribution Workflowβ
The template includes .github/workflows/type-check.yml, which validates that types.py and py.typed end up inside distribution artifacts. After you rename your package, update the paths in that workflow (e.g., change src/your_package/types.py). See the PEP 561 Type Distribution Workflow for a full walkthrough.
Troubleshooting Checklistβ
- Imports fail in CI β Ensure the package name in MyPy command matches your src layout (e.g.,
uv run mypy src/). py.typedmissing β Confirm the file exists and, if you changed build tools, that itβs included in wheel/sdist artifacts.- Pre-commit slows down β Enable MyPy caching by adding
cache_dirto configuration or leverageuv run mypy --dirtylocally. - Third-party stubs missing β Install stub packages via
uv add types-requests(theyβre automatically tracked inuv.lock).
Helpful Referencesβ
- MyPy docs
- PEP 561 β Distributing Type Information
- PEP 695 β Type Parameter Syntax
- uv documentation
Keep this file tailored to your real codebase once you flesh out the template. Treat the existing content as scaffolding and expand it as your project grows.