Choose your strictness level¶
The template offers a single axis — strictness — that controls both how
strictly type annotations are required and how thorough the static-analysis
toolchain is. Pick one level when prompted; it drives the generated
pyproject.toml, task-runner tasks and CI configuration together.
The 4 levels¶
| Level | Type annotations | Type checkers | Static analysis | Ruff |
|---|---|---|---|---|
none |
Not required | None | None | Minimal set (pycodestyle, pyflakes, isort) |
basic |
Not required | None | None | Basic set (bugbear, pycodestyle, isort, pyupgrade, ...) |
recommended |
Partial (fully-untyped functions pass) | basedpyright + secondary (pyrefly by default) | typos, vulture, deptry (+ audit on demand: pip-audit) |
ALL rules with pragmatic ignores |
full |
All functions annotated | basedpyright (strict, Any forbidden) + secondary (pyrefly/ty) |
Same as recommended | ALL rules with minimal ignores |
none: pytest + ruff with a minimal rule set. No type checking, no static analysis. For throwaway scripts and experiments.basic: pytest + ruff with a curated basic rule set. No type checking. Good for small prototypes that still want consistent style.recommended(default): the full toolchain — ruff withALLrules (preview enabled, pragmaticWHYNOTignores), basedpyright (always) plus your chosen secondary checker (type_checker: pyrefly by default, or ty), typos / vulture / deptry, driven by your task runner. Partially-annotated functions are allowed. Dependency auditing is a separate on-demandaudittask (pip-audit, needs network) so offlinetype-check/check/CI stays green.full: everything in recommended plus strict type checking.Anyis forbidden (reportAnyetc.), every function must be annotated, and ruff's ignores are minimized. When ty is the secondary checker, it additionally treats unresolved references as errors. Best for a brand-new project you intend to maintain long-term.
How to Choose¶
When creating a project, select your strictness level when prompted.
none: you want fast iteration without thinking about types or style. Good for throwaway scripts and experiments.basic: you want consistent style but no type checking.recommended(default): a balanced default. Fits both new code and applying the template to existing code.full: you treatAnyas a code smell and want strict typing from day one. Best for a brand-new project you intend to maintain long-term.
Lessons from practice¶
fullis for new projects. Applying strict mode to legacy code can produce thousands of errors. Userecommendedfor retrofits.recommendedsurvives retrofits.analyzeUnannotatedFunctions = falseskips fully-untyped functions, so an existing codebase stays green while new code gets stricter.Anyis sometimes necessary. Libraries likeboto3without full stubs needAny(ortypes-boto3).fullrequires the latter.- Type checkers are not interchangeable.
# pyright: ignore[Rule]is the correct comment for pyright-based checkers; mypy's# type: ignore[code]codes are not recognized.