Skip to content

Commit 5fe0bc4

Browse files
Implement usethis tool ty and usethis typecheck (#1446)
* Implement `usethis tool ty` and `usethis typecheck` * Bump uv fallback version * Update `TestGetUsageTable` to include ty * Include ty in `OTHER_TOOLS` * Elaborate on required updates in `CONTRIBUTING.md` * Remove `ty` from the benchmark `test_several_tools_add_and_remove` Add `--typecheck` support to `usethis init` * Use default ty config to analyze `src` and `tests` * Update failing test * Strengthen test in tests/usethis/_core/test_core_tool.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 6edd7ec commit 5fe0bc4

27 files changed

Lines changed: 1011 additions & 18 deletions

File tree

.importlinter

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ containers =
8080
usethis._tool.impl.base
8181
layers =
8282
pyproject_toml
83-
codespell | deptry | import_linter | mkdocs | pyproject_fmt | requirements_txt
83+
codespell | deptry | import_linter | mkdocs | pyproject_fmt | requirements_txt | ty
8484
ruff
8585
pytest : coverage_py
8686
pre_commit
@@ -93,7 +93,7 @@ containers =
9393
usethis._tool.impl.spec
9494
layers =
9595
pyproject_toml
96-
codespell | deptry | import_linter | mkdocs | pyproject_fmt | requirements_txt
96+
codespell | deptry | import_linter | mkdocs | pyproject_fmt | requirements_txt | ty
9797
ruff
9898
pytest : coverage_py
9999
pre_commit
@@ -128,7 +128,7 @@ type = layers
128128
containers =
129129
usethis._ui.interface
130130
layers =
131-
author | badge | browse | ci | doc | docstyle | format_ | init | lint | list | readme | rule | show | spellcheck | status | test | tool | version
131+
author | badge | browse | ci | doc | docstyle | format_ | init | lint | list | readme | rule | show | spellcheck | status | test | tool | typecheck | version
132132
exhaustive = true
133133

134134
[importlinter:contract:pipeweld]

CONTRIBUTING.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,9 +162,14 @@ Tool implementations are defined in classes in the `usethis._tool.impl` module.
162162

163163
- You should write tests in `tests/usethis/_core/test_core_tool` for the `use_*` function, following the pattern of the other tests in that module for other tools.
164164

165-
#### Pass tests
165+
#### Register the tool as a peer in `PyprojectTOMLTool`
166166

167-
- Some tests may break as a result of new test registration, for example the `TestGetUsageTable` tests for the `usethis list` command. You should run the test suite (via CI if you like) and address any failing tests.
167+
- Add your `Tool` subclass instance to the `OTHER_TOOLS` list in `usethis._tool.impl.base.pyproject_toml`. This list tracks all tools other than `pyproject.toml` itself, and is used by `PyprojectTOMLTool` to detect active configuration. A corresponding test `test_in_sync_with_all_tools` will fail if this step is missed.
168+
169+
#### Update tests
170+
171+
- Some tests may need updating as a result of new tool registration. In particular:
172+
- `TestGetUsageTable` tests in `tests/usethis/_core/test_list.py` — these enumerate all tools and their statuses. Add a `UsageRow` for your new tool.
168173

169174
#### Update the README and documentation
170175

README.md

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -75,13 +75,15 @@ Additionally, the command line reference documentation can be viewed with `useth
7575
- [`usethis lint`](https://usethis.readthedocs.io/en/stable/cli/reference#usethis-lint) — Add/Configure recommended linters (namely, [Ruff](https://docs.astral.sh/ruff/linter) and [deptry](https://github.com/fpgmaas/deptry)).
7676
- [`usethis spellcheck`](https://usethis.readthedocs.io/en/stable/cli/reference#usethis-spellcheck) — Add/Configure recommended spellcheckers (namely, [codespell](https://github.com/codespell-project/codespell)).
7777
- [`usethis test`](https://usethis.readthedocs.io/en/stable/cli/reference#usethis-test) — Add/Configure a recommended testing framework (namely, [pytest](https://github.com/pytest-dev/pytest) with [Coverage.py](https://github.com/nedbat/coveragepy)).
78+
- [`usethis typecheck`](https://usethis.readthedocs.io/en/stable/cli/reference#usethis-typecheck) — Add/Configure a recommended type checker (namely, [ty](https://docs.astral.sh/ty/)).
7879
- [`usethis tool`](https://usethis.readthedocs.io/en/stable/cli/reference#usethis-tool) — Add/Configure specific tools individually.
7980
- [`usethis tool codespell`](https://usethis.readthedocs.io/en/stable/cli/reference#code-quality-tools) - Use the [codespell spellchecker](https://github.com/codespell-project/codespell): detect common spelling mistakes.
8081
- [`usethis tool deptry`](https://usethis.readthedocs.io/en/stable/cli/reference#code-quality-tools) - Use the [deptry linter](https://github.com/fpgmaas/deptry): avoid missing or superfluous dependency declarations.
8182
- [`usethis tool import-linter`](https://usethis.readthedocs.io/en/stable/cli/reference#code-quality-tools) - Use [Import Linter](https://import-linter.readthedocs.io/en/stable/): enforce a self-imposed architecture on imports.
8283
- [`usethis tool pre-commit`](https://usethis.readthedocs.io/en/stable/cli/reference#code-quality-tools) - Use the [pre-commit](https://github.com/pre-commit/pre-commit) framework to manage and maintain Git hooks. Note that this will also install all the hooks to Git.
8384
- [`usethis tool pyproject-fmt`](https://usethis.readthedocs.io/en/stable/cli/reference#code-quality-tools) - Use the [pyproject-fmt formatter](https://github.com/tox-dev/toml-fmt/tree/main/pyproject-fmt): opinionated formatting of 'pyproject.toml' files.
8485
- [`usethis tool ruff`](https://usethis.readthedocs.io/en/stable/cli/reference#code-quality-tools) - Use [Ruff](https://github.com/astral-sh/ruff): an extremely fast Python linter and code formatter.
86+
- [`usethis tool ty`](https://usethis.readthedocs.io/en/stable/cli/reference#code-quality-tools) - Use [ty](https://docs.astral.sh/ty/): an extremely fast Python type checker.
8587
- [`usethis tool coverage.py`](https://usethis.readthedocs.io/en/stable/cli/reference#testing) - Use [Coverage.py](https://github.com/nedbat/coveragepy): a code coverage measurement tool.
8688
- [`usethis tool pytest`](https://usethis.readthedocs.io/en/stable/cli/reference#testing) - Use the [pytest](https://github.com/pytest-dev/pytest) testing framework.
8789
- [`usethis tool mkdocs`](https://usethis.readthedocs.io/en/stable/cli/reference#documentation) - Use [MkDocs](https://www.mkdocs.org/): Generate project documentation sites with Markdown.
@@ -173,13 +175,7 @@ If you're not interested in templating automations, then [configurator](https://
173175
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
174176
[![Socket](https://badge.socket.dev/pypi/package/usethis)](https://socket.dev/pypi/package/usethis/overview)
175177

176-
### Roadmap
177-
178-
Major features planned are:
179-
180-
- Support for a typechecker (likely ty, [#838](https://github.com/usethis-python/usethis-python/issues/838)).
181-
182-
Other features are tracked in the [GitHub Issues](https://github.com/usethis-python/usethis-python/issues) page.
178+
Feature requests are tracked in the [GitHub Issues](https://github.com/usethis-python/usethis-python/issues) page.
183179

184180
### Contributing
185181

docs/cli/overview.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,15 @@
1111
- [`usethis lint`](reference.md#usethis-lint) — Add/Configure recommended linters (namely, [Ruff](https://docs.astral.sh/ruff/linter) and [deptry](https://github.com/fpgmaas/deptry)).
1212
- [`usethis spellcheck`](reference.md#usethis-spellcheck) — Add/Configure recommended spellcheckers (namely, [codespell](https://github.com/codespell-project/codespell)).
1313
- [`usethis test`](reference.md#usethis-test) — Add/Configure a recommended testing framework (namely, [pytest](https://github.com/pytest-dev/pytest) with [Coverage.py](https://github.com/nedbat/coveragepy)).
14+
- [`usethis typecheck`](reference.md#usethis-typecheck) — Add/Configure a recommended type checker (namely, [ty](https://docs.astral.sh/ty/)).
1415
- [`usethis tool`](reference.md#usethis-tool) — Add/Configure specific tools individually.
1516
- [`usethis tool codespell`](reference.md#code-quality-tools) - Use the [codespell spellchecker](https://github.com/codespell-project/codespell): detect common spelling mistakes.
1617
- [`usethis tool deptry`](reference.md#code-quality-tools) - Use the [deptry linter](https://github.com/fpgmaas/deptry): avoid missing or superfluous dependency declarations.
1718
- [`usethis tool import-linter`](reference.md#code-quality-tools) - Use [Import Linter](https://import-linter.readthedocs.io/en/stable/): enforce a self-imposed architecture on imports.
1819
- [`usethis tool pre-commit`](reference.md#code-quality-tools) - Use the [pre-commit](https://github.com/pre-commit/pre-commit) framework to manage and maintain Git hooks. Note that this will also install all the hooks to Git.
1920
- [`usethis tool pyproject-fmt`](reference.md#code-quality-tools) - Use the [pyproject-fmt formatter](https://github.com/tox-dev/toml-fmt/tree/main/pyproject-fmt): opinionated formatting of 'pyproject.toml' files.
2021
- [`usethis tool ruff`](reference.md#code-quality-tools) - Use [Ruff](https://github.com/astral-sh/ruff): an extremely fast Python linter and code formatter.
22+
- [`usethis tool ty`](reference.md#code-quality-tools) - Use [ty](https://docs.astral.sh/ty/): an extremely fast Python type checker.
2123
- [`usethis tool coverage.py`](reference.md#testing) - Use [Coverage.py](https://github.com/nedbat/coveragepy): a code coverage measurement tool.
2224
- [`usethis tool pytest`](reference.md#testing) - Use the [pytest](https://github.com/pytest-dev/pytest) testing framework.
2325
- [`usethis tool mkdocs`](reference.md#documentation) - Use [MkDocs](https://www.mkdocs.org/): Generate project documentation sites with Markdown.

docs/cli/reference.md

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
Initialize a new Python project with recommended defaults, including:
66

77
- a `pyproject.toml` file and relevant configuration,
8-
- recommended linters, formatters, spellcheckers, and test frameworks (all opt-out),
8+
- recommended linters, formatters, spellcheckers, type checkers, and test frameworks (all opt-out),
99
- docstring style enforcement (opt-in),
1010
- the pre-commit framework (opt-in),
1111
- CI services (opt-in),
@@ -19,6 +19,7 @@ Supported options:
1919
- `--lint` to add recommended linters (default; or `--no-lint` to opt-out)
2020
- `--spellcheck` to add a recommended spellchecker (default; or `--no-spellcheck` to opt-out)
2121
- `--test` to add a recommended testing framework (default; or `--no-test` to opt-out)
22+
- `--typecheck` to add a recommended type checker (default; or `--no-typecheck` to opt-out)
2223
- `--pre-commit` to add the pre-commit framework for git hooks (but the default is `--no-pre-commit`)
2324
- `--ci` to add a CI service configuration
2425

@@ -172,6 +173,32 @@ Possible values:
172173

173174
See [`usethis tool`](#usethis-tool) for more information.
174175

176+
## `usethis typecheck`
177+
178+
Add a recommended type checker to the project (namely, [ty](https://docs.astral.sh/ty/)), including:
179+
180+
- declared & installed dependencies with `uv add`,
181+
- relevant configuration, and
182+
- any other relevant directories or tool-bespoke configuration files.
183+
184+
Note if `pyproject.toml` is not present, it will be created, since this is required for declaring dependencies with `uv add`.
185+
186+
Supported options:
187+
188+
- `--remove` to remove the tool instead of adding it
189+
- `--how` to only print how to use the tool, with no other side effects
190+
- `--offline` to disable network access and rely on caches
191+
- `--frozen` to leave the virtual environment and lockfile unchanged
192+
- `--quiet` to suppress output
193+
- `--backend` to specify a package manager backend to use. The default is to auto-detect.
194+
195+
Possible values:
196+
- `auto` to auto-detect the backend (default)
197+
- `uv` to use the [uv](https://docs.astral.sh/uv) package manager
198+
- `none` to not use a package manager backend and display messages for some operations.
199+
200+
See [`usethis tool`](#usethis-tool) for more information.
201+
175202
## `usethis tool`
176203

177204
Add a new tool to a Python project, including:
@@ -192,6 +219,7 @@ declaring dependencies with `uv add`.
192219
- `usethis tool pre-commit` - Use the [pre-commit](https://github.com/pre-commit/pre-commit) framework to manage and maintain Git hooks. Note that this will also install all the hooks to Git.
193220
- `usethis tool pyproject-fmt` - Use the [pyproject-fmt formatter](https://github.com/tox-dev/toml-fmt/tree/main/pyproject-fmt): opinionated formatting of 'pyproject.toml' files.
194221
- `usethis tool ruff` - Use [Ruff](https://github.com/astral-sh/ruff): an extremely fast Python linter and code formatter.
222+
- `usethis tool ty` - Use [ty](https://docs.astral.sh/ty/): an extremely fast Python type checker.
195223

196224
### Testing
197225

src/usethis/_backend/uv/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from usethis._backend.uv.call import call_uv_subprocess
44
from usethis._backend.uv.errors import UVSubprocessFailedError
55

6-
FALLBACK_UV_VERSION = "0.10.8"
6+
FALLBACK_UV_VERSION = "0.10.12"
77

88

99
def get_uv_version() -> str:

src/usethis/_config_file.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,15 @@ def files_manager() -> Iterator[None]:
2727
DotCoverageRCManager(),
2828
DotCoverageRCTOMLManager(),
2929
DotRuffTOMLManager(),
30+
DotTyTOMLManager(),
3031
DotPytestINIManager(),
3132
DotImportLinterManager(),
3233
MkDocsYMLManager(),
3334
PreCommitConfigYAMLManager(),
3435
PytestINIManager(),
3536
RuffTOMLManager(),
3637
ToxINIManager(),
38+
TyTOMLManager(),
3739
UVTOMLManager(),
3840
):
3941
yield
@@ -117,3 +119,19 @@ class ToxINIManager(INIFileManager):
117119
@property
118120
def relative_path(self) -> Path:
119121
return Path("tox.ini")
122+
123+
124+
class DotTyTOMLManager(TOMLFileManager):
125+
"""Class to manage the .ty.toml file."""
126+
127+
@property
128+
def relative_path(self) -> Path:
129+
return Path(".ty.toml")
130+
131+
132+
class TyTOMLManager(TOMLFileManager):
133+
"""Class to manage the ty.toml file."""
134+
135+
@property
136+
def relative_path(self) -> Path:
137+
return Path("ty.toml")

src/usethis/_core/tool.py

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
from usethis._tool.impl.base.pytest import PytestTool
3636
from usethis._tool.impl.base.requirements_txt import RequirementsTxtTool
3737
from usethis._tool.impl.base.ruff import RuffTool
38+
from usethis._tool.impl.base.ty import TyTool
3839
from usethis._tool.rule import RuleConfig
3940
from usethis._types.backend import BackendEnum
4041

@@ -513,7 +514,31 @@ def _get_basic_rule_config() -> RuleConfig:
513514
return rule_config
514515

515516

516-
def use_tool(
517+
def use_ty(*, remove: bool = False, how: bool = False) -> None:
518+
tool = TyTool()
519+
520+
if how:
521+
tool.print_how_to_use()
522+
return
523+
524+
if not remove:
525+
ensure_dep_declaration_file()
526+
527+
tool.add_dev_deps()
528+
tool.update_bitbucket_steps()
529+
tool.add_pre_commit_config()
530+
531+
tool.add_configs()
532+
tool.print_how_to_use()
533+
else:
534+
tool.remove_bitbucket_steps()
535+
tool.remove_configs()
536+
tool.remove_pre_commit_repo_configs()
537+
tool.remove_dev_deps()
538+
tool.remove_managed_files()
539+
540+
541+
def use_tool( # noqa: PLR0912
517542
tool: SupportedToolType,
518543
*,
519544
remove: bool = False,
@@ -553,6 +578,8 @@ def use_tool(
553578
use_requirements_txt(remove=remove, how=how)
554579
elif isinstance(tool, RuffTool):
555580
use_ruff(remove=remove, how=how)
581+
elif isinstance(tool, TyTool):
582+
use_ty(remove=remove, how=how)
556583
else:
557584
# Having the assert_never here is effectively a way of testing cases are
558585
# exhaustively handled, which ensures it is kept up to date with ALL_TOOLS,

src/usethis/_integrations/pre_commit/hooks.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"ruff", # Alias used for ruff-check
2323
"ruff-check", # ruff-check followed by ruff-format seems to be the recommended way by Astral
2424
"ruff-format",
25+
"ty",
2526
"deptry",
2627
"lint_imports", # Alias used for import-linter used in the Import Linter docs, see https://github.com/usethis-python/usethis-python/issues/1022
2728
"import-linter",

src/usethis/_tool/all_.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from usethis._tool.impl.base.pytest import PytestTool
1414
from usethis._tool.impl.base.requirements_txt import RequirementsTxtTool
1515
from usethis._tool.impl.base.ruff import RuffTool
16+
from usethis._tool.impl.base.ty import TyTool
1617

1718
SupportedToolType: TypeAlias = (
1819
CodespellTool
@@ -26,6 +27,7 @@
2627
| PytestTool
2728
| RequirementsTxtTool
2829
| RuffTool
30+
| TyTool
2931
)
3032

3133
ALL_TOOLS: list[SupportedToolType] = [
@@ -41,4 +43,5 @@
4143
PytestTool(),
4244
RequirementsTxtTool(),
4345
RuffTool(),
46+
TyTool(),
4447
]

0 commit comments

Comments
 (0)