From 4b32d34bd33889162222d1bd235fe016f0dd898b Mon Sep 17 00:00:00 2001 From: Patrick Roddy Date: Fri, 12 Jun 2026 12:29:55 +0100 Subject: [PATCH 1/6] Make sure `prek` only runs on top level --- .prekignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 .prekignore diff --git a/.prekignore b/.prekignore new file mode 100644 index 00000000..00ca4657 --- /dev/null +++ b/.prekignore @@ -0,0 +1 @@ +tests/data/ From c956a4eacda2832c92fcce5f4d79178d19f21e57 Mon Sep 17 00:00:00 2001 From: Patrick Roddy Date: Fri, 12 Jun 2026 12:30:30 +0100 Subject: [PATCH 2/6] Swap out `mypy` for `ty` in code --- .pre-commit-config.yaml | 12 ++++++------ pyproject.toml | 6 ++++++ .../test_package_generation/.pre-commit-config.yaml | 10 +++++++--- tests/data/test_package_generation/pyproject.toml | 12 ++++++++---- .../src/cookiecutter_test/__init__.py | 2 +- .../.pre-commit-config.yaml | 10 +++++++--- {{cookiecutter.project_slug}}/pyproject.toml | 12 ++++++++---- .../src/{{cookiecutter.package_name}}/__init__.py | 2 +- 8 files changed, 44 insertions(+), 22 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index faedc096..6de349e6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -23,14 +23,14 @@ repos: rev: v0.24.4 hooks: - id: toml-sort-fix - - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.20.2 + - repo: https://github.com/astral-sh/ty-pre-commit + rev: v0.0.49 hooks: - - id: mypy + - id: ty args: - - --config-file=pyproject.toml - additional_dependencies: - - pytest + - --group=typechecking + - --isolated + - --no-default-groups - repo: https://github.com/rbubley/mirrors-prettier rev: v3.8.3 hooks: diff --git a/pyproject.toml b/pyproject.toml index 2ab54710..7beb426e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,9 @@ +[dependency-groups] +typechecking = [ + "pytest", + "pytest-venv", +] + [tool.pytest.ini_options] addopts = [ "--color=yes", diff --git a/tests/data/test_package_generation/.pre-commit-config.yaml b/tests/data/test_package_generation/.pre-commit-config.yaml index dd68b7bf..de653007 100644 --- a/tests/data/test_package_generation/.pre-commit-config.yaml +++ b/tests/data/test_package_generation/.pre-commit-config.yaml @@ -18,10 +18,14 @@ repos: rev: v0.24.4 hooks: - id: toml-sort-fix - - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.20.2 + - repo: https://github.com/astral-sh/ty-pre-commit + rev: v0.0.49 hooks: - - id: mypy + - id: ty + args: + - --group=typechecking + - --isolated + - --no-default-groups - repo: https://github.com/rbubley/mirrors-prettier rev: v3.8.3 hooks: diff --git a/tests/data/test_package_generation/pyproject.toml b/tests/data/test_package_generation/pyproject.toml index e5ee29bd..327367af 100644 --- a/tests/data/test_package_generation/pyproject.toml +++ b/tests/data/test_package_generation/pyproject.toml @@ -8,11 +8,11 @@ requires = [ [dependency-groups] dev = [ "build", - "mypy", "pre-commit", "ruff", "tox", "twine", + "ty", ] docs = [ "mkdocs-include-markdown-plugin", @@ -25,6 +25,9 @@ test = [ "pytest", "pytest-cov", ] +typechecking = [ + "pytest", +] [project] authors = [ @@ -67,9 +70,6 @@ paths.source = [ ".tox*/*/lib/python*/site-packages", ] -[tool.mypy] -explicit_package_bases = true - [tool.pytest.ini_options] addopts = [ "--color=yes", @@ -148,3 +148,7 @@ gh.python."3.11" = ["py311"] gh.python."3.12" = ["py312"] gh.python."3.13" = ["py313"] gh.python."3.14" = ["py314"] + +[tool.ty] +analysis.respect-type-ignore-comments = false +terminal.error-on-warning = true diff --git a/tests/data/test_package_generation/src/cookiecutter_test/__init__.py b/tests/data/test_package_generation/src/cookiecutter_test/__init__.py index a37fbaec..2e38966d 100644 --- a/tests/data/test_package_generation/src/cookiecutter_test/__init__.py +++ b/tests/data/test_package_generation/src/cookiecutter_test/__init__.py @@ -1,6 +1,6 @@ """cookiecutter_test package.""" -from ._version import __version__ # noqa: F401 +from ._version import __version__ # noqa: F401 # ty: ignore[unresolved-import] def example_function(argument: str, keyword_argument: str = "default") -> str: diff --git a/{{cookiecutter.project_slug}}/.pre-commit-config.yaml b/{{cookiecutter.project_slug}}/.pre-commit-config.yaml index dd68b7bf..de653007 100644 --- a/{{cookiecutter.project_slug}}/.pre-commit-config.yaml +++ b/{{cookiecutter.project_slug}}/.pre-commit-config.yaml @@ -18,10 +18,14 @@ repos: rev: v0.24.4 hooks: - id: toml-sort-fix - - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.20.2 + - repo: https://github.com/astral-sh/ty-pre-commit + rev: v0.0.49 hooks: - - id: mypy + - id: ty + args: + - --group=typechecking + - --isolated + - --no-default-groups - repo: https://github.com/rbubley/mirrors-prettier rev: v3.8.3 hooks: diff --git a/{{cookiecutter.project_slug}}/pyproject.toml b/{{cookiecutter.project_slug}}/pyproject.toml index cdc1ced8..433e5d89 100644 --- a/{{cookiecutter.project_slug}}/pyproject.toml +++ b/{{cookiecutter.project_slug}}/pyproject.toml @@ -8,11 +8,11 @@ requires = [ [dependency-groups] dev = [ "build", - "mypy", "pre-commit", "ruff", "tox", "twine", + "ty", ] docs = [ "mkdocs-include-markdown-plugin", @@ -25,6 +25,9 @@ test = [ "pytest", "pytest-cov", ] +typechecking = [ + "pytest", +] [project] authors = [ @@ -69,9 +72,6 @@ paths.source = [ ".tox*/*/lib/python*/site-packages", ] -[tool.mypy] -explicit_package_bases = true - [tool.pytest.ini_options] addopts = [ "--color=yes", @@ -154,3 +154,7 @@ env.docs = {commands = [ ) %} gh.python."3.{{python_version}}" = ["py3{{python_version}}"] {%- endfor %} + +[tool.ty] +analysis.respect-type-ignore-comments = false +terminal.error-on-warning = true diff --git a/{{cookiecutter.project_slug}}/src/{{cookiecutter.package_name}}/__init__.py b/{{cookiecutter.project_slug}}/src/{{cookiecutter.package_name}}/__init__.py index 456257d0..4d0f9cb8 100644 --- a/{{cookiecutter.project_slug}}/src/{{cookiecutter.package_name}}/__init__.py +++ b/{{cookiecutter.project_slug}}/src/{{cookiecutter.package_name}}/__init__.py @@ -1,6 +1,6 @@ """{{cookiecutter.package_name}} package.""" -from ._version import __version__ # noqa: F401 +from ._version import __version__ # noqa: F401 # ty: ignore[unresolved-import] def example_function(argument: str, keyword_argument: str = "default") -> str: From a22ef677d6c855dcd937dece6b7706b974126b9e Mon Sep 17 00:00:00 2001 From: Patrick Roddy Date: Fri, 12 Jun 2026 12:30:43 +0100 Subject: [PATCH 3/6] Update docs --- docs/pages/libraries/jupyter-notebooks.md | 4 ++-- docs/pages/linting.md | 7 ++++--- docs/pages/tutorial.md | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/docs/pages/libraries/jupyter-notebooks.md b/docs/pages/libraries/jupyter-notebooks.md index 5fb8eb8e..9307689a 100644 --- a/docs/pages/libraries/jupyter-notebooks.md +++ b/docs/pages/libraries/jupyter-notebooks.md @@ -32,7 +32,7 @@ more reliably than [black] via [nbQA]. | Name | Short description | 🚦 | | ---------------- | -------------------------------------------------------------------------------- | :------------------------------------------: | | `black[jupyter]` | (also `black-jupyter`) [black] with the optional Jupyter extension. | Best | -| [nbQA] | Recommended for all other linters ([ruff], [isort]) and [mypy]. | Best | +| [nbQA] | Recommended for all other linters ([ruff], [isort]) and [ty]. | Best | | [pre-commit] | Has cell output cleanup hooks (if desired). Also found to work well with [nbQA]. | Best | | `nbqa black` | [black] via [nbQA]. | Good | @@ -48,7 +48,7 @@ more reliably than [black] via [nbQA]. [nbQA]: https://nbqa.readthedocs.io/en/latest/index.html [isort]: https://pycqa.github.io/isort [ruff]: https://github.com/charliermarsh/ruff -[mypy]: https://mypy.readthedocs.io/en/stable +[ty]: https://docs.astral.sh/ty/ [pre-commit]: https://github.com/kynan/nbstripout [jupytext]: https://jupytext.readthedocs.io/en/stable/ diff --git a/docs/pages/linting.md b/docs/pages/linting.md index 1983cc0a..942179da 100644 --- a/docs/pages/linting.md +++ b/docs/pages/linting.md @@ -29,9 +29,10 @@ for some of these. ### Type checking -| Name | Short description | 🚦 | -| ---------------------------------------------- | ----------------------------------------------------------------------------- | :-----------------------------------------: | -| [mypy](https://mypy.readthedocs.io/en/stable/) | Static type checker, won't fail if no typing but will if typing is incorrect. | Best | +| Name | Short description | 🚦 | +| ---------------------------------------------- | ----------------------------------------------------------------------------- | :------------------------------------------: | +| [ty](https://docs.astral.sh/ty/) | Static type checker, fast and rapidly developing. | Best | +| [mypy](https://mypy.readthedocs.io/en/stable/) | Static type checker, won't fail if no typing but will if typing is incorrect. | Good | ### Dependency checking diff --git a/docs/pages/tutorial.md b/docs/pages/tutorial.md index f9a51cc4..baa47f04 100644 --- a/docs/pages/tutorial.md +++ b/docs/pages/tutorial.md @@ -403,7 +403,7 @@ The package is set-up to use [pre-commit](https://pre-commit.com/), a framework There is a `.pre-commit-config.yaml` configuration file which you can take a look at. With this setup `pre-commit` will run a series of fast linters, checks and formatters on the repository on every commit. -The main tools we recommend are [ruff](https://docs.astral.sh/ruff/), [mypy](https://mypy.readthedocs.io/en/stable/) and [prettier](https://prettier.io/). +The main tools we recommend are [ruff](https://docs.astral.sh/ruff/), [ty](https://docs.astral.sh/ty/) and [prettier](https://prettier.io/). These Git hook scripts can installed locally by running ```sh From 33275da28a64ad1ce43acf629af8ef29e512d88a Mon Sep 17 00:00:00 2001 From: Patrick Roddy Date: Fri, 12 Jun 2026 12:39:12 +0100 Subject: [PATCH 4/6] Comments whitespace --- .../test_package_generation/src/cookiecutter_test/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/data/test_package_generation/src/cookiecutter_test/__init__.py b/tests/data/test_package_generation/src/cookiecutter_test/__init__.py index 2e38966d..1094344c 100644 --- a/tests/data/test_package_generation/src/cookiecutter_test/__init__.py +++ b/tests/data/test_package_generation/src/cookiecutter_test/__init__.py @@ -1,6 +1,6 @@ """cookiecutter_test package.""" -from ._version import __version__ # noqa: F401 # ty: ignore[unresolved-import] +from ._version import __version__ # noqa: F401 # ty: ignore[unresolved-import] def example_function(argument: str, keyword_argument: str = "default") -> str: From 738e894bfb20f31f1de48bba7077adb93b744c36 Mon Sep 17 00:00:00 2001 From: Patrick Roddy Date: Fri, 12 Jun 2026 12:47:13 +0100 Subject: [PATCH 5/6] Use `ty` overrides --- pyproject.toml | 6 ++++++ .../src/cookiecutter_test/__init__.py | 2 +- .../src/{{cookiecutter.package_name}}/__init__.py | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 7beb426e..4e0cedc3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -72,3 +72,9 @@ gh.python = {"3.11" = [ ], "3.14" = [ "py314", ]} + +[[tool.ty.overrides]] +include = [ + "**/src/*/__init__.py", +] +rules.unresolved-import = "ignore" diff --git a/tests/data/test_package_generation/src/cookiecutter_test/__init__.py b/tests/data/test_package_generation/src/cookiecutter_test/__init__.py index 1094344c..a37fbaec 100644 --- a/tests/data/test_package_generation/src/cookiecutter_test/__init__.py +++ b/tests/data/test_package_generation/src/cookiecutter_test/__init__.py @@ -1,6 +1,6 @@ """cookiecutter_test package.""" -from ._version import __version__ # noqa: F401 # ty: ignore[unresolved-import] +from ._version import __version__ # noqa: F401 def example_function(argument: str, keyword_argument: str = "default") -> str: diff --git a/{{cookiecutter.project_slug}}/src/{{cookiecutter.package_name}}/__init__.py b/{{cookiecutter.project_slug}}/src/{{cookiecutter.package_name}}/__init__.py index 4d0f9cb8..456257d0 100644 --- a/{{cookiecutter.project_slug}}/src/{{cookiecutter.package_name}}/__init__.py +++ b/{{cookiecutter.project_slug}}/src/{{cookiecutter.package_name}}/__init__.py @@ -1,6 +1,6 @@ """{{cookiecutter.package_name}} package.""" -from ._version import __version__ # noqa: F401 # ty: ignore[unresolved-import] +from ._version import __version__ # noqa: F401 def example_function(argument: str, keyword_argument: str = "default") -> str: From a3956c647c56ac74b3ac9bfc61d764c6ca8ac8da Mon Sep 17 00:00:00 2001 From: Patrick Roddy Date: Fri, 12 Jun 2026 13:13:09 +0100 Subject: [PATCH 6/6] Add missing `be` Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- docs/pages/tutorial.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pages/tutorial.md b/docs/pages/tutorial.md index baa47f04..49e40324 100644 --- a/docs/pages/tutorial.md +++ b/docs/pages/tutorial.md @@ -404,7 +404,7 @@ There is a `.pre-commit-config.yaml` configuration file which you can take a loo With this setup `pre-commit` will run a series of fast linters, checks and formatters on the repository on every commit. The main tools we recommend are [ruff](https://docs.astral.sh/ruff/), [ty](https://docs.astral.sh/ty/) and [prettier](https://prettier.io/). -These Git hook scripts can installed locally by running +These Git hook scripts can be installed locally by running ```sh pre-commit install