diff --git a/STANDARD.md b/STANDARD.md index e803ab4..ce9793f 100644 --- a/STANDARD.md +++ b/STANDARD.md @@ -406,6 +406,7 @@ following rules: * isort * pylint (convention and error only) * pyupgrade +* flake8-type-checking Configuration should live in the top-level `pyproject.toml` file: @@ -417,6 +418,7 @@ select = [ "I", # isort "PLC", "PLE", # pylint "UP", # pyupgrade + "TCH", # flake8-type-checking ] ignore = [ "E501", # let black handle line-length @@ -440,3 +442,57 @@ repos: Be sure to run `pre-commit autoupdate` to pick up the latest version. [ruff]: https://pypi.org/project/ruff/ + +### Type Checking + +Projects should use [Pyright] for type checking. Pyright has advanced type +inference capabilities, so can provide value even on projects that don't have +any type annotations. + +While annotations aren't necessary for Pyright to function, providing them +allows both Pyright and other developers to understand the code base in more +depth. As such, annotations should be enforced for new projects. + +Configuration for Pyright should live in the top-level `pyproject.toml` file: + +```toml +[tool.pyright] +include = "src/" +reportUnknownParameterType = "error" +``` + +The `reportUnknownParameterType` config enforces type annotations. If enabling +Pyright on an existing project that is missing annotations, it is recommended +to omit this config. In this case, see [Getting Started with Type Checking] for +a recommended incremental upgrade path. + +#### Where to Run + +Pyright should be run as a Taskcluster task, similar to: + +```yaml +type-check: + description: "Run Pyright type checking against code base" + worker-type: linux + worker: + docker-image: {in-tree: python} + max-run-time: 300 + run: + using: run-task + cwd: '{checkout}' + cache-dotcache: true + command: >- + poetry install --only main --only type && + poetry run pyright +``` + +While it's possible to run as a [pre-commit hook], this method isn't +recommended as Pyright needs to run in an environment where the project's +dependencies are installed. This means either the dependencies need to be +listed a second time in `pre-commit-config.yaml`, or Pyright needs to be +explicitly told about Poetry's virtualenv (which varies from person to person +and shouldn't be committed in the config file). + +[Pyright]: https://github.com/Microsoft/pyright +[Getting Started with Type Checking]: https://microsoft.github.io/pyright/#/getting-started +[pre-commit hook]: https://microsoft.github.io/pyright/#/ci-integration?id=running-pyright-as-a-pre-commit-hook diff --git a/reps/hooks.py b/reps/hooks.py index 61dbf3e..77f9322 100644 --- a/reps/hooks.py +++ b/reps/hooks.py @@ -111,6 +111,11 @@ def build_specifiers(*packages): + list(build_specifiers("sphinx<7", "sphinx-autobuild", "sphinx-book-theme")) ) + run( + ["poetry", "add", "--group=type"] + + list(build_specifiers("pyright")) + ) + @hook("post-gen-py") @hook("post-gen-base") diff --git a/reps/templates/python/{{cookiecutter.__project_slug}}/pyproject.toml b/reps/templates/python/{{cookiecutter.__project_slug}}/pyproject.toml index fc960e8..bb29ad5 100644 --- a/reps/templates/python/{{cookiecutter.__project_slug}}/pyproject.toml +++ b/reps/templates/python/{{cookiecutter.__project_slug}}/pyproject.toml @@ -27,6 +27,7 @@ select = [ "I", # isort "PLC", "PLE", # pylint "UP", # pyupgrade + "TCH", # flake8-type-checking ] ignore = [ "E501", # let black handle line-length @@ -36,6 +37,10 @@ target-version = "py{{cookiecutter.__min_tox_python_version}}" [tool.ruff.isort] known-first-party = ["{{cookiecutter.__package_name}}"] +[tool.pyright] +include = ["src/{{cookiecutter.__package_name}}"] +reportUnknownParameterType = "error" + [build-system] requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" diff --git a/reps/templates/python/{{cookiecutter.__project_slug}}/taskcluster/ci/test/kind.yml b/reps/templates/python/{{cookiecutter.__project_slug}}/taskcluster/ci/test/kind.yml index 8a787d3..2e2ed1c 100644 --- a/reps/templates/python/{{cookiecutter.__project_slug}}/taskcluster/ci/test/kind.yml +++ b/reps/templates/python/{{cookiecutter.__project_slug}}/taskcluster/ci/test/kind.yml @@ -34,3 +34,12 @@ tasks: command: >- poetry install --only test && poetry run tox --parallel + + type-check: + description: "Run pyright type checking against code base" + worker: + max-run-time: 300 + run: + command: >- + poetry install --only main --only type && + poetry run pyright