Compare commits

..

22 Commits

Author SHA1 Message Date
David Peter a0b2d91932 Update 2025-12-15 14:09:08 +01:00
David Peter 6d86e85ab5 More updates 2025-12-15 13:58:45 +01:00
David Peter 4769721baa Up 2025-12-15 13:50:22 +01:00
David Peter 1026a03306 More updates 2025-12-15 13:45:55 +01:00
David Peter 54b62c5ec7 Updates 2025-12-15 13:39:58 +01:00
David Peter 80e1ff294d Clean up links 2025-12-15 13:32:57 +01:00
David Peter 9e89c7a9ef Add test links 2025-12-15 13:28:11 +01:00
David Peter ab4ac358e7 Convert to GitHub format 2025-12-15 13:13:50 +01:00
David Peter 311b0880bf Review findings 2025-12-15 12:00:22 +01:00
David Peter a2692af074 Cleanup 2025-12-15 10:30:10 +01:00
David Peter 91e0f54dc0 Restructure 2025-12-15 10:23:14 +01:00
David Peter beb5a1fee9 Add module resolution section 2025-12-15 10:16:33 +01:00
David Peter 606a45d26c Control flow section 2025-12-15 10:12:16 +01:00
David Peter bb96d86249 Add literals section 2025-12-15 10:02:42 +01:00
David Peter 208984e181 Tuple section 2025-12-15 09:58:43 +01:00
David Peter 7e96b365e7 Constructors section 2025-12-15 09:56:02 +01:00
David Peter cd1b251bc3 Updates 2025-12-15 09:46:45 +01:00
David Peter f5d67c3682 Updates 2025-12-15 09:34:17 +01:00
David Peter 9a41e102c0 More sections 2025-12-13 11:37:45 +01:00
David Peter bcc9e1d05c Generics 2025-12-13 11:30:48 +01:00
David Peter 41fc2b79c0 Added two more sections 2025-12-13 11:27:33 +01:00
David Peter 6dc83fb2b2 Initial section 2025-12-13 11:22:39 +01:00
47 changed files with 1363 additions and 3207 deletions

View File

@ -57,9 +57,9 @@ jobs:
env:
TAG: ${{ inputs.plan != '' && fromJson(inputs.plan).announcement_tag || 'dry-run' }}
run: |
version=$(grep -m 1 "^version = " pyproject.toml | sed -e 's/version = "\(.*\)"/\1/g')
version=$(grep -m 1 "^version = " dist-workspace.toml | sed -e 's/version = "\(.*\)"/\1/g')
if [ "${TAG}" != "${version}" ]; then
echo "The input tag does not match the version from pyproject.toml:" >&2
echo "The input tag does not match the version from dist-workspace.toml:" >&2
echo "${TAG}" >&2
echo "${version}" >&2
exit 1
@ -135,6 +135,7 @@ jobs:
# Order is on purpose such that the label org.opencontainers.image.version has the first pattern with the full version
tags: |
type=pep440,pattern={{ version }},value=${{ fromJson(inputs.plan).announcement_tag }}
type=raw,value=${{ fromJson(inputs.plan).announcement_tag }}
type=pep440,pattern={{ major }}.{{ minor }},value=${{ fromJson(inputs.plan).announcement_tag }}
- uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
@ -169,9 +170,9 @@ jobs:
# Mapping of base image followed by a comma followed by one or more base tags (comma separated)
# Note, org.opencontainers.image.version label will use the first base tag (use the most specific tag first)
image-mapping:
- alpine:3.23,alpine3.23,alpine
- debian:trixie-slim,trixie-slim,debian-slim
- buildpack-deps:trixie,trixie,debian
- alpine:3.21,alpine3.21,alpine
- debian:bookworm-slim,bookworm-slim,debian-slim
- buildpack-deps:bookworm,bookworm,debian
steps:
- uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
@ -194,7 +195,7 @@ jobs:
# Generate Dockerfile content
cat <<EOF > Dockerfile
FROM ${BASE_IMAGE}
COPY --from=${TY_BASE_IMG}:latest /ty /usr/local/bin/ty
COPY --from=${TY_BASE_IMG}:${TAG_VALUE} /ty /usr/local/bin/ty
ENTRYPOINT []
CMD ["/usr/local/bin/ty"]
EOF
@ -280,6 +281,7 @@ jobs:
# Order is on purpose such that the label org.opencontainers.image.version has the first pattern with the full version
tags: |
type=pep440,pattern={{ version }},value=${{ fromJson(inputs.plan).announcement_tag }}
type=raw,value=${{ fromJson(inputs.plan).announcement_tag }}
type=pep440,pattern={{ major }}.{{ minor }},value=${{ fromJson(inputs.plan).announcement_tag }}
- uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0

View File

@ -88,4 +88,4 @@ repos:
# actionlint has a shellcheck integration which extracts shell scripts in `run:` steps from GitHub Actions
# and checks these with shellcheck. This is arguably its most useful feature,
# but the integration only works if shellcheck is installed
- "github.com/wasilibs/go-shellcheck/cmd/shellcheck@v0.11.1"
- "github.com/wasilibs/go-shellcheck/cmd/shellcheck@v0.10.0"

View File

@ -1,464 +0,0 @@
# Benchmarks
All benchmarks were computed on macOS (Apple M4 Pro 14, 48 GB) with the following tool versions:
- [Pyrefly](https://pypi.org/project/pyrefly/) 0.45.2
- [Pyright](https://www.npmjs.com/package/pyright) 1.1.407
- [mypy](https://pypi.org/project/mypy/) \<=1.19.0
- [ty](https://pypi.org/project/ty/) 0.0.2
Benchmark performance may vary across operating systems, and from project to project. This document
includes benchmarks from a variety of projects to provide a representative example of real-world
usage: [Black](https://github.com/psf/black), [discord.py](https://github.com/Rapptz/discord.py),
[Home Assistant](https://github.com/home-assistant/core), [isort](https://github.com/pycqa/isort),
[Jinja](https://github.com/pallets/jinja), [pandas](https://github.com/pandas-dev/pandas),
[pandas-stubs](https://github.com/pandas-dev/pandas-stubs),
[Prefect](https://github.com/PrefectHQ/prefect), and [PyTorch](https://github.com/pytorch/pytorch).
For instructions on running the benchmarks, see
[`ty_benchmark/README.md`](https://github.com/astral-sh/ruff/blob/7f7485d608d2da19a0632a1238f2d4be551f612f/scripts/ty_benchmark/README.md).
## CLI
```text
black
-----
Benchmark 1: ty
Time (mean ± σ): 53.8 ms ± 1.6 ms [User: 344.9 ms, System: 36.3 ms]
Range (min … max): 51.4 ms … 57.9 ms 49 runs
Warning: Ignoring non-zero exit code.
Benchmark 2: Pyrefly
Time (mean ± σ): 167.4 ms ± 5.2 ms [User: 648.8 ms, System: 157.8 ms]
Range (min … max): 159.3 ms … 177.0 ms 18 runs
Warning: Ignoring non-zero exit code.
Benchmark 3: mypy
Time (mean ± σ): 1.197 s ± 0.008 s [User: 1.144 s, System: 0.051 s]
Range (min … max): 1.186 s … 1.212 s 10 runs
Benchmark 4: Pyright
Time (mean ± σ): 1.193 s ± 0.020 s [User: 13.264 s, System: 0.808 s]
Range (min … max): 1.173 s … 1.240 s 10 runs
Warning: Ignoring non-zero exit code.
Summary
ty ran
3.11 ± 0.13 times faster than Pyrefly
22.16 ± 0.74 times faster than Pyright
22.25 ± 0.66 times faster than mypy
-------------------------------------------------------------------------------
discord.py
----------
Benchmark 1: ty
Time (mean ± σ): 272.3 ms ± 1.4 ms [User: 1436.3 ms, System: 99.3 ms]
Range (min … max): 270.5 ms … 275.6 ms 10 runs
Warning: Ignoring non-zero exit code.
Benchmark 2: Pyrefly
Time (mean ± σ): 312.7 ms ± 23.9 ms [User: 2585.5 ms, System: 244.1 ms]
Range (min … max): 283.4 ms … 367.9 ms 10 runs
Warning: Ignoring non-zero exit code.
Benchmark 3: mypy
Time (mean ± σ): 6.617 s ± 0.212 s [User: 6.521 s, System: 0.091 s]
Range (min … max): 6.233 s … 6.852 s 10 runs
Warning: Ignoring non-zero exit code.
Benchmark 4: Pyright
Time (mean ± σ): 2.874 s ± 0.078 s [User: 35.269 s, System: 1.710 s]
Range (min … max): 2.753 s … 2.964 s 10 runs
Warning: Ignoring non-zero exit code.
Summary
ty ran
1.15 ± 0.09 times faster than Pyrefly
10.55 ± 0.29 times faster than Pyright
24.30 ± 0.79 times faster than mypy
-------------------------------------------------------------------------------
homeassistant
-------------
Benchmark 1: ty
Time (mean ± σ): 2.186 s ± 0.083 s [User: 23.139 s, System: 2.920 s]
Range (min … max): 2.067 s … 2.355 s 10 runs
Warning: Ignoring non-zero exit code.
Benchmark 2: Pyrefly
Time (mean ± σ): 5.320 s ± 0.020 s [User: 25.054 s, System: 33.545 s]
Range (min … max): 5.294 s … 5.365 s 10 runs
Warning: Ignoring non-zero exit code.
Benchmark 3: mypy
Time (mean ± σ): 45.662 s ± 0.224 s [User: 43.882 s, System: 1.767 s]
Range (min … max): 45.328 s … 46.009 s 10 runs
Warning: Ignoring non-zero exit code.
Benchmark 4: Pyright
Time (mean ± σ): 19.623 s ± 0.425 s [User: 227.040 s, System: 21.942 s]
Range (min … max): 19.255 s … 20.748 s 10 runs
Warning: Ignoring non-zero exit code.
Summary
ty ran
2.43 ± 0.09 times faster than Pyrefly
8.98 ± 0.39 times faster than Pyright
20.89 ± 0.80 times faster than mypy
-------------------------------------------------------------------------------
isort
-----
Benchmark 1: ty
Time (mean ± σ): 39.0 ms ± 1.1 ms [User: 161.0 ms, System: 21.0 ms]
Range (min … max): 36.2 ms … 41.2 ms 67 runs
Warning: Ignoring non-zero exit code.
Benchmark 2: Pyrefly
Time (mean ± σ): 138.5 ms ± 2.8 ms [User: 462.0 ms, System: 82.2 ms]
Range (min … max): 132.2 ms … 143.8 ms 21 runs
Warning: Ignoring non-zero exit code.
Benchmark 3: mypy
Time (mean ± σ): 581.2 ms ± 2.2 ms [User: 547.8 ms, System: 31.2 ms]
Range (min … max): 578.4 ms … 584.9 ms 10 runs
Benchmark 4: Pyright
Time (mean ± σ): 2.453 s ± 0.032 s [User: 13.608 s, System: 0.743 s]
Range (min … max): 2.402 s … 2.504 s 10 runs
Warning: Ignoring non-zero exit code.
Summary
ty ran
3.55 ± 0.13 times faster than Pyrefly
14.91 ± 0.44 times faster than mypy
62.90 ± 2.02 times faster than Pyright
-------------------------------------------------------------------------------
jinja
-----
Benchmark 1: ty
Time (mean ± σ): 110.2 ms ± 3.3 ms [User: 326.8 ms, System: 27.6 ms]
Range (min … max): 107.0 ms … 119.0 ms 26 runs
Warning: Ignoring non-zero exit code.
Benchmark 2: Pyrefly
Time (mean ± σ): 134.5 ms ± 1.7 ms [User: 444.8 ms, System: 87.5 ms]
Range (min … max): 131.5 ms … 137.8 ms 21 runs
Warning: Ignoring non-zero exit code.
Benchmark 3: mypy
Time (mean ± σ): 700.9 ms ± 13.2 ms [User: 665.5 ms, System: 33.0 ms]
Range (min … max): 693.7 ms … 737.7 ms 10 runs
Warning: Ignoring non-zero exit code.
Benchmark 4: Pyright
Time (mean ± σ): 1.099 s ± 0.014 s [User: 12.235 s, System: 0.736 s]
Range (min … max): 1.081 s … 1.127 s 10 runs
Warning: Ignoring non-zero exit code.
Summary
ty ran
1.22 ± 0.04 times faster than Pyrefly
6.36 ± 0.23 times faster than mypy
9.97 ± 0.33 times faster than Pyright
-------------------------------------------------------------------------------
pandas
------
Benchmark 1: ty
Time (mean ± σ): 551.5 ms ± 56.7 ms [User: 4906.6 ms, System: 222.6 ms]
Range (min … max): 467.6 ms … 614.8 ms 10 runs
Warning: Ignoring non-zero exit code.
Benchmark 2: Pyrefly
Time (mean ± σ): 1.174 s ± 0.012 s [User: 11.917 s, System: 1.035 s]
Range (min … max): 1.149 s … 1.186 s 10 runs
Warning: Ignoring non-zero exit code.
Benchmark 3: mypy
Time (mean ± σ): 21.366 s ± 0.083 s [User: 21.112 s, System: 0.247 s]
Range (min … max): 21.234 s … 21.539 s 10 runs
Benchmark 4: Pyright
Time (mean ± σ): 6.878 s ± 0.082 s [User: 80.281 s, System: 3.504 s]
Range (min … max): 6.749 s … 7.001 s 10 runs
Warning: Ignoring non-zero exit code.
Summary
ty ran
2.13 ± 0.22 times faster than Pyrefly
12.47 ± 1.29 times faster than Pyright
38.74 ± 3.99 times faster than mypy
-------------------------------------------------------------------------------
pandas-stubs
------------
Benchmark 1: ty
Time (mean ± σ): 83.2 ms ± 2.8 ms [User: 377.9 ms, System: 50.1 ms]
Range (min … max): 75.3 ms … 87.1 ms 36 runs
Warning: Ignoring non-zero exit code.
Benchmark 2: Pyrefly
Time (mean ± σ): 253.6 ms ± 6.0 ms [User: 853.5 ms, System: 322.0 ms]
Range (min … max): 245.2 ms … 264.2 ms 11 runs
Warning: Ignoring non-zero exit code.
Benchmark 3: mypy
Time (mean ± σ): 5.290 s ± 0.028 s [User: 5.150 s, System: 0.135 s]
Range (min … max): 5.248 s … 5.332 s 10 runs
Benchmark 4: Pyright
Time (mean ± σ): 1.792 s ± 0.030 s [User: 17.300 s, System: 1.199 s]
Range (min … max): 1.760 s … 1.843 s 10 runs
Summary
ty ran
3.05 ± 0.12 times faster than Pyrefly
21.55 ± 0.80 times faster than Pyright
63.61 ± 2.15 times faster than mypy
-------------------------------------------------------------------------------
prefect
-------
Benchmark 1: ty
Time (mean ± σ): 92.4 ms ± 1.1 ms [User: 524.8 ms, System: 70.1 ms]
Range (min … max): 90.8 ms … 95.1 ms 30 runs
Warning: Ignoring non-zero exit code.
Benchmark 2: Pyrefly
Time (mean ± σ): 322.3 ms ± 7.9 ms [User: 1061.7 ms, System: 691.8 ms]
Range (min … max): 305.0 ms … 330.5 ms 10 runs
Warning: Ignoring non-zero exit code.
Benchmark 3: mypy
Time (mean ± σ): 742.5 ms ± 3.4 ms [User: 702.0 ms, System: 38.1 ms]
Range (min … max): 737.6 ms … 749.0 ms 10 runs
Warning: Ignoring non-zero exit code.
Benchmark 4: Pyright
Time (mean ± σ): 3.545 s ± 0.042 s [User: 41.849 s, System: 2.252 s]
Range (min … max): 3.507 s … 3.641 s 10 runs
Warning: Ignoring non-zero exit code.
Summary
ty ran
3.49 ± 0.10 times faster than Pyrefly
8.03 ± 0.10 times faster than mypy
38.35 ± 0.64 times faster than Pyright
-------------------------------------------------------------------------------
pytorch
-------
Benchmark 1: ty
Time (mean ± σ): 1.160 s ± 0.115 s [User: 11.200 s, System: 1.344 s]
Range (min … max): 1.034 s … 1.314 s 10 runs
Warning: Ignoring non-zero exit code.
Benchmark 2: Pyrefly
Time (mean ± σ): 2.084 s ± 0.029 s [User: 19.660 s, System: 4.377 s]
Range (min … max): 2.051 s … 2.143 s 10 runs
Warning: Ignoring non-zero exit code.
Benchmark 3: mypy
Time (mean ± σ): 30.157 s ± 0.155 s [User: 29.776 s, System: 0.373 s]
Range (min … max): 29.956 s … 30.454 s 10 runs
Warning: Ignoring non-zero exit code.
Benchmark 4: Pyright
Time (mean ± σ): 12.770 s ± 0.294 s [User: 149.537 s, System: 8.990 s]
Range (min … max): 12.357 s … 13.175 s 10 runs
Warning: Ignoring non-zero exit code.
Summary
ty ran
1.80 ± 0.18 times faster than Pyrefly
11.01 ± 1.12 times faster than Pyright
26.01 ± 2.59 times faster than mypy
```
## LSP
### Incremental edit
```shell
----------------------------------------------------------------------------------------- benchmark 'black': 3 tests ----------------------------------------------------------------------------------------
Name (time in ms) Min Max Mean StdDev Median IQR Outliers OPS Rounds Iterations
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
test_incremental_edit[black-ty] 8.8965 (1.0) 9.4442 (1.0) 9.1480 (1.0) 0.1953 (1.0) 9.1324 (1.0) 0.3284 (1.0) 4;0 109.3131 (1.0) 10 1
test_incremental_edit[black-pyrefly] 181.7555 (20.43) 192.5020 (20.38) 186.0771 (20.34) 4.5209 (23.15) 183.9968 (20.15) 8.1744 (24.89) 2;0 5.3741 (0.05) 10 1
test_incremental_edit[black-pyright] 418.8096 (47.08) 436.1230 (46.18) 430.3303 (47.04) 5.7802 (29.60) 432.2938 (47.34) 7.9072 (24.08) 3;0 2.3238 (0.02) 10 1
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------- benchmark 'discord.py': 3 tests -----------------------------------------------------------------------------------------
Name (time in ms) Min Max Mean StdDev Median IQR Outliers OPS Rounds Iterations
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
test_incremental_edit[discord.py-ty] 11.0239 (1.0) 11.4890 (1.0) 11.2585 (1.0) 0.1475 (1.0) 11.3125 (1.0) 0.2244 (1.0) 4;0 88.8216 (1.0) 10 1
test_incremental_edit[discord.py-pyrefly] 404.7799 (36.72) 540.6511 (47.06) 480.9133 (42.72) 39.8237 (269.90) 486.0451 (42.97) 36.0575 (160.67) 3;1 2.0794 (0.02) 10 1
test_incremental_edit[discord.py-pyright] 438.0625 (39.74) 459.7234 (40.01) 454.7564 (40.39) 7.2835 (49.36) 458.2917 (40.51) 9.2910 (41.40) 2;0 2.1990 (0.02) 10 1
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------- benchmark 'homeassistant': 3 tests ---------------------------------------------------------------------------------------------
Name (time in ms) Min Max Mean StdDev Median IQR Outliers OPS Rounds Iterations
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
test_incremental_edit[homeassistant-ty] 26.2820 (1.0) 26.8146 (1.0) 26.5646 (1.0) 0.1786 (1.0) 26.5610 (1.0) 0.2392 (1.0) 4;0 37.6440 (1.0) 10 1
test_incremental_edit[homeassistant-pyright] 492.1233 (18.72) 513.8475 (19.16) 499.2279 (18.79) 6.6173 (37.05) 497.2621 (18.72) 6.0271 (25.20) 3;1 2.0031 (0.05) 10 1
test_incremental_edit[homeassistant-pyrefly] 1,858.6557 (70.72) 1,979.7762 (73.83) 1,923.3550 (72.40) 38.1201 (213.43) 1,917.0547 (72.18) 48.3089 (201.99) 4;0 0.5199 (0.01) 10 1
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------- benchmark 'isort': 3 tests ----------------------------------------------------------------------------------------
Name (time in ms) Min Max Mean StdDev Median IQR Outliers OPS Rounds Iterations
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
test_incremental_edit[isort-ty] 9.9467 (1.0) 10.3084 (1.0) 10.1385 (1.0) 0.1117 (1.0) 10.1680 (1.0) 0.1633 (1.0) 3;0 98.6339 (1.0) 10 1
test_incremental_edit[isort-pyrefly] 116.1576 (11.68) 128.3192 (12.45) 122.6576 (12.10) 3.7490 (33.56) 123.0442 (12.10) 5.8752 (35.97) 3;0 8.1528 (0.08) 10 1
test_incremental_edit[isort-pyright] 383.3340 (38.54) 400.4724 (38.85) 390.9956 (38.57) 5.0222 (44.95) 389.3690 (38.29) 6.7132 (41.10) 3;0 2.5576 (0.03) 10 1
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------- benchmark 'jinja': 3 tests ----------------------------------------------------------------------------------------
Name (time in ms) Min Max Mean StdDev Median IQR Outliers OPS Rounds Iterations
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
test_incremental_edit[jinja-ty] 43.7648 (1.0) 45.4928 (1.0) 44.3021 (1.0) 0.4960 (1.0) 44.2532 (1.0) 0.4335 (1.0) 2;1 22.5723 (1.0) 10 1
test_incremental_edit[jinja-pyrefly] 182.0870 (4.16) 194.4938 (4.28) 189.2674 (4.27) 4.0190 (8.10) 190.3916 (4.30) 2.8280 (6.52) 3;2 5.2835 (0.23) 10 1
test_incremental_edit[jinja-pyright] 424.4407 (9.70) 439.2709 (9.66) 432.3523 (9.76) 5.2093 (10.50) 432.5269 (9.77) 8.0710 (18.62) 4;0 2.3129 (0.10) 10 1
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------- benchmark 'pandas': 3 tests ----------------------------------------------------------------------------------------------
Name (time in ms) Min Max Mean StdDev Median IQR Outliers OPS Rounds Iterations
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
test_incremental_edit[pandas-ty] 69.6266 (1.0) 93.7763 (1.0) 81.3957 (1.0) 7.0073 (1.0) 81.2143 (1.0) 6.5060 (1.0) 3;0 12.2857 (1.0) 10 1
test_incremental_edit[pandas-pyright] 434.3018 (6.24) 540.0721 (5.76) 467.1337 (5.74) 34.8674 (4.98) 457.4263 (5.63) 46.5595 (7.16) 1;0 2.1407 (0.17) 10 1
test_incremental_edit[pandas-pyrefly] 3,756.2226 (53.95) 4,757.2635 (50.73) 4,377.4530 (53.78) 367.8468 (52.49) 4,486.5002 (55.24) 714.0047 (109.74) 5;0 0.2284 (0.02) 10 1
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------- benchmark 'prefect': 3 tests ----------------------------------------------------------------------------------------------
Name (time in ms) Min Max Mean StdDev Median IQR Outliers OPS Rounds Iterations
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
test_incremental_edit[prefect-ty] 4.7899 (1.0) 5.3654 (1.0) 5.0291 (1.0) 0.1827 (1.0) 4.9726 (1.0) 0.2836 (1.0) 3;0 198.8408 (1.0) 10 1
test_incremental_edit[prefect-pyright] 537.4210 (112.20) 555.0903 (103.46) 543.9572 (108.16) 5.3413 (29.24) 543.2359 (109.25) 7.0621 (24.90) 4;0 1.8384 (0.01) 10 1
test_incremental_edit[prefect-pyrefly] 2,486.7581 (519.17) 3,972.1852 (740.34) 3,280.6660 (652.33) 500.2204 (>1000.0) 3,231.6573 (649.90) 706.5563 (>1000.0) 3;0 0.3048 (0.00) 10 1
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------- benchmark 'pytorch': 3 tests ----------------------------------------------------------------------------------------------
Name (time in ms) Min Max Mean StdDev Median IQR Outliers OPS Rounds Iterations
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
test_incremental_edit[pytorch-ty] 4.3493 (1.0) 4.6291 (1.0) 4.4956 (1.0) 0.0940 (1.0) 4.4831 (1.0) 0.1323 (1.0) 4;0 222.4377 (1.0) 10 1
test_incremental_edit[pytorch-pyright] 367.6819 (84.54) 374.5961 (80.92) 370.4936 (82.41) 2.2878 (24.35) 370.5413 (82.65) 3.5865 (27.12) 2;0 2.6991 (0.01) 10 1
test_incremental_edit[pytorch-pyrefly] 2,333.3450 (536.48) 2,889.9276 (624.30) 2,604.7441 (579.39) 202.1562 (>1000.0) 2,582.8069 (576.12) 380.2684 (>1000.0) 4;0 0.3839 (0.00) 10 1
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
```
### Fetch diagnostics
```shell
----------------------------------------------------------------------------------------- benchmark 'black': 3 tests ----------------------------------------------------------------------------------------
Name (time in ms) Min Max Mean StdDev Median IQR Outliers OPS Rounds Iterations
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
test_fetch_diagnostics[black-ty] 40.5680 (1.0) 45.9828 (1.0) 43.4315 (1.0) 1.9415 (3.59) 43.4317 (1.0) 3.6550 (5.37) 5;0 23.0247 (1.0) 10 1
test_fetch_diagnostics[black-pyrefly] 131.4388 (3.24) 133.1042 (2.89) 132.3125 (3.05) 0.5407 (1.0) 132.2801 (3.05) 0.6808 (1.0) 3;0 7.5579 (0.33) 10 1
test_fetch_diagnostics[black-pyright] 234.5532 (5.78) 261.0507 (5.68) 241.2080 (5.55) 7.5489 (13.96) 238.8710 (5.50) 3.9942 (5.87) 1;1 4.1458 (0.18) 10 1
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------- benchmark 'discord.py': 3 tests -----------------------------------------------------------------------------------------
Name (time in ms) Min Max Mean StdDev Median IQR Outliers OPS Rounds Iterations
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
test_fetch_diagnostics[discord.py-ty] 88.1260 (1.0) 91.9354 (1.0) 89.9785 (1.0) 1.2617 (1.0) 89.8813 (1.0) 1.9953 (1.33) 3;0 11.1138 (1.0) 10 1
test_fetch_diagnostics[discord.py-pyrefly] 438.9406 (4.98) 462.2016 (5.03) 442.3538 (4.92) 7.0283 (5.57) 439.9846 (4.90) 1.4996 (1.0) 1;1 2.2606 (0.20) 10 1
test_fetch_diagnostics[discord.py-pyright] 488.1340 (5.54) 501.5540 (5.46) 493.6927 (5.49) 3.7678 (2.99) 493.7276 (5.49) 3.5742 (2.38) 3;1 2.0256 (0.18) 10 1
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------- benchmark 'homeassistant': 3 tests ----------------------------------------------------------------------------------------
Name (time in ms) Min Max Mean StdDev Median IQR Outliers OPS Rounds Iterations
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
test_fetch_diagnostics[homeassistant-ty] 109.6321 (1.0) 112.8913 (1.0) 111.4661 (1.0) 1.1174 (1.0) 111.4080 (1.0) 1.7967 (1.0) 5;0 8.9713 (1.0) 10 1
test_fetch_diagnostics[homeassistant-pyrefly] 218.1328 (1.99) 238.8827 (2.12) 222.4006 (2.00) 6.7033 (6.00) 219.6265 (1.97) 4.9113 (2.73) 2;1 4.4964 (0.50) 10 1
test_fetch_diagnostics[homeassistant-pyright] 888.3600 (8.10) 938.0845 (8.31) 901.1896 (8.08) 18.2062 (16.29) 893.4438 (8.02) 5.7174 (3.18) 2;2 1.1096 (0.12) 10 1
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------- benchmark 'isort': 3 tests ----------------------------------------------------------------------------------------
Name (time in ms) Min Max Mean StdDev Median IQR Outliers OPS Rounds Iterations
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
test_fetch_diagnostics[isort-ty] 41.8193 (1.0) 47.1411 (1.0) 43.6068 (1.0) 1.7622 (1.0) 43.1409 (1.0) 2.2658 (1.0) 3;0 22.9322 (1.0) 10 1
test_fetch_diagnostics[isort-pyrefly] 103.6808 (2.48) 110.2636 (2.34) 105.9967 (2.43) 2.6978 (1.53) 104.5978 (2.42) 5.5226 (2.44) 3;0 9.4343 (0.41) 10 1
test_fetch_diagnostics[isort-pyright] 297.8888 (7.12) 327.5334 (6.95) 306.2138 (7.02) 8.7235 (4.95) 304.5766 (7.06) 6.0185 (2.66) 1;1 3.2657 (0.14) 10 1
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------- benchmark 'jinja': 3 tests ----------------------------------------------------------------------------------------
Name (time in ms) Min Max Mean StdDev Median IQR Outliers OPS Rounds Iterations
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
test_fetch_diagnostics[jinja-ty] 114.6546 (1.0) 129.8110 (1.0) 120.6856 (1.0) 5.6731 (3.75) 119.8813 (1.0) 9.1737 (7.27) 3;0 8.2860 (1.0) 10 1
test_fetch_diagnostics[jinja-pyrefly] 134.1455 (1.17) 139.0428 (1.07) 136.2655 (1.13) 1.5126 (1.0) 135.7366 (1.13) 1.2612 (1.0) 3;1 7.3386 (0.89) 10 1
test_fetch_diagnostics[jinja-pyright] 280.1174 (2.44) 305.6963 (2.35) 287.5077 (2.38) 8.9505 (5.92) 283.8312 (2.37) 10.0400 (7.96) 2;0 3.4782 (0.42) 10 1
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------- benchmark 'pandas': 3 tests ----------------------------------------------------------------------------------------
Name (time in ms) Min Max Mean StdDev Median IQR Outliers OPS Rounds Iterations
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
test_fetch_diagnostics[pandas-ty] 289.0480 (1.0) 294.6924 (1.0) 292.1341 (1.0) 1.6226 (1.0) 292.2783 (1.0) 2.4183 (2.01) 2;0 3.4231 (1.0) 10 1
test_fetch_diagnostics[pandas-pyrefly] 522.8750 (1.81) 529.1068 (1.80) 524.6167 (1.80) 1.9387 (1.19) 524.1335 (1.79) 1.2023 (1.0) 2;2 1.9062 (0.56) 10 1
test_fetch_diagnostics[pandas-pyright] 928.4370 (3.21) 949.3941 (3.22) 941.8812 (3.22) 5.6550 (3.49) 943.2703 (3.23) 4.2351 (3.52) 2;1 1.0617 (0.31) 10 1
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------- benchmark 'prefect': 3 tests ----------------------------------------------------------------------------------------
Name (time in ms) Min Max Mean StdDev Median IQR Outliers OPS Rounds Iterations
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
test_fetch_diagnostics[prefect-ty] 123.5941 (1.0) 127.0129 (1.0) 125.3534 (1.0) 1.0498 (1.02) 125.1861 (1.0) 1.4461 (1.10) 3;0 7.9774 (1.0) 10 1
test_fetch_diagnostics[prefect-pyrefly] 437.5048 (3.54) 441.0088 (3.47) 438.7041 (3.50) 1.0287 (1.0) 438.4152 (3.50) 1.3126 (1.0) 2;0 2.2794 (0.29) 10 1
test_fetch_diagnostics[prefect-pyright] 828.5065 (6.70) 884.9894 (6.97) 845.3657 (6.74) 14.9587 (14.54) 842.5912 (6.73) 8.1088 (6.18) 2;1 1.1829 (0.15) 10 1
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------- benchmark 'pytorch': 3 tests -----------------------------------------------------------------------------------------
Name (time in ms) Min Max Mean StdDev Median IQR Outliers OPS Rounds Iterations
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
test_fetch_diagnostics[pytorch-ty] 51.7146 (1.0) 59.2463 (1.0) 54.3685 (1.0) 2.2254 (2.06) 54.3844 (1.0) 3.0549 (2.12) 2;0 18.3930 (1.0) 10 1
test_fetch_diagnostics[pytorch-pyrefly] 174.7057 (3.38) 178.1138 (3.01) 175.7364 (3.23) 1.0824 (1.0) 175.5052 (3.23) 1.4398 (1.0) 1;0 5.6903 (0.31) 10 1
test_fetch_diagnostics[pytorch-pyright] 447.4101 (8.65) 474.9993 (8.02) 460.5399 (8.47) 9.8641 (9.11) 461.9636 (8.49) 18.7404 (13.02) 3;0 2.1714 (0.12) 10 1
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
```

View File

@ -1,289 +1,5 @@
# Changelog
## 0.0.8
Released on 2025-12-29.
### Breaking changes
- Rename `non-subscriptable` rule to `not-subscriptable` ([#22193](https://github.com/astral-sh/ruff/pull/22193))
### Core type checking
- Promote float and complex when promoting literals ([#22215](https://github.com/astral-sh/ruff/pull/22215))
- Callable type of a type object is not function-like ([#22226](https://github.com/astral-sh/ruff/pull/22226))
- Fix and simplify callable type materializations ([#22213](https://github.com/astral-sh/ruff/pull/22213))
### LSP server
- Add option to disable syntax errors ([#22217](https://github.com/astral-sh/ruff/pull/22217))
- Fix completion in decorators with missing declaration ([#22177](https://github.com/astral-sh/ruff/pull/22177))
- Better completions context detection when typing in decorator positions ([#22224](https://github.com/astral-sh/ruff/pull/22224))
- Limit the returned completions to reduce lag ([#22240](https://github.com/astral-sh/ruff/pull/22240))
### Diagnostics
- Improve wording of `unsupported-base` sub-diagnostic ([#22194](https://github.com/astral-sh/ruff/pull/22194))
- Preserve the invalid assignment diagnostic message when implicitly shadowing a definition ([#22219](https://github.com/astral-sh/ruff/pull/22219))
### Other changes
- Update docker image to use alpine 3.23 and trixie ([#2217](https://github.com/astral-sh/ty/pull/2217))
### Contributors
- [@RasmusNygren](https://github.com/RasmusNygren)
- [@samypr100](https://github.com/samypr100)
- [@silamon](https://github.com/silamon)
- [@carljm](https://github.com/carljm)
- [@MichaReiser](https://github.com/MichaReiser)
- [@MatthewMckee4](https://github.com/MatthewMckee4)
## 0.0.7
Released on 2025-12-24.
### Bug fixes
- Fix classification of modules in `import x as y` for semantic syntax highlighting ([#22175](https://github.com/astral-sh/ruff/pull/22175))
- Fix module resolution on network drives ([#22173](https://github.com/astral-sh/ruff/pull/22173))
- Render the entire diagnostic message in all output formats ([#22164](https://github.com/astral-sh/ruff/pull/22164))
### Other changes
- Add a dedicated diagnostic for TypedDict deletions ([#22123](https://github.com/astral-sh/ruff/pull/22123))
- Check `__delitem__` instead of `__getitem__` for `del x[k]` ([#22121](https://github.com/astral-sh/ruff/pull/22121))
- Fix `@staticmethod` combined with other decorators incorrectly binding `self` ([#22128](https://github.com/astral-sh/ruff/pull/22128))
- Fix implementation of `Top[Callable[..., object]]` ([#22145](https://github.com/astral-sh/ruff/pull/22145))
- Improve diagnostic when `callable` is used in a type expression instead of `collections.abc.Callable` or `typing.Callable` ([#22180](https://github.com/astral-sh/ruff/pull/22180))
- Improve diagnostic when a user tries to access a function attribute on a `Callable` type ([#22182](https://github.com/astral-sh/ruff/pull/22182))
- Include the specialization of a generic `TypedDict` as part of its display ([#22174](https://github.com/astral-sh/ruff/pull/22174))
- Support tuple narrowing based on member checks ([#22167](https://github.com/astral-sh/ruff/pull/22167))
- Synthesize `__delitem__` for TypedDict to allow deleting non-required keys ([#22122](https://github.com/astral-sh/ruff/pull/22122))
### Contributors
- [@MichaReiser](https://github.com/MichaReiser)
- [@ntBre](https://github.com/ntBre)
- [@AlexWaygood](https://github.com/AlexWaygood)
- [@charliermarsh](https://github.com/charliermarsh)
## 0.0.6
Released on 2025-12-23.
### Bug fixes
- FIx panic from unexpanded type aliases in implicit tuple aliases ([#22015](https://github.com/astral-sh/ruff/pull/22015))
- Support `type[T]` where `T` is a type alias to a union of types ([#22115](https://github.com/astral-sh/ruff/pull/22115))
- Support `==` narrowing for tuples in unions with disjoint types ([#22129](https://github.com/astral-sh/ruff/pull/22129))
- Respect debug text interpolation in f-strings ([#22151](https://github.com/astral-sh/ruff/pull/22151))
- Fix panic from unstable union-type ordering in fixed-point iteration ([#22070](https://github.com/astral-sh/ruff/pull/22070))
### LSP server
- Add `ty.configuration` and `ty.configurationFile` options ([#22053](https://github.com/astral-sh/ruff/pull/22053))
- Add `diagnosticMode: off` to disable diagnostics while retaining Go To Definition, etc. ([#22073](https://github.com/astral-sh/ruff/pull/22073))
- Set flag to avoid `type[T@f]` being inserted when you double-click on the inlay ([#22139](https://github.com/astral-sh/ruff/pull/22139))
- Use Markdown for completions documentation if the LSP client supports it ([#21752](https://github.com/astral-sh/ruff/pull/21752))
### CLI
- Abort printing diagnostics when pressing `Ctrl+C` ([#22083](https://github.com/astral-sh/ruff/pull/22083))
### Configuration
- Add `respect-type-ignore-comments` configuration option ([#22137](https://github.com/astral-sh/ruff/pull/22137))
- Support custom builtins via `__builtins__.pyi` ([#22021](https://github.com/astral-sh/ruff/pull/22021))
### Other changes
- Bind self with instance in `__get__` ([#22155](https://github.com/astral-sh/ruff/pull/22155))
- Support type inference between protocol instances ([#22120](https://github.com/astral-sh/ruff/pull/22120))
- Synthesize a precise `_fields` attribute for NamedTuples ([#22163](https://github.com/astral-sh/ruff/pull/22163))
- Synthesize a precise `_replace` method for NamedTuples ([#22153](https://github.com/astral-sh/ruff/pull/22153))
- Narrow "tagged unions" of `TypedDict`s ([#22104](https://github.com/astral-sh/ruff/pull/22104))
### Contributors
- [@mtshiba](https://github.com/mtshiba)
- [@charliermarsh](https://github.com/charliermarsh)
- [@Wizzerinus](https://github.com/Wizzerinus)
- [@oconnor663](https://github.com/oconnor663)
- [@MichaReiser](https://github.com/MichaReiser)
- [@ibraheemdev](https://github.com/ibraheemdev)
- [@MatthewMckee4](https://github.com/MatthewMckee4)
## 0.0.5
Released on 2025-12-20.
### Bug fixes
- Fix debug-mode server panic when a user typed a class definition by ensuring class arguments are visited in source order for semantic tokens ([#22063](https://github.com/astral-sh/ruff/pull/22063))
### LSP server
- Classify docstrings in semantic tokens during syntax highlighting ([#22031](https://github.com/astral-sh/ruff/pull/22031))
### CLI
- Add `--force-exclude` option ([#22076](https://github.com/astral-sh/ruff/pull/22076))
- Only clear output between two successful checks ([#22078](https://github.com/astral-sh/ruff/pull/22078))
### Other changes
- Add support for `dict(...)` calls in `TypedDict` contexts ([#22113](https://github.com/astral-sh/ruff/pull/22113))
- Speedup bidirectional type-checking involving large unions by avoiding narrowing on non-generic calls ([#22102](https://github.com/astral-sh/ruff/pull/22102))
- Simplify inferred types by avoiding storing multi-inference attempts ([#22062](https://github.com/astral-sh/ruff/pull/22062), [#22103](https://github.com/astral-sh/ruff/pull/22103))
- Improve union builder performance ([#22048](https://github.com/astral-sh/ruff/pull/22048))
- Only prefer declared types in non-covariant positions ([#22068](https://github.com/astral-sh/ruff/pull/22068))
- Respect intersections in iterations ([#21965](https://github.com/astral-sh/ruff/pull/21965))
- Sync vendored typeshed stubs ([#22091](https://github.com/astral-sh/ruff/pull/22091)). [Typeshed diff](https://github.com/python/typeshed/compare/ef2b90c67e5c668b91b3ae121baf00ee5165c30b...3c2dbb1fde8e8d1d59b10161c8bf5fd06c0011cd)
- Understand that the type of `X` on an enum class will be `int` if `X` is defined using `enum.nonmember` in the class definition ([#22025](https://github.com/astral-sh/ruff/pull/22025))
### Contributors
- [@charliermarsh](https://github.com/charliermarsh)
- [@ibraheemdev](https://github.com/ibraheemdev)
- [@RasmusNygren](https://github.com/RasmusNygren)
- [@Hugo-Polloli](https://github.com/Hugo-Polloli)
- [@carljm](https://github.com/carljm)
- [@Gankra](https://github.com/Gankra)
- [@MichaReiser](https://github.com/MichaReiser)
## 0.0.4
Released on 2025-12-18.
### LSP server
- Add support for attribute docstrings ([#22036](https://github.com/astral-sh/ruff/pull/22036))
- Correctly encode multiline tokens for clients not supporting multiline tokens ([#22033](https://github.com/astral-sh/ruff/pull/22033))
- Autocompletions: Don't suggest keyword statements when only expressions are valid ([#22002](https://github.com/astral-sh/ruff/pull/22002))
- Fix goto-declaration on the right-hand side of `from module import submodule` ([#22042](https://github.com/astral-sh/ruff/pull/22042))
- Fix some configuration panics in the LSP ([#22040](https://github.com/astral-sh/ruff/pull/22040))
- Gracefully handle client requests that can't be deserialized ([#22051](https://github.com/astral-sh/ruff/pull/22051))
### Other changes
- Improve performance for large match statements ([#22045](https://github.com/astral-sh/ruff/pull/22045))
- Disable possibly-missing-imports by default ([#22041](https://github.com/astral-sh/ruff/pull/22041))
- Implement disjointness for TypedDicts, significantly speeding up checking of code that uses pydantic ([#22044](https://github.com/astral-sh/ruff/pull/22044))
### Contributors
- [@oconnor663](https://github.com/oconnor663)
- [@MichaReiser](https://github.com/MichaReiser)
- [@Gankra](https://github.com/Gankra)
- [@RasmusNygren](https://github.com/RasmusNygren)
- [@charliermarsh](https://github.com/charliermarsh)
## 0.0.3
Released on 2025-12-17.
### LSP server
- Improve rendering of signatures in hovers ([#22007](https://github.com/astral-sh/ruff/pull/22007))
### Core type checking
- Apply narrowing to `len` calls based on argument size ([#22026](https://github.com/astral-sh/ruff/pull/22026))
- Don't add identical lower/upper bounds multiple times when inferring specializations ([#22030](https://github.com/astral-sh/ruff/pull/22030))
- Improve `unsupported-base` and `invalid-super-argument` diagnostics to avoid extremely long lines when encountering verbose types ([#22022](https://github.com/astral-sh/ruff/pull/22022))
- Improve disambiguation of types in many cases ([#22019](https://github.com/astral-sh/ruff/pull/22019))
- Respect deferred values in keyword arguments etc. for `.pyi` files ([#22029](https://github.com/astral-sh/ruff/pull/22029))
- Handle field specifier functions that accept `**kwargs` and recognize metaclass-based transformers as instances of `DataclassInstance` ([#22018](https://github.com/astral-sh/ruff/pull/22018))
### Contributors
- [@charliermarsh](https://github.com/charliermarsh)
- [@sharkdp](https://github.com/sharkdp)
- [@Gankra](https://github.com/Gankra)
- [@zanieb](https://github.com/zanieb)
- [@AlexWaygood](https://github.com/AlexWaygood)
- [@dcreager](https://github.com/dcreager)
## 0.0.2
Released on 2025-12-16.
This is the first Beta release of ty, which we're now ready to recommend to motivated users for
production use. See our [blog post](https://astral.sh/blog/ty) for more details.
### LSP server
- Improve display of completions to show actual insertion text ([#21988](https://github.com/astral-sh/ruff/pull/21988))
- Improve highlighting of special type syntax in hovers ([#22005](https://github.com/astral-sh/ruff/pull/22005))
- Improve syntax highlighting of constants ([#22006](https://github.com/astral-sh/ruff/pull/22006))
### Core type checking
- Infer precise types for `isinstance(…)` calls involving type variables ([#21999](https://github.com/astral-sh/ruff/pull/21999))
- Infer `TypeVar` specializations for `Callable` types ([#21551](https://github.com/astral-sh/ruff/pull/21551))
- Propagate `classmethod`-ness through decorators returning `Callable`s ([#21958](https://github.com/astral-sh/ruff/pull/21958))
- Improve rendering of default values for function args ([#22010](https://github.com/astral-sh/ruff/pull/22010))
- Don't use implicit superclass annotation when converting a class constructor into a `Callable` ([#22011](https://github.com/astral-sh/ruff/pull/22011))
### Other
- Type checking performance improvement ([#22000](https://github.com/astral-sh/ruff/pull/22000))
### Contributors
- [@sharkdp](https://github.com/sharkdp)
- [@carljm](https://github.com/carljm)
- [@Gankra](https://github.com/Gankra)
- [@BurntSushi](https://github.com/BurntSushi)
- [@dcreager](https://github.com/dcreager)
- [@MichaReiser](https://github.com/MichaReiser)
## 0.0.1-alpha.35
Released on 2025-12-16.
### Bug fixes
- Fix panic for stringified comprehensions and boolean expressions in type expression ([#21967](https://github.com/astral-sh/ruff/pull/21967))
- Avoid stack overflow when determining inferable typevars ([#21971](https://github.com/astral-sh/ruff/pull/21971))
- Fix false-positive `invalid-method-override` diagnostic on method that uses `Callable` with a `ParamSpec` ([#21934](https://github.com/astral-sh/ruff/pull/21934))
- Disallow explicit specialization of type variables themselves ([#21938](https://github.com/astral-sh/ruff/pull/21938))
- Fix hover type on named expression ("walrus expression") targets ([#21952](https://github.com/astral-sh/ruff/pull/21952))
### LSP server
- Add *"qualify ..."* code fix for undefined references ([#21968](https://github.com/astral-sh/ruff/pull/21968))
- Add new goto-definition targets on inlay hints ([#21950](https://github.com/astral-sh/ruff/pull/21950))
- Remove invalid statement-keyword completions in `for`-statements ([#21979](https://github.com/astral-sh/ruff/pull/21979))
### Core type checking
- Add support for `__qualname__` and other implicit class attributes ([#21966](https://github.com/astral-sh/ruff/pull/21966))
- Emit a diagnostic when a frozen dataclass inherits a non-frozen dataclass and vice versa ([#21962](https://github.com/astral-sh/ruff/pull/21962))
- Emit a diagnostic when a type variable with a default is followed by one without a default ([#21787](https://github.com/astral-sh/ruff/pull/21787))
- Improve diagnostics for unsupported binary operations and unsupported augmented assignments ([#21947](https://github.com/astral-sh/ruff/pull/21947))
- Improve check enforcing that an overloaded function must have an implementation ([#21978](https://github.com/astral-sh/ruff/pull/21978))
- Use unqualified names for displays of `TypeAliasType`s and unbound `ParamSpec`s/`TypeVar`s ([#21960](https://github.com/astral-sh/ruff/pull/21960))
### Performance
- Speed up ty on Linux by using jemalloc ([#21975](https://github.com/astral-sh/ruff/pull/21975))
### Contributors
- [@11happy](https://github.com/11happy)
- [@dhruvmanila](https://github.com/dhruvmanila)
- [@AlexWaygood](https://github.com/AlexWaygood)
- [@mtshiba](https://github.com/mtshiba)
- [@MichaReiser](https://github.com/MichaReiser)
- [@Gankra](https://github.com/Gankra)
- [@silamon](https://github.com/silamon)
- [@dcreager](https://github.com/dcreager)
- [@charliermarsh](https://github.com/charliermarsh)
- [@RasmusNygren](https://github.com/RasmusNygren)
- [@carljm](https://github.com/carljm)
## 0.0.1-alpha.34
Released on 2025-12-12.

View File

@ -6,60 +6,51 @@
An extremely fast Python type checker and language server, written in Rust.
<br />
<p align="center">
<img alt="Shows a bar chart with benchmark results." width="500px" src="./docs/assets/ty-benchmark-cli.svg">
</p>
<p align="center">
<i>Type checking the <a href="https://github.com/home-assistant/core">home-assistant</a> project without caching.</i>
</p>
<br />
ty is backed by [Astral](https://astral.sh), the creators of
[uv](https://github.com/astral-sh/uv) and [Ruff](https://github.com/astral-sh/ruff).
## Highlights
- 10x - 100x faster than mypy and Pyright
- Comprehensive [diagnostics](https://docs.astral.sh/ty/features/diagnostics/) with rich contextual information
- Configurable [rule levels](https://docs.astral.sh/ty/rules/), [per-file overrides](https://docs.astral.sh/ty/reference/configuration/#overrides), [suppression comments](https://docs.astral.sh/ty/suppression/), and first-class project support
- Designed for adoption, with support for [redeclarations](https://docs.astral.sh/ty/features/type-system/#redeclarations) and [partially typed code](https://docs.astral.sh/ty/features/type-system/#gradual-guarantee)
- [Language server](https://docs.astral.sh/ty/features/language-server/) with code navigation, completions, code actions, auto-import, inlay hints, on-hover help, etc.
- Fine-grained [incremental analysis](https://docs.astral.sh/ty/features/language-server/#fine-grained-incrementality) designed for fast updates when editing files in an IDE
- Editor integrations for [VS Code](https://docs.astral.sh/ty/editors/#vs-code), [PyCharm](https://docs.astral.sh/ty/editors/#pycharm), [Neovim](https://docs.astral.sh/ty/editors/#neovim) and more
- Advanced typing features like first-class [intersection types](https://docs.astral.sh/ty/features/type-system/#intersection-types), advanced [type narrowing](https://docs.astral.sh/ty/features/type-system/#top-and-bottom-materializations), and
[sophisticated reachability analysis](https://docs.astral.sh/ty/features/type-system/#reachability-based-on-types)
## Getting started
Run ty with [uvx](https://docs.astral.sh/uv/guides/tools/#running-tools) to get started quickly:
Try out the [online playground](https://play.ty.dev), or run ty with
[uvx](https://docs.astral.sh/uv/guides/tools/#running-tools) to get started quickly:
```shell
uvx ty
```
For other ways to install ty, see the [installation](https://docs.astral.sh/ty/installation/) documentation.
If you do not provide a subcommand, ty will list available commands — for detailed information about
command-line options, see the [CLI reference](https://docs.astral.sh/ty/reference/cli/).
Use the `check` command to run the type checker:
```shell
uvx ty check
```
Or, check out the [ty playground](https://play.ty.dev) to try it out in your browser.
ty will run on all Python files in the working directory and or subdirectories. If used from a
project, ty will run on all Python files in the project (starting in the directory with the
`pyproject.toml`)
You can also provide specific paths to check:
```shell
uvx ty check example.py
```
When type checking, ty will find installed packages in the active virtual environment (via
`VIRTUAL_ENV`) or discover a virtual environment named `.venv` in the project root or working
directory. It will not find packages in non-virtual environments without specifying the target path
with `--python`. See the [module discovery](https://docs.astral.sh/ty/modules/) documentation for
details.
## Learning more
To learn more about using ty, see the [documentation](https://docs.astral.sh/ty/).
## Installation
To install ty, see the [installation](https://docs.astral.sh/ty/installation/) documentation.
To add the ty language server to your editor, see the [editor integration](https://docs.astral.sh/ty/editors/) guide.
## Getting help
## Getting involved
If you have questions or want to report a bug, please open an
[issue](https://github.com/astral-sh/ty/issues) in this repository.
You may also join our [Discord server](https://discord.com/invite/astral-sh).
## Contributing
Development of this project takes place in the [Ruff](https://github.com/astral-sh/ruff) repository
at this time. Please [open pull requests](https://github.com/astral-sh/ruff/pulls) there for changes
to anything in the `ruff` submodule (which includes all of the Rust source code).
@ -67,26 +58,6 @@ to anything in the `ruff` submodule (which includes all of the Rust source code)
See the
[contributing guide](./CONTRIBUTING.md) for more details.
## FAQ
<!-- We intentionally use smaller headings for the FAQ items -->
<!-- markdownlint-disable MD001 -->
#### Why is ty doing \_\_\_\_\_?
See our [typing FAQ](https://docs.astral.sh/ty/reference/typing-faq).
#### How do you pronounce ty?
It's pronounced as "tee - why" ([`/tiː waɪ/`](https://en.wikipedia.org/wiki/Help:IPA/English#Key))
#### How should I stylize ty?
Just "ty", please.
<!-- markdownlint-enable MD001 -->
## License
ty is licensed under the MIT license ([LICENSE](LICENSE) or

View File

@ -1,7 +1,7 @@
[workspace]
members = ["cargo:./ruff"]
packages = ["ty"]
version = "0.0.8"
version = "0.0.1-alpha.34"
# Config for 'dist'
[dist]

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 5.6 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 5.8 KiB

View File

@ -8,24 +8,25 @@ Specifically, ty will search for a `pyproject.toml` or `ty.toml` file in the cur
If a `pyproject.toml` file is found, ty will read configuration from the `[tool.ty]` table. For example, to ignore the `index-out-of-bounds` rule, add the following to a `pyproject.toml`:
```toml title="pyproject.toml"
**`pyproject.toml`**:
```toml
[tool.ty.rules]
index-out-of-bounds = "ignore"
```
!!! note
If there is no `tool.ty` table, the `pyproject.toml` file will be ignored, and ty will continue
searching in the directory hierarchy.
(If there is no `tool.ty` table, the `pyproject.toml` file will be ignored, and ty will continue searching in the directory hierarchy.)
ty will also search for `ty.toml` files, which follow an identical structure, but omit the `[tool.ty]` prefix. For example:
```toml title="ty.toml"
**`ty.toml`**:
```toml
[rules]
index-out-of-bounds = "ignore"
```
!!! important
!!! note
`ty.toml` files take precedence over `pyproject.toml` files, so if both `ty.toml` and `pyproject.toml` files are present in a directory, configuration will be read from `ty.toml`, and the `[tool.ty]` section in the accompanying `pyproject.toml` will be ignored.

View File

@ -2,9 +2,6 @@
ty can be integrated with various editors to provide a seamless development experience.
Learn more about ty's editor features in the [language server](./features/language-server.md)
documentation.
## VS Code
The Astral team maintains an official VS Code extension.
@ -105,7 +102,7 @@ Starting with version 2025.3, PyCharm users can enable native ty support in the
1. Select which options should be enabled.
For more information, refer to [PyCharm documentation](https://www.jetbrains.com/help/pycharm/lsp-tools.html#ty).
For more information, refer to [PyCharm documentation](https://www.jetbrains.com/help/pycharm/2025.3/lsp-tools.html#ty).
## Other editors
@ -120,7 +117,7 @@ ty server
Refer to your editor's documentation to learn how to connect to an LSP server.
## Settings
## Customize your experience
See the [editor settings reference](./reference/editor-settings.md) for more details on configuring the language
See the [editor settings](./reference/editor-settings.md) for more details on configuring the language
server.

View File

@ -4,17 +4,15 @@ ty automatically discovers all Python files in your project. You can customize w
For example, with the following configuration, ty checks all Python files in the `src` and `tests` directories except those in the `src/generated` directory:
```toml title="pyproject.toml"
```toml
[tool.ty.src]
include = ["src", "tests"]
exclude = ["src/generated"]
```
## Default exclusions
By default, ty excludes a [variety of commonly ignored directories](./reference/configuration.md#exclude). If you want to include one of these directories, you can do so by adding a negative `exclude`:
By default, ty excludes a [variety of commonly ignored directories](./reference/configuration.md#exclude_1). If you want to include one of these directories, you can do so by adding a negative `exclude` using a leading `!`:
```toml title="pyproject.toml"
```toml
[tool.ty.src]
# Remove `build` from the excluded directories.
exclude = ["!**/build/"]
@ -22,9 +20,7 @@ exclude = ["!**/build/"]
By default, ty ignores files listed in an `.ignore` or `.gitignore` file. To disable this functionality, set [`respect-ignore-files`](./reference/configuration.md#respect-ignore-files) to `false`.
## Explicit targets
You may explicitly pass the paths that ty should check, e.g.:
You may also explicitly pass the paths that ty should check, e.g.:
```shell
ty check src scripts/benchmark.py
@ -48,23 +44,8 @@ Both `include` and `exclude` support gitignore like glob patterns:
All patterns are anchored: The pattern `src` only includes `<project_root>/src` but not something like `<project_root>/test/src`. To include any directory named `src`, use the prefix match `**/src`. The same applies for exclude patterns where `src` only excludes `<project_root>/src` but not something like `<project_root>/test/src`.
!!! warning
!!! note
A prefix include pattern like `**/src` can notably slow down the Python file discovery.
All fields accepting patterns use the reduced portable glob syntax from [PEP 639](https://peps.python.org/pep-0639/#add-license-FILES-key), with the addition that characters can be escaped with a backslash.
## Excluding files from virtual environments
In Python 3.13+, the `venv` module will add a `.gitignore` file to the virtual environment root and
ty will not emit diagnostics for the contained files. However, when using an older version of
Python, ty may include diagnostics for files in the virtual environment.
You can resolve this by adding a `.gitignore` to the environment, e.g., for a virtual environment
named `.venv`:
```shell
echo "*" > .venv/.gitignore
```
Or by adding your virtual environment to your `.gitignore` or `.ignore` file.

View File

@ -1,37 +0,0 @@
# Diagnostics
ty provides diagnostics that include snippets of your source code, annotations and helpful
explanations. It will sometimes also provide suggestions on how to fix the reported issues.
## Example: Typed dictionaries
In this first example, ty detected an invalid assignment to a `TypedDict` key. Notice how the
diagnostic includes both the context around the line with the error, as well as the reference to the
`age` item in the `TypedDict` definition:
![TypedDict invalid-assignment diagnostic](screenshots/diagnostics1.dark.png#only-dark)
![TypedDict invalid-assignment diagnostic](screenshots/diagnostics1.light.png#only-light)
When a `TypedDict` key is misspelled, ty will suggest the correct spelling. If you are using an
editor with language server support, you can also apply this suggestion as a quick fix:
![TypedDict misspelled-key diagnostic](screenshots/diagnostics2.dark.png#only-dark)
![TypedDict misspelled-key diagnostic](screenshots/diagnostics2.light.png#only-light)
## Example: Invalid arguments
Here, a file has been opened for writing in text mode, but we are trying to write bytes to it.
The diagnostic points out the type mismatch and also includes the corresponding parameter in the
function definition for `write`:
![Invalid arguments diagnostic](screenshots/diagnostics3.dark.png#only-dark)
![Invalid arguments diagnostic](screenshots/diagnostics3.light.png#only-light)
## Example: Backwards compatibility
Instead of just telling you that `tomllib` can not be found, ty will tell you *why* it is not
available for your project. In this case, your project is targeting Python 3.10, but `tomllib` was
only added in Python 3.11:
![Missing import diagnostic](screenshots/diagnostics4.dark.png#only-dark)
![Missing import diagnostic](screenshots/diagnostics4.light.png#only-light)

View File

@ -1,181 +0,0 @@
<!-- Note for maintainers: the screenshots referenced in this document were taken using
the "Atom One Light" theme in VS Code. -->
# Language server
You can generally expect ty to be a fully-featured [language server] for Python.
This page describes some of the key features provided by ty's IDE integration and includes
a reference table of supported LSP features at the end.
See the [editor integration](../editors.md) guide for instructions on how to set up ty
with your editor.
## Diagnostics
<figure markdown="span">
![](screenshots/inline-diagnostics.png)
<figcaption>Example of an inline diagnostic with code-span annotations</figcaption>
</figure>
ty reports type errors and other [diagnostics](./diagnostics.md) directly in your editor. Diagnostics
are updated as you type. You can use the
[`diagnosticMode`](../reference/editor-settings.md#diagnosticmode) setting to control if you want to
see diagnostics for open files only, or for your entire workspace.
!!! info
ty supports both the "pull" and "push" diagnostic models. Most modern editors will use the "pull" model
for better performance, where diagnostics are fetched on demand rather than pushed after every
change.
## Code navigation
<figure markdown="span">
![](screenshots/find-references.png)
<figcaption>"Find references" shows usages across the entire workspace</figcaption>
</figure>
ty powers several language server features that allow you to navigate a Python codebase:
- **Go to Definition**: Jump to where a symbol is defined. ty resolves imports, function calls,
class references, and more.
- **Go to Declaration**: Navigate to the declaration site of a symbol, which can differ from its
definition (could be in a stub file).
- **Go to Type Definition**: Navigate to the type of a symbol. For example, this takes you to the class `Person`
when invoked on a variable `user: Person`.
- **Find all references**: Find every usage of a function, class, or variable across your entire workspace.
- **Document and workspace symbols**: See an outline of symbols in the current file, or search through symbols across your entire workspace.
## Code completions
<figure markdown="span">
![Code completion example](screenshots/code-completion.png){ width="500" }
<figcaption>Accepting this completion will automatically add a <code>subprocess</code> import at the top of the file.</figcaption>
</figure>
ty provides intelligent code completions as you type, offering suggestions for variables, functions, classes, and modules that are in scope.
For symbols that are not yet imported, ty suggests auto-import actions to add the necessary `import` statements.
## Code actions and refactorings
<figure markdown="span">
![Code action example](screenshots/quick-fix.png){ width="700" }
<figcaption>ty offers to remove the unused suppression comment</figcaption>
</figure>
ty offers quick fixes and other code actions to help you resolve issues:
- **Add import**: Automatically add missing import statements
- **Quick fixes**: Some diagnostics come with quick fix suggestions to resolve the issue
- **Rename symbol**: Safely rename symbols across your entire codebase
- **Selection range**: Expand or shrink the text selection in your editor based on ty's understanding of Python syntax
## Contextual information
<figure markdown="span">
![Inlay hints](screenshots/inlay-hints.png)
<figcaption>Gray inlay hints and on-hover information (signature, docstring)</figcaption>
</figure>
ty surfaces useful contextual information as you code:
- **Hover**: Hover over any symbol to see its type, documentation, function signatures, and other
useful information like the variance of type parameters.
- **Inlay hints**: Display inline type hints for variables and parameters without explicit
annotations, as well as parameter names at call sites. These hints can also be double-clicked
to insert the type annotations into your source code. You can also click on parts of the inlay
hints for go-to-definition navigation.
- **Signature help**: When calling a function, ty displays the function's parameters and their
types. This appears automatically when you type `(` and updates as you navigate between arguments.
- **Document highlight**: When the cursor is on a symbol, ty highlights all occurrences of that
symbol in the current file.
- **Semantic highlighting**: Syntax highlighting based on the underlying semantics and types.
## Notebook support
ty supports Jupyter notebooks (`.ipynb` files) with language server features. Each cell is
analyzed in context, with diagnostics, completions, and other features working across cells.
## Fine-grained incrementality
ty's architecture is designed for low-latency updates of diagnostics and other language server features.
When you make a change in your editor, ty incrementally updates only the affected parts of the
codebase, rather than re-analyzing everything from scratch. This happens at a fine-grained level,
down to individual definitions. This incrementality means that you get instant feedback as you type, i.e.,
within a few milliseconds, even on large projects.
!!! info
Fine-grained dependencies also allow ty to skip large parts of 3rd-party dependencies when they are not relevant
to your codebase.
## Feature reference
<!-- markdownlint-disable MD060 -->
| Feature | Status | Notes |
| ----------------------------------------------------- | ---------------- | ------------------------------------------------------------- |
| [`callHierarchy/*`][callhierarchy] | ❌ Not supported | |
| [`notebookDocument/*`][notebookdocument] | ✅ Supported | |
| [`textDocument/codeAction`][codeaction] | ✅ Supported | Quick fixes |
| [`textDocument/codeLens`][codelens] | ❌ Not supported | |
| [`textDocument/completion`][completion] | ✅ Supported | |
| [`textDocument/declaration`][declaration] | ✅ Supported | |
| [`textDocument/definition`][definition] | ✅ Supported | |
| [`textDocument/diagnostic`][diagnostic] | ✅ Supported | |
| [`textDocument/documentColor`][documentcolor] | ❌ Not supported | |
| [`textDocument/documentHighlight`][documenthighlight] | ✅ Supported | |
| [`textDocument/documentLink`][documentlink] | ❌ Not supported | |
| [`textDocument/documentSymbol`][documentsymbol] | ✅ Supported | |
| [`textDocument/foldingRange`][foldingrange] | ❌ Not supported | |
| [`textDocument/formatting`][formatting] | — | Use [Ruff] for formatting |
| [`textDocument/hover`][hover] | ✅ Supported | |
| [`textDocument/implementation`][implementation] | ❌ Not supported | |
| [`textDocument/inlayHint`][inlayhint] | ✅ Supported | |
| [`textDocument/onTypeFormatting`][ontypeformatting] | — | [Ruff #16829](https://github.com/astral-sh/ruff/issues/16829) |
| [`textDocument/prepareRename`][preparerename] | ✅ Supported | |
| [`textDocument/rangeFormatting`][rangeformatting] | — | Use [Ruff] for formatting |
| [`textDocument/references`][references] | ✅ Supported | |
| [`textDocument/rename`][rename] | ✅ Supported | |
| [`textDocument/selectionRange`][selectionrange] | ✅ Supported | |
| [`textDocument/semanticTokens`][semantictokens] | ✅ Supported | |
| [`textDocument/signatureHelp`][signaturehelp] | ✅ Supported | |
| [`textDocument/typeDefinition`][typedefinition] | ✅ Supported | |
| [`typeHierarchy/*`][typehierarchy] | ❌ Not supported | [#534] |
| [`workspace/diagnostic`][workspacediagnostic] | ✅ Supported | |
| [`workspace/symbol`][workspacesymbol] | ✅ Supported | |
| [`workspace/willRenameFiles`][willrenamefiles] | ❌ Not supported | [#1560] |
[#1560]: https://github.com/astral-sh/ty/issues/1560
[#534]: https://github.com/astral-sh/ty/issues/534
[callhierarchy]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#callHierarchy_incomingCalls
[codeaction]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_codeAction
[codelens]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_codeLens
[completion]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_completion
[declaration]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_declaration
[definition]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_definition
[diagnostic]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_diagnostic
[documentcolor]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_documentColor
[documenthighlight]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_documentHighlight
[documentlink]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_documentLink
[documentsymbol]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_documentSymbol
[foldingrange]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_foldingRange
[formatting]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_formatting
[hover]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_hover
[implementation]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_implementation
[inlayhint]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_inlayHint
[language server]: https://microsoft.github.io/language-server-protocol/
[notebookdocument]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#notebookDocument_synchronization
[ontypeformatting]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_onTypeFormatting
[preparerename]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_prepareRename
[rangeformatting]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_rangeFormatting
[references]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_references
[rename]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_rename
[ruff]: https://docs.astral.sh/ruff/
[selectionrange]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_selectionRange
[semantictokens]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_semanticTokens
[signaturehelp]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_signatureHelp
[typedefinition]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_typeDefinition
[typehierarchy]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#typeHierarchy_supertypes
[willrenamefiles]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#workspace_willRenameFiles
[workspacediagnostic]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#workspace_diagnostic
[workspacesymbol]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#workspace_symbol

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 313 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 309 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 166 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 165 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 285 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 283 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 286 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 284 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

View File

@ -1,223 +0,0 @@
# Type system
You can generally expect ty to support all typing features that are described and specified in the
[Python typing documentation] (for a detailed overview, please refer to the
[type system features tracking issue](https://github.com/astral-sh/ty/issues/1889)). This page
highlights some of the unique features that ty's type system provides.
## Redeclarations
ty allows you to reuse the same symbol with a different type. The following example shows how the
`paths` parameter is redeclared as a list of strings:
```py
def split_paths(paths: str) -> list[Path]:
paths: list[str] = paths.split(":")
return [Path(p) for p in paths]
```
(Full example in the [playground](https://play.ty.dev/80a74c95-a43e-4a3d-8c26-f88e879d7dcb))
## Intersection types
ty has first-class support for intersection types. In contrast to a union type `A | B`, which means
"*either* A *or* B", an intersection type `A & B` means "*both* A *and* B". Type narrowing in ty is
based on intersections. For example, notice how we can call `obj.serialize_json()` *and* access the
`.version` property in the following function:
```py
def output_as_json(obj: Serializable) -> str:
if isinstance(obj, Versioned):
reveal_type(obj) # reveals: Serializable & Versioned
return str({
"data": obj.serialize_json(),
"version": obj.version
})
else:
return obj.serialize_json()
```
(Full example in the [playground](https://play.ty.dev/39241435-5e78-4ce9-817f-ce65be73a6ed))
Intersections can also be built using gradual types like `Any` or its implicit counterpart
`Unknown`. For example, imagine you call into untyped (third party) code that returns an object of
type `Unknown`. Narrowing the type of that object using `isinstance` will result in an intersection
type `Unknown & Iterable`. This type allows you to use `obj` as an iterable. But more importantly,
it still gives you access to attributes defined on the original unknown type (`.description`, in this
example):
```py
def print_content(data: bytes):
obj = untyped_library.deserialize(data)
if isinstance(obj, Iterable):
print(obj.description)
for part in obj:
print("*", part.description)
else:
print(obj.description)
```
(Full example in the [playground](https://play.ty.dev/8f98820e-7306-4d69-b572-56d69a92b90f))
Intersection types are also used in `hasattr` narrowing. Take a look at the following example where
we narrow a type of `Person | Animal | None` using `hasattr(…, "name")`. `Person` is preserved in
the narrowed union type because it has a `name` attribute. `Animal` is intersected with a synthetic
protocol, accounting for the possibility of subclasses of `Animal` that add a `name` member.
`None` is excluded completely since it is a final type that has no `name` attribute:
```py
class Person:
name: str
class Animal:
species: str
def greet(being: Person | Animal | None):
if hasattr(being, "name"):
# `being` is now of type `Person | (Animal & <Protocol with members 'name'>)`
print(f"Hello, {being.name}!")
else:
print("Hello there!")
```
(Full example in the [playground](https://play.ty.dev/31f2c718-516a-4a85-80e0-2a4682b818f1))
!!! info
If you run into a situation like this and would like `Animal` to be excluded from the narrowed
type as well, you can make `Animal` a `@final` class. This also allows ty to infer a more precise
type for `being.name` (`str` instead of `object`).
If ty is the only type checker you use, you can also make direct use of intersection types in
annotations by importing `Intersection` from the special `ty_extensions` module that is (currently)
only available at type-checking time:
```py
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from ty_extensions import Intersection
type SerializableVersioned = Intersection[Serializable, Versioned]
def output_as_json(obj: SerializableVersioned) -> str:
...
```
(Full example in the [playground](https://play.ty.dev/f003e901-0e45-4f45-9759-d6db9d5e5f66))
## Top and bottom materializations
Gradual types generally have two special [materializations]. The top materialization represents the
"largest" type that a gradual type can materialize to: the union of all possible materializations.
For example, the top materialization of `Any` is `object`, and the top materialization of
`Any & int` is `int`. For invariant generic classes, the top materialization cannot be expressed in
Python's type system, but it is a useful type that ty intersects with when `isinstance` checks
involve generic classes. For example, when checking `isinstance(…, list)`, ty intersects with the
top materialization of `list[Unknown]`:
```py
@final
class Item: ...
def process(items: Item | list[Item]):
if isinstance(items, list):
# reveals: list[Item]
reveal_type(items)
```
(Full example in the [playground](https://play.ty.dev/f1306120-0b8d-4ed5-b832-1f2d379eae2b))
!!! info
You might wonder why `Item` is declared `@final` here. If we remove the `@final` decorator, the
inferred type in the `if` branch becomes `(Item & Top[list[Unknown]]) | list[Item]` instead.
This accounts for the possibility of classes that inherit from both `Item` *and* `list`! If
you run into this situation and want to rule out this case, you can also perform the `isinstance`
check against `Item` instead. The `else` branch will then have a narrowed type of
`list[Item] & ~Item`, which effectively acts like `list[Item]`.
## Reachability based on types
Reachability analysis in ty is based on type inference. This allows ty to detect unreachable
branches in many more situations compared to approaches which match on a few known patterns (e.g.
`sys.version_info >= (3, 10)` checks). This has useful practical applications. Consider a case
where you are writing code that needs to be compatible with two major versions of a dependency.
The following code can be successfully type-checked with either pydantic 1.x installed, or pydantic
2.x installed. In both cases, ty will only consider the corresponding branch to be reachable, and
will not emit any type errors for the other branch. This works because
`pydantic.__version__.startswith("2.")` can be evaluated to `True` or `False` at type-checking time:
```py
import pydantic
from pydantic import BaseModel
PYDANTIC_V2 = pydantic.__version__.startswith("2.")
class Person(BaseModel):
name: str
def to_json(person: Person):
if PYDANTIC_V2:
return person.model_dump_json() # no error here when checking with 1.x
else:
return person.json()
```
(Full example in the [playground](https://play.ty.dev/34a227bb-93d5-405e-86c3-72f57ec5642e))
## Gradual guarantee
ty generally tries to avoid emitting false positive type errors in untyped code. The following
snippet does not produce any type errors when checked with ty (whereas other type checkers make the
assumption that `max_retries` is of type `None`, leading to an error in the attribute assignment):
```py
class RetryPolicy:
max_retries = None
policy = RetryPolicy()
policy.max_retries = 1
```
(Full example in the [playground](https://play.ty.dev/a5286db1-cdfd-45e7-af54-29649ba5c423))
This is achieved by treating `max_retries` as being of type `Unknown | None`, which means that the
type of the attribute is not fully known, but `None` is definitely a possible value.
Users can always opt into stricter checking by adding type annotations (`int | None`, in this case).
!!! info
We are also planning to add a mode for users that prefer to have stricter types inferred by default
in these situations. You can follow [this issue](https://github.com/astral-sh/ty/issues/1240) for
updates.
## Fixpoint iteration
In a situation where a symbol's type cyclically depends on itself, ty uses a mechanism called fixpoint iteration to
be able to infer a type for that symbol. In the `tick` method below, note how the type of `self.value` depends on
`self.value` itself. ty starts by assuming that `self.value` is just `Unknown | Literal[0]` (the type inferred
from the `__init__` method), and then iterates until the type converges to `Unknown | Literal[0, 1, 2, 3, 4]`.
Without the modulo operation, the union would grow indefinitely. In that case, we fall back to `int` after a certain
number of iterations.
```py
class LoopingCounter:
def __init__(self):
self.value = 0
def tick(self):
self.value = (self.value + 1) % 5
# reveals: Unknown | Literal[0, 1, 2, 3, 4]
reveal_type(LoopingCounter().value)
```
(Full example in the [playground](https://play.ty.dev/64400d96-ee1b-48f3-8361-b583dddddf82))
[materializations]: https://typing.python.org/en/latest/spec/concepts.html#materialization
[python typing documentation]: https://typing.python.org/en/latest/spec/index.html

View File

@ -1,58 +1,54 @@
# ty
An extremely fast Python type checker and language server, written in Rust.
<p align="center">
<img alt="Shows a bar chart with benchmark results." width="500px" src="./assets/ty-benchmark-cli.svg#only-light">
</p>
<p align="center">
<img alt="Shows a bar chart with benchmark results." width="500px" src="./assets/ty-benchmark-cli-dark.svg#only-dark">
</p>
<p align="center">
<i>Type checking the <a href="https://github.com/home-assistant/core">home-assistant</a> project without caching.</i>
</p>
ty is backed by [Astral](https://astral.sh), the creators of
[uv](https://github.com/astral-sh/uv) and [Ruff](https://github.com/astral-sh/ruff).
An extremely fast Python type checker, written in Rust.
<!-- TODO
## Highlights
- 10x - 100x faster than mypy and Pyright
- Comprehensive [diagnostics](./features/diagnostics.md) with rich contextual information
- Configurable [rule levels](./rules.md), [per-file overrides](./reference/configuration.md#overrides), [suppression comments](./suppression.md), and first-class project support
- Designed for adoption, with support for [redeclarations](./features/type-system.md#redeclarations) and [partially typed code](./features/type-system.md#gradual-guarantee)
- [Language server](./features/language-server.md) with code navigation, completions, code actions, auto-import, inlay hints, on-hover help, etc.
- Fine-grained [incremental analysis](./features/language-server.md#fine-grained-incrementality) designed for fast updates when editing files in an IDE
- Editor integrations for [VS Code](./editors.md#vs-code), [PyCharm](./editors.md#pycharm), [Neovim](./editors.md#neovim) and more
- Advanced typing features like first-class [intersection types](./features/type-system.md#intersection-types), advanced [type narrowing](./features/type-system.md#top-and-bottom-materializations), and
[sophisticated reachability analysis](./features/type-system.md#reachability-based-on-types)
- ...
-->
## Getting started
Run ty with [uvx](https://docs.astral.sh/uv/guides/tools/#running-tools) to get started quickly:
Try out the [online playground](https://play.ty.dev), or run ty with
[uvx](https://docs.astral.sh/uv/guides/tools/#running-tools) to get started quickly:
```shell
uvx ty
```
For other ways to install ty, see the [installation](./installation.md) documentation.
If you do not provide a subcommand, ty will list available commands — for detailed information about
command-line options, see the [CLI reference](./reference/cli.md).
Use the `check` command to run the type checker:
```shell
uvx ty check
```
ty will check all Python files in the working directory or project by default.
ty will run on all Python files in the working directory and or subdirectories. If used from a
project, ty will run on all Python files in the project (starting in the directory with the
`pyproject.toml`)
See the [type checking](./type-checking.md) documentation for more details.
You can also provide specific paths to check:
## Installation
```shell
uvx ty check example.py
```
To install ty, see the [installation](./installation.md) documentation.
When type checking, ty will find installed packages in the active virtual environment (via
`VIRTUAL_ENV`) or discover a virtual environment named `.venv` in the project root or working
directory. It will not find packages in non-virtual environments without specifying the target path
with `--python`. See the [module discovery](./modules.md) documentation for
details.
To add the ty language server to your editor, see the [editor integration](./editors.md) guide.
### Usage
## Playground
Run [`ty check`](./reference/cli.md#ty-check), in your project's top-level directory,
to check the project for type errors using ty's default configuration.
ty has an [online playground](https://play.ty.dev) you can use to try it out on snippets or small
projects.
!!! tip
The playground is a great way to share snippets with other people, e.g., when sharing a bug
report.
If this provokes a cascade of errors, and you are using the standard library `venv` module
to provide your virtual environment, add the venv directory to your `.gitignore`
or `.ignore` file and then retry.

View File

@ -1,21 +1,6 @@
# Installing ty
## Running ty without installation
Use [uvx](https://docs.astral.sh/uv/guides/tools/) to quickly get started with ty:
```shell
uvx ty
```
## Installation methods
### Adding ty to your project
!!! tip
Adding ty as a dependency ensures that all developers on the project are using the same version
of ty.
## Adding ty to your project
Use [uv](https://github.com/astral-sh/uv) (or your project manager of choice) to add ty as a
development dependency:
@ -24,19 +9,16 @@ development dependency:
uv add --dev ty
```
Adding ty as a dependency ensures that all developers on the project are using the same version of
ty.
Then, use `uv run` to invoke ty:
```shell
uv run ty
```
To update ty, use `--upgrade-package`:
```shell
uv lock --upgrade-package ty
```
### Installing globally with uv
## Installing globally
Install ty globally with uv:
@ -44,158 +26,16 @@ Install ty globally with uv:
uv tool install ty@latest
```
To update ty, use `uv tool upgrade`:
```shell
uv tool upgrade ty
```
### Installing with the standalone installer
ty includes a standalone installer.
=== "macOS and Linux"
Use `curl` to download the script and execute it with `sh`:
```console
$ curl -LsSf https://astral.sh/ty/install.sh | sh
```
If your system doesn't have `curl`, you can use `wget`:
```console
$ wget -qO- https://astral.sh/ty/install.sh | sh
```
Request a specific version by including it in the URL:
```console
$ curl -LsSf https://astral.sh/ty/0.0.8/install.sh | sh
```
=== "Windows"
Use `irm` to download the script and execute it with `iex`:
```pwsh-session
PS> powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/ty/install.ps1 | iex"
```
Changing the [execution policy](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_execution_policies?view=powershell-7.4#powershell-execution-policies) allows running a script from the internet.
Request a specific version by including it in the URL:
```pwsh-session
PS> powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/ty/0.0.8/install.ps1 | iex"
```
!!! tip
The installation script may be inspected before use:
=== "macOS and Linux"
```console
$ curl -LsSf https://astral.sh/ty/install.sh | less
```
=== "Windows"
```pwsh-session
PS> powershell -c "irm https://astral.sh/ty/install.ps1 | more"
```
Alternatively, the installer or binaries can be downloaded directly from [GitHub](#installing-from-github-releases).
### Installing from GitHub Releases
ty release artifacts can be downloaded directly from
[GitHub Releases](https://github.com/astral-sh/ty/releases).
Each release page includes binaries for all supported platforms as well as instructions for using
the standalone installer via `github.com` instead of `astral.sh`.
### Installing globally with pipx
Install ty globally with pipx:
Or, pipx:
```shell
pipx install ty
```
To update ty, use `pipx upgrade`:
```shell
pipx upgrade ty
```
### Installing with pip
## Installing with pip
Install ty into your current Python environment with pip:
```shell
pip install ty
```
### Installing in Docker
Install ty in Docker by copying the binary from the official image:
```dockerfile title="Dockerfile"
COPY --from=ghcr.io/astral-sh/ty:latest /ty /bin/
```
The following tags are available:
- `ghcr.io/astral-sh/ty:latest`
- `ghcr.io/astral-sh/ty:{major}.{minor}.{patch}`, e.g., `ghcr.io/astral-sh/ty:0.0.8`
- `ghcr.io/astral-sh/ty:{major}.{minor}`, e.g., `ghcr.io/astral-sh/ty:0.0` (the latest patch
version)
## Adding ty to your editor
See the [editor integration](./editors.md) guide to add ty to your editor.
## Shell autocompletion
!!! tip
You can run `echo $SHELL` to help you determine your shell.
To enable shell autocompletion for ty commands, run one of the following:
=== "Bash"
```bash
echo 'eval "$(ty generate-shell-completion bash)"' >> ~/.bashrc
```
=== "Zsh"
```bash
echo 'eval "$(ty generate-shell-completion zsh)"' >> ~/.zshrc
```
=== "fish"
```bash
echo 'ty generate-shell-completion fish | source' > ~/.config/fish/completions/ty.fish
```
=== "Elvish"
```bash
echo 'eval (ty generate-shell-completion elvish | slurp)' >> ~/.elvish/rc.elv
```
=== "PowerShell / pwsh"
```powershell
if (!(Test-Path -Path $PROFILE)) {
New-Item -ItemType File -Path $PROFILE -Force
}
Add-Content -Path $PROFILE -Value '(& ty generate-shell-completion powershell) | Out-String | Invoke-Expression'
```
Then restart the shell or source the shell config file.

View File

@ -22,13 +22,13 @@ example-pkg
then set [`environment.root`](./reference/configuration.md#root) in your `pyproject.toml` to `["./app"]`:
```toml title="pyproject.toml"
```toml
[tool.ty.environment]
root = ["./app"]
```
Note that a `./python` folder is automatically added to the project `root` if it exists,
and is not itself a package (i.e. does not contain an `__init__.py` file or an
Note that `python` and `tests` folders are automatically added to the project `root` if they exist,
and if they are not packages themselves (i.e. they do not contain an `__init__.py` file or an
`__init__.pyi` file).
## Third-party modules

View File

@ -35,7 +35,7 @@ configured or detected, ty will try to infer the Python version being used from
environment's metadata.
If no virtual environment is present or inferring the Python version from the metadata fails,
ty will fall back to the latest stable Python version supported by ty (currently 3.14).
ty will fall back to the latest stable Python version supported by ty (currently 3.13).
The Python version may also be explicitly specified using the
[`python-version`](./reference/configuration.md#python-version) setting or the

1
docs/reference/cli.md generated
View File

@ -56,7 +56,6 @@ over all configuration files.</p>
</dd><dt id="ty-check--exit-zero"><a href="#ty-check--exit-zero"><code>--exit-zero</code></a></dt><dd><p>Always use exit code 0, even when there are error-level diagnostics</p>
</dd><dt id="ty-check--extra-search-path"><a href="#ty-check--extra-search-path"><code>--extra-search-path</code></a> <i>path</i></dt><dd><p>Additional path to use as a module-resolution source (can be passed multiple times).</p>
<p>This is an advanced option that should usually only be used for first-party or third-party modules that are not installed into your Python environment in a conventional way. Use <code>--python</code> to point ty to your Python environment if it is in an unusual location.</p>
</dd><dt id="ty-check--force-exclude"><a href="#ty-check--force-exclude"><code>--force-exclude</code></a></dt><dd><p>Enforce exclusions, even for paths passed to ty directly on the command-line. Use <code>--no-force-exclude</code> to disable</p>
</dd><dt id="ty-check--help"><a href="#ty-check--help"><code>--help</code></a>, <code>-h</code></dt><dd><p>Print help (see a summary with '-h')</p>
</dd><dt id="ty-check--ignore"><a href="#ty-check--ignore"><code>--ignore</code></a> <i>rule</i></dt><dd><p>Disables the rule. Can be specified multiple times.</p>
</dd><dt id="ty-check--no-progress"><a href="#ty-check--no-progress"><code>--no-progress</code></a></dt><dd><p>Hide all progress outputs.</p>

View File

@ -18,61 +18,13 @@ Valid severities are:
**Type**: `dict[RuleName, "ignore" | "warn" | "error"]`
**Example usage**:
**Example usage** (`pyproject.toml`):
=== "pyproject.toml"
```toml
[tool.ty.rules]
possibly-unresolved-reference = "warn"
division-by-zero = "ignore"
```
=== "ty.toml"
```toml
[rules]
possibly-unresolved-reference = "warn"
division-by-zero = "ignore"
```
---
## `analysis`
### `respect-type-ignore-comments`
Whether ty should respect `type: ignore` comments.
When set to `false`, `type: ignore` comments are treated like any other normal
comment and can't be used to suppress ty errors (you have to use `ty: ignore` instead).
Setting this option can be useful when using ty alongside other type checkers or when
you prefer using `ty: ignore` over `type: ignore`.
Defaults to `true`.
**Default value**: `true`
**Type**: `bool`
**Example usage**:
=== "pyproject.toml"
```toml
[tool.ty.analysis]
# Disable support for `type: ignore` comments
respect-type-ignore-comments = false
```
=== "ty.toml"
```toml
[analysis]
# Disable support for `type: ignore` comments
respect-type-ignore-comments = false
```
```toml
[tool.ty.rules]
possibly-unresolved-reference = "warn"
division-by-zero = "ignore"
```
---
@ -93,21 +45,12 @@ configuration setting.
**Type**: `list[str]`
**Example usage**:
**Example usage** (`pyproject.toml`):
=== "pyproject.toml"
```toml
[tool.ty.environment]
extra-paths = ["./shared/my-search-path"]
```
=== "ty.toml"
```toml
[environment]
extra-paths = ["./shared/my-search-path"]
```
```toml
[tool.ty.environment]
extra-paths = ["./shared/my-search-path"]
```
---
@ -133,21 +76,12 @@ This option can be used to point to virtual or system Python environments.
**Type**: `str`
**Example usage**:
**Example usage** (`pyproject.toml`):
=== "pyproject.toml"
```toml
[tool.ty.environment]
python = "./custom-venv-location/.venv"
```
=== "ty.toml"
```toml
[environment]
python = "./custom-venv-location/.venv"
```
```toml
[tool.ty.environment]
python = "./custom-venv-location/.venv"
```
---
@ -169,23 +103,13 @@ If no platform is specified, ty will use the current platform:
**Type**: `"win32" | "darwin" | "android" | "ios" | "linux" | "all" | str`
**Example usage**:
**Example usage** (`pyproject.toml`):
=== "pyproject.toml"
```toml
[tool.ty.environment]
# Tailor type stubs and conditionalized type definitions to windows.
python-platform = "win32"
```
=== "ty.toml"
```toml
[environment]
# Tailor type stubs and conditionalized type definitions to windows.
python-platform = "win32"
```
```toml
[tool.ty.environment]
# Tailor type stubs and conditionalized type definitions to windows.
python-platform = "win32"
```
---
@ -213,21 +137,12 @@ to reflect the differing contents of the standard library across Python versions
**Type**: `"3.7" | "3.8" | "3.9" | "3.10" | "3.11" | "3.12" | "3.13" | "3.14" | <major>.<minor>`
**Example usage**:
**Example usage** (`pyproject.toml`):
=== "pyproject.toml"
```toml
[tool.ty.environment]
python-version = "3.12"
```
=== "ty.toml"
```toml
[environment]
python-version = "3.12"
```
```toml
[tool.ty.environment]
python-version = "3.12"
```
---
@ -243,30 +158,20 @@ If left unspecified, ty will try to detect common project layouts and initialize
* if a `./<project-name>/<project-name>` directory exists, include `.` and `./<project-name>` in the first party search path
* otherwise, default to `.` (flat layout)
Additionally, if a `./python` directory exists and is not a package (i.e. it does not contain an `__init__.py` or `__init__.pyi` file),
Besides, if a `./python` or `./tests` directory exists and is not a package (i.e. it does not contain an `__init__.py` or `__init__.pyi` file),
it will also be included in the first party search path.
**Default value**: `null`
**Type**: `list[str]`
**Example usage**:
**Example usage** (`pyproject.toml`):
=== "pyproject.toml"
```toml
[tool.ty.environment]
# Multiple directories (priority order)
root = ["./src", "./lib", "./vendor"]
```
=== "ty.toml"
```toml
[environment]
# Multiple directories (priority order)
root = ["./src", "./lib", "./vendor"]
```
```toml
[tool.ty.environment]
# Multiple directories (priority order)
root = ["./src", "./lib", "./vendor"]
```
---
@ -280,21 +185,12 @@ bundled as a zip file in the binary
**Type**: `str`
**Example usage**:
**Example usage** (`pyproject.toml`):
=== "pyproject.toml"
```toml
[tool.ty.environment]
typeshed = "/path/to/custom/typeshed"
```
=== "ty.toml"
```toml
[environment]
typeshed = "/path/to/custom/typeshed"
```
```toml
[tool.ty.environment]
typeshed = "/path/to/custom/typeshed"
```
---
@ -304,22 +200,24 @@ Configuration override that applies to specific files based on glob patterns.
An override allows you to apply different rule configurations to specific
files or directories. Multiple overrides can match the same file, with
later overrides take precedence. Override rules take precedence over global
rules for matching files.
later overrides take precedence.
For example, to relax enforcement of rules in test files:
### Precedence
- Later overrides in the array take precedence over earlier ones
- Override rules take precedence over global rules for matching files
### Examples
```toml
# Relax rules for test files
[[tool.ty.overrides]]
include = ["tests/**", "**/test_*.py"]
[tool.ty.overrides.rules]
possibly-unresolved-reference = "warn"
```
Or, to ignore a rule in generated files but retain enforcement in an important file:
```toml
# Ignore generated files but still check important ones
[[tool.ty.overrides]]
include = ["generated/**"]
exclude = ["generated/important.py"]
@ -342,31 +240,17 @@ If not specified, defaults to `[]` (excludes no files).
**Type**: `list[str]`
**Example usage**:
**Example usage** (`pyproject.toml`):
=== "pyproject.toml"
```toml
[[tool.ty.overrides]]
exclude = [
"generated",
"*.proto",
"tests/fixtures/**",
"!tests/fixtures/important.py" # Include this one file
]
```
=== "ty.toml"
```toml
[[overrides]]
exclude = [
"generated",
"*.proto",
"tests/fixtures/**",
"!tests/fixtures/important.py" # Include this one file
]
```
```toml
[[tool.ty.overrides]]
exclude = [
"generated",
"*.proto",
"tests/fixtures/**",
"!tests/fixtures/important.py" # Include this one file
]
```
---
@ -384,27 +268,15 @@ If not specified, defaults to `["**"]` (matches all files).
**Type**: `list[str]`
**Example usage**:
**Example usage** (`pyproject.toml`):
=== "pyproject.toml"
```toml
[[tool.ty.overrides]]
include = [
"src",
"tests",
]
```
=== "ty.toml"
```toml
[[overrides]]
include = [
"src",
"tests",
]
```
```toml
[[tool.ty.overrides]]
include = [
"src",
"tests",
]
```
---
@ -420,27 +292,15 @@ severity levels or disable them entirely.
**Type**: `dict[RuleName, "ignore" | "warn" | "error"]`
**Example usage**:
**Example usage** (`pyproject.toml`):
=== "pyproject.toml"
```toml
[[tool.ty.overrides]]
include = ["src"]
```toml
[[tool.ty.overrides]]
include = ["src"]
[tool.ty.overrides.rules]
possibly-unresolved-reference = "ignore"
```
=== "ty.toml"
```toml
[[overrides]]
include = ["src"]
[overrides.rules]
possibly-unresolved-reference = "ignore"
```
[tool.ty.overrides.rules]
possibly-unresolved-reference = "ignore"
```
---
@ -498,31 +358,17 @@ to re-include `dist` use `exclude = ["!dist"]`
**Type**: `list[str]`
**Example usage**:
**Example usage** (`pyproject.toml`):
=== "pyproject.toml"
```toml
[tool.ty.src]
exclude = [
"generated",
"*.proto",
"tests/fixtures/**",
"!tests/fixtures/important.py" # Include this one file
]
```
=== "ty.toml"
```toml
[src]
exclude = [
"generated",
"*.proto",
"tests/fixtures/**",
"!tests/fixtures/important.py" # Include this one file
]
```
```toml
[tool.ty.src]
exclude = [
"generated",
"*.proto",
"tests/fixtures/**",
"!tests/fixtures/important.py" # Include this one file
]
```
---
@ -553,27 +399,15 @@ matches `<project_root>/src` and not `<project_root>/test/src`).
**Type**: `list[str]`
**Example usage**:
**Example usage** (`pyproject.toml`):
=== "pyproject.toml"
```toml
[tool.ty.src]
include = [
"src",
"tests",
]
```
=== "ty.toml"
```toml
[src]
include = [
"src",
"tests",
]
```
```toml
[tool.ty.src]
include = [
"src",
"tests",
]
```
---
@ -587,28 +421,19 @@ Enabled by default.
**Type**: `bool`
**Example usage**:
**Example usage** (`pyproject.toml`):
=== "pyproject.toml"
```toml
[tool.ty.src]
respect-ignore-files = false
```
=== "ty.toml"
```toml
[src]
respect-ignore-files = false
```
```toml
[tool.ty.src]
respect-ignore-files = false
```
---
### `root`
!!! warning "Deprecated"
This option has been deprecated. Use `environment.root` instead.
> [!WARN] "Deprecated"
> This option has been deprecated. Use `environment.root` instead.
The root of the project, used for finding first-party modules.
@ -618,28 +443,19 @@ If left unspecified, ty will try to detect common project layouts and initialize
* if a `./<project-name>/<project-name>` directory exists, include `.` and `./<project-name>` in the first party search path
* otherwise, default to `.` (flat layout)
Additionally, if a `./python` directory exists and is not a package (i.e. it does not contain an `__init__.py` file),
Besides, if a `./tests` directory exists and is not a package (i.e. it does not contain an `__init__.py` file),
it will also be included in the first party search path.
**Default value**: `null`
**Type**: `str`
**Example usage**:
**Example usage** (`pyproject.toml`):
=== "pyproject.toml"
```toml
[tool.ty.src]
root = "./app"
```
=== "ty.toml"
```toml
[src]
root = "./app"
```
```toml
[tool.ty.src]
root = "./app"
```
---
@ -655,23 +471,13 @@ Defaults to `false`.
**Type**: `bool`
**Example usage**:
**Example usage** (`pyproject.toml`):
=== "pyproject.toml"
```toml
[tool.ty.terminal]
# Error if ty emits any warning-level diagnostics.
error-on-warning = true
```
=== "ty.toml"
```toml
[terminal]
# Error if ty emits any warning-level diagnostics.
error-on-warning = true
```
```toml
[tool.ty.terminal]
# Error if ty emits any warning-level diagnostics.
error-on-warning = true
```
---
@ -685,21 +491,12 @@ Defaults to `full`.
**Type**: `full | concise`
**Example usage**:
**Example usage** (`pyproject.toml`):
=== "pyproject.toml"
```toml
[tool.ty.terminal]
output-format = "concise"
```
=== "ty.toml"
```toml
[terminal]
output-format = "concise"
```
```toml
[tool.ty.terminal]
output-format = "concise"
```
---

View File

@ -3,138 +3,6 @@
The editor settings supported by ty's language server, as well as the settings specific to [ty's VS
Code extension][ty-vscode].
## `configuration`
In-editor configuration of ty's settings. The inline settings always take precedence over the settings from configuration files,
including the configuration specified with [`configurationFile`](#configurationfile).
Consult [the configuration reference](../configuration.md) for a list of all supported configuration options.
**Default value**: `null`
**Type**: `object`
**Example usage**:
=== "VS Code"
```json
{
"ty.configuration": {
"rules": {
"unresolved-reference": "warn"
}
}
}
```
=== "Neovim"
```lua
require('lspconfig').ty.setup({
settings = {
ty = {
configuration = {
rules = {
["unresolved-reference"] = "warn"
}
}
},
},
})
-- For Neovim 0.11.0 and later:
vim.lsp.config('ty', {
settings = {
ty = {
configuration = {
rules = {
["unresolved-reference"] = "warn"
}
}
},
},
})
```
=== "Zed"
```json
{
"lsp": {
"ty": {
"settings": {
"configuration": {
"rules": {
"unresolved-reference": "warn"
}
}
}
}
}
}
```
## `configurationFile`
The path to a `ty.toml` configuration file. ty will use the specified configuration over any automatically discovered configuration.
ty will expand a tilde `~` at the start of a string to the user's home directory, as well as variables like `$A` or `${A}`.
!!! info
While ty configuration can be included in a `pyproject.toml` file, it is not allowed in this context.
**Default value**: `null`
**Type**: `string`
**Example usage**:
=== "VS Code"
```json
{
"ty.configurationFile": "./.config/ty.toml"
}
```
=== "Neovim"
```lua
require('lspconfig').ty.setup({
settings = {
ty = {
configurationFile = "./.config/ty.toml"
},
},
})
-- For Neovim 0.11.0 and later:
vim.lsp.config('ty', {
settings = {
ty = {
configurationFile = "./.config/ty.toml"
},
},
})
```
=== "Zed"
```json
{
"lsp": {
"ty": {
"settings": {
"configurationFile": "./.config/ty.toml"
}
}
}
}
```
______________________________________________________________________
## `disableLanguageServices`
Whether to disable the language services for the ty language server like code completion, hover,
@ -194,20 +62,42 @@ server for features like code completion, hover, go to definition, etc.
______________________________________________________________________
## `python.ty.disableLanguageServices`
!!! warning "Deprecated"
This option has been deprecated. Use [`ty.disableLanguageServices`](#disablelanguageservices) instead.
Whether to disable the language services that ty provides like code completion, hover, go to
definition, etc.
This is useful if you want to use ty exclusively for type checking in combination with another
language server for features like code completion, hover, go to definition, etc.
**Default value**: `false`
**Type**: `boolean`
**Example usage**:
```json
{
"python.ty.disableLanguageServices": true
}
```
______________________________________________________________________
## `diagnosticMode`
Determines the scope of the diagnostics reported by the language server.
Setting this to `off` is useful if you want to use ty exclusively for the language server features
like code completion, hover, go to definition, etc.
- `off`: Diagnostics are disabled.
- `openFilesOnly`: Diagnostics are reported only for files that are currently open in the editor.
- `workspace`: Diagnostics are reported for all files in the workspace.
**Default value**: `"openFilesOnly"`
**Type**: `"off" | "workspace" | "openFilesOnly"`
**Type**: `"workspace" | "openFilesOnly"`
**Example usage**:
@ -256,64 +146,6 @@ like code completion, hover, go to definition, etc.
______________________________________________________________________
## `showSyntaxErrors`
Whether to show syntax error diagnostics.
This is useful when using ty with other language servers, allowing the user to refer to syntax errors
from only one source.
**Default value**: `true`
**Type**: `bool`
**Example usage**:
=== "VS Code"
```json
{
"ty.showSyntaxErrors": false
}
```
=== "Neovim"
```lua
require('lspconfig').ty.setup({
settings = {
ty = {
showSyntaxErrors = false,
},
},
})
-- For Neovim 0.11.0 and later:
vim.lsp.config('ty', {
settings = {
ty = {
showSyntaxErrors = false,
},
},
})
```
=== "Zed"
```json
{
"lsp": {
"ty": {
"settings": {
"showSyntaxErrors": false
}
}
}
}
```
______________________________________________________________________
## `inlayHints`
These settings control the inline hints that ty provides in an editor.

View File

@ -2,15 +2,6 @@
ty defines and respects the following environment variables:
### `TY_CONFIG_FILE`
Path to a `ty.toml` configuration file to use.
When set, ty will use this file for configuration instead of
discovering configuration files automatically.
Equivalent to the `--config-file` command-line argument.
### `TY_LOG`
If set, ty will use this value as the log level for its `--verbose` output.

1410
docs/reference/rules.md generated

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,465 @@
# Type system features
This issue summarizes the support for various type system features in ty. Sections are organized to follow the structure of the [Python typing specification](https://typing.python.org/en/latest/spec/), with some additional sections at the end. If a top-level item is marked completed without any sub-items, you can generally expect that feature to be fully implemented (and we value any bug reports in case you find issues). If a top-level item is marked completed with open sub-items, the feature is generally working, but there might be some open issues — including but not limited to the ones listed (in this case, we also value any bug reports, but please search the issue tracker before doing so). If a top-level item is not checked, the feature is not implemented yet (it's probably not helpful to report bugs, but feel free to upvote the tracking issue or comment if you have useful information).
## Special types and type qualifiers
[Official documentation](https://typing.python.org/en/latest/spec/special-types.html)
**tests:** [`any.md`](https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/resources/mdtest/annotations/any.md), [`never.md`](https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/resources/mdtest/annotations/never.md), [`int_float_complex.md`](https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/resources/mdtest/annotations/int_float_complex.md), [`final.md`](https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/resources/mdtest/type_qualifiers/final.md), [`classvar.md`](https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/resources/mdtest/type_qualifiers/classvar.md), [`annotated.md`](https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/resources/mdtest/annotations/annotated.md), [`union.md`](https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/resources/mdtest/annotations/union.md), [`instance_layout_conflict.md`](https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/resources/mdtest/instance_layout_conflict.md)
- [x] `Any`
- [x] `None`
- [x] `NoReturn`, `Never`
- [x] `object`
- [x] `Literal[...]` (strings, ints, bools, enum, None)
- [x] `LiteralString`
- [x] `type[C]`
- [x] `float`/`complex` special cases (`float` means `int | float`)
- [x] `Final`, `Final[T]`
- [ ] Diagnostic: subclass overrides `Final` attribute #871
- [ ] Diagnostic: `Final` without binding #872
- [x] `@final` decorator
- [x] `@disjoint_base` decorator
- [x] `ClassVar`, `ClassVar[T]`
- [ ] Diagnostic: `ClassVar` with type variable #518
- [x] `InitVar[T]` (see Dataclasses)
- [x] `Annotated[T, ...]`
- [x] `Required[T]`, `NotRequired[T]` (see TypedDict)
- [x] `ReadOnly[T]` (see TypedDict)
- [x] `Union[X, Y]`, `X | Y`
- [x] `Optional[X]`
- [ ] `type()` functional syntax #740
## Generics
[Official documentation](https://typing.python.org/en/latest/spec/generics.html)
**tests:** [`pep695/`](https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/resources/mdtest/generics/pep695/), [`legacy/`](https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/resources/mdtest/generics/legacy/), [`self.md`](https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/resources/mdtest/annotations/self.md), [`scoping.md`](https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/resources/mdtest/generics/scoping.md)
- [x] `TypeVar` (legacy syntax)
- [x] `TypeVar` (PEP 695 syntax: `def f[T]()`)
- [x] `TypeVar` upper bound (`bound=`)
- [x] `TypeVar` constraints
- [x] `TypeVar` defaults (PEP 696)
- [x] `TypeVar` variance (`covariant`, `contravariant`)
- [x] `TypeVar` variance inference (`infer_variance`)
- [x] Generic classes (legacy and PEP 695 syntax)
- [x] Generic functions (legacy and PEP 695 syntax)
- [x] Generic type aliases (PEP 695)
- [ ] Some limitations #1851
- [x] `ParamSpec` (legacy and PEP 695 syntax)
- [ ] `ParamSpec` usage validation #1861
- [x] `ParamSpec.args`, `ParamSpec.kwargs`
- [x] `ParamSpec` defaults
- [x] `Self`
- [ ] `Self` in attribute annotations #1124
- [ ] Solve type variables in all cases #623
- [x] Generic classes
- [x] Unions
- [ ] `Callable`s
- [ ] Generic protocols #1714
- [ ] Generic bounds/constraints on type variables #1839
- [ ] Support `TypeVarTuple` #156
## Protocols
[Official documentation](https://typing.python.org/en/latest/spec/protocol.html)
**tests:** [`protocols.md`](https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/resources/mdtest/protocols.md)
- [x] `Protocol` class definition
- [x] Generic protocols (legacy and PEP 695 syntax)
- [x] Structural subtyping / assignability
- [x] Protocol inheritance
- [x] `is_protocol()`, `get_protocol_members()`
- [x] `@runtime_checkable` decorator
- [x] Protocol instantiation restriction
- [x] Non-protocol class inheritance restriction
- [x] `@property` members
- [ ] Partial support #1379
- [ ] Modules as protocol implementations #931
- [ ] `@classmethod` and `@staticmethod` members #1381
- [ ] `ClassVar` members #1380
- [ ] `type[SomeProtocol]` #903
- [ ] `issubclass()` on protocols with non-methods #1878
## Type narrowing
[Official documentation](https://typing.python.org/en/latest/spec/narrowing.html)
**tests:** [`narrow/`](https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/resources/mdtest/narrow/), [`type_guards.md`](https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/resources/mdtest/narrow/type_guards.md)
- [x] `isinstance()` / `issubclass()` narrowing
- [x] `is None` / `is not None` narrowing
- [x] `is` / `is not` identity narrowing
- [x] Truthiness narrowing
- [x] `assert` narrowing
- [x] `match` statement narrowing
- [x] `hasattr()` narrowing
- [x] `callable()` narrowing
- [x] Assignment narrowing
- [x] `TypeIs[…]` user-defined type guards
- [ ] `TypeGuard[…]` user-defined type guards #117
- [ ] `TypeIs`/`TypeGuard` as method #1569
- [ ] Tuple length checks #560
- [ ] Tuple match case narrowing #561
## Tuples
[Official documentation](https://typing.python.org/en/latest/spec/tuples.html)
**tests:** [`subscript/tuple.md`](https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/resources/mdtest/subscript/tuple.md), [`comparison/tuples.md`](https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/resources/mdtest/comparison/tuples.md), [`binary/tuples.md`](https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/resources/mdtest/binary/tuples.md)
- [x] `tuple[X, Y, Z]` heterogeneous tuples
- [x] `tuple[X, ...]` homogeneous tuples
- [x] `tuple[()]` empty tuple
- [x] Mixed tuples (`tuple[X, *tuple[Y, ...]]`)
- [x] Indexing with literal integers
- [x] Diagnostic: index out of bounds
- [x] Slicing tuples
- [x] Tuple subclasses
- [x] `typing.Tuple` (deprecated alias)
- [x] Covariant element types
- [x] Tuple inheritance
- [x] Unpacking in assignments
- [x] `*args` unpacking in calls
- [ ] Diagnostic: invalid comparisons for non-fixed-length tuples #1741
- [ ] `TypeVarTuple` / `Unpack` #156
## `NamedTuple`
[Official documentation](https://typing.python.org/en/latest/spec/namedtuples.html)
**tests:** [`named_tuple.md`](https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/resources/mdtest/named_tuple.md)
- [x] Class syntax (`class Foo(NamedTuple): ...`)
- [x] Field access by name and index, slicing, unpacking
- [x] Default values, diagnostic for non-default after default
- [x] Read-only fields (assignment rejected)
- [x] Inheritance, generic `NamedTuple`s
- [x] Multiple inheritance restriction
- [x] Underscore field name restriction
- [x] Prohibited attribute override check (`_asdict`, `_make`, …)
- [x] `_fields`, `_field_defaults`, `_make`, `_asdict`, `_replace`
- [x] Subtype of `tuple[...]`
- [x] `super()` restriction in `NamedTuple` methods
- [x] `NamedTuple` in type expressions
- [x] `type[NamedTuple]` in type expressions
- [ ] Not fully supported
- [ ] Functional syntax (`NamedTuple("Foo", [...])`) #1049
- [ ] `collections.namedtuple`: not tested
- [ ] Subclass field conflicting with base class field: not tested
## `TypedDict`
[Official documentation](https://typing.python.org/en/latest/spec/typeddict.html)
**tests:** [`typed_dict.md`](https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/resources/mdtest/typed_dict.md)
- [x] Class syntax (`class Foo(TypedDict): ...`)
- [x] Key access by literal string, `Final` constants
- [x] Constructor validation (missing keys, invalid types)
- [x] `total` parameter
- [x] `Required[…]`, `NotRequired[…]`
- [x] `ReadOnly[…]`
- [x] Inheritance, generic `TypedDict`s
- [x] Recursive `TypedDict`
- [x] Structural assignability and equivalence
- [x] Methods (`get`, `pop`, `setdefault`, `keys`, `values`, `copy`)
- [x] `__total__`, `__required_keys__`, `__optional_keys__`
- [ ] Functional syntax (`TypedDict("Foo", {...})`) #154
- [ ] `closed`, `extra_items` (PEP 728) #154
- [ ] `Unpack` for `**kwargs` typing #1746
- [ ] Tagged union narrowing #1479
- [ ] Diagnostic: Invalid `isinstance()` check on `TypedDict`: not tested
## Enums
[Official documentation](https://typing.python.org/en/latest/spec/enums.html)
**tests:** [`enums.md`](https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/resources/mdtest/enums.md), [`comparison/enums.md`](https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/resources/mdtest/comparison/enums.md)
- [x] `Enum`, `IntEnum`, `StrEnum`
- [x] `Literal[EnumMember]` types
- [x] `.name`, `.value` inference
- [x] `auto()` value inference
- [x] `member()`, `nonmember()`
- [x] Enum aliases
- [x] `_ignore_` attribute
- [ ] List form not fully supported
- [x] Implicitly final (subclassing restriction)
- [x] Exhaustiveness checking (`if`/`match`)
- [x] Custom `__eq__`/`__ne__` methods
- [x] Iteration over enum members
- [ ] `list(Enum)` returns `list[Unknown]`
- [ ] Functional syntax (`Enum("Name", [...])`) #876
- [ ] `enum.Flag` expansion handling #876
- [ ] Custom `__new__` or `__init__` methods #876
- [ ] `_generate_next_value_` support #876
- [ ] Value-based member retrieval (`Color("red")`) #876
- [ ] Narrowing with custom `__eq__` in `match` #1454
## Literals
[Official documentation](https://typing.python.org/en/latest/spec/literal.html)
**tests:** [`literal.md`](https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/resources/mdtest/annotations/literal.md), [`literal_string.md`](https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/resources/mdtest/annotations/literal_string.md)
- [x] `Literal[0]` (integer literals)
- [x] `Literal["a"]` (string literals)
- [x] `Literal[b"a"]` (bytes literals)
- [x] `Literal[True]` (boolean literals)
- [x] `Literal[Color.RED]` (enum literals)
- [x] `Literal[None]`
- [x] Nested `Literal` flattening
- [x] Union of literals simplification
- [x] `Literal` with type aliases
- [x] Invalid form diagnostics
- [x] `LiteralString`
- [x] `LiteralString` assignability
- [x] `LiteralString` narrowing
- [x] `LiteralString` cannot be parameterized
- [x] `LiteralString` cannot be subclassed
## Callables
[Official documentation](https://typing.python.org/en/latest/spec/callables.html)
**tests:** [`callable.md`](https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/resources/mdtest/annotations/callable.md), [`callable_instance.md`](https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/resources/mdtest/call/callable_instance.md)
- [x] `Callable[[X, Y], R]` syntax
- [x] `Callable[..., R]` gradual form
- [x] `Callable` with `ParamSpec`
- [x] Callback protocols (`__call__` method)
- [x] Callable assignability (contra/covariance)
- [x] Nested `Callable` types
- [x] `Callable` in unions/intersections
- [x] Invalid form diagnostics
- [ ] `Concatenate` #1535
- [ ] `Unpack` for `**kwargs` typing #1746
## Overloads
[Official documentation](https://typing.python.org/en/latest/spec/overload.html)
**tests:** [`overloads.md`](https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/resources/mdtest/overloads.md), [`call/overloads.md`](https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/resources/mdtest/call/overloads.md)
- [x] `@overload` decorator
- [x] Overload resolution
- [x] Generic overloads
- [x] Methods, constructors, `@staticmethod`, `@classmethod`
- [x] Version-specific overloads
- [x] Diagnostic: at least two overloads required
- [x] Diagnostic: missing implementation (non-stub)
- [x] Diagnostic: inconsistent decorators
- [x] Diagnostic: `@final`/`@override` placement
- [ ] Variadic parameters with generics #1825
- [ ] Unannotated implementation validation: not tested #1232
- [ ] Diagnostic: overlapping overloads #103
- [ ] Implementation consistency check #109
- [ ] `@overload` with other decorators #1675
## Dataclasses
[Official documentation](https://typing.python.org/en/latest/spec/dataclasses.html)
**tests:** [`dataclasses.md`](https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/resources/mdtest/dataclasses/dataclasses.md), [`fields.md`](https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/resources/mdtest/dataclasses/fields.md)
- [x] `@dataclass` decorator (`init`, `repr`, `eq`, `order`, `frozen`, `match_args`, `kw_only`, `slots`, `weakref_slot`, `unsafe_hash`)
- [x] `field()` (`default`, `default_factory`, `init`, `kw_only`, `doc`, `repr`, `hash`, `compare`)
- [x] `InitVar[…]`, `ClassVar[…]` exclusion, `KW_ONLY` sentinel
- [x] `fields()`, `__dataclass_fields__`
- [x] `Final` fields
- [x] Inheritance, generic dataclasses, descriptor-typed fields
- [x] `replace()`, `__replace__`
- [ ] `replace()` returns `Unknown`
- [x] `asdict()`
- [ ] Incorrectly accepts class objects
- [x] Diagnostic: frozen/non-frozen dataclass inheritance
- [ ] Diagnostic: non-default field after default field #111
- [ ] Diagnostic: `order=True` with custom comparison methods #111
- [ ] Diagnostic: `frozen=True` with `__setattr__`/`__delattr__` #111
- [ ] `__post_init__` signature validation #111
- [ ] Diagnostic: unsound subclassing of `order=True` dataclasses #1681
- [ ] `astuple()`: not tested
- [ ] `make_dataclass()`, `is_dataclass()`: not tested
## `dataclass_transform`
[Official documentation](https://typing.python.org/en/latest/spec/dataclasses.html#dataclass-transform)
**tests:** [`dataclass_transform.md`](https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/resources/mdtest/dataclasses/dataclass_transform.md)
- [x] Function-based transformers (decorator functions)
- [x] Metaclass-based transformers
- [x] Base-class-based transformers (`__init_subclass__`)
- [x] `eq_default` parameter
- [x] `order_default` parameter
- [x] `kw_only_default` parameter
- [x] `frozen_default` parameter
- [ ] Metaclass override not working
- [x] `field_specifiers` (`init`, `default`, `default_factory`, `factory`, `kw_only`, `alias`)
- [ ] `converter` parameter #1327
- [x] Other dataclass parameters (`slots`, etc.)
- [x] Overloaded dataclass-like decorators
- [x] Nested dataclass-transformers
- [x] Combining with `@dataclass` (Home Assistant pattern)
## Constructors
[Official documentation](https://typing.python.org/en/latest/spec/constructors.html)
**tests:** [`constructor.md`](https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/resources/mdtest/call/constructor.md)
- [x] `__init__` signature inference
- [x] `__new__` signature inference
- [x] Constructor inheritance from superclass
- [x] Both `__new__` and `__init__` present
- [x] Descriptor-based `__new__`/`__init__`
- [x] Generic class constructor inference
- [x] Type variable solving from constructor params
- [ ] Custom `__new__` return type #281
- [ ] Custom metaclass `__call__`
- [ ] `__new__`/`__init__` consistency validation
- [ ] Diagnostic: explicit `__init__` on instance #1016
## Type aliases
[Official documentation](https://typing.python.org/en/latest/spec/aliases.html)
**tests:** [`pep695_type_aliases.md`](https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/resources/mdtest/pep695_type_aliases.md), [`pep613_type_aliases.md`](https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/resources/mdtest/pep613_type_aliases.md), [`implicit_type_aliases.md`](https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/resources/mdtest/implicit_type_aliases.md)
- [x] Implicit type aliases (`Alias = int`)
- [x] PEP 613 `TypeAlias` annotation
- [ ] Fully stringified RHS not supported
- [x] PEP 695 `type` statement
- [x] Generic type aliases (PEP 695)
- [ ] Limitations #1851
- [x] Generic implicit/PEP 613 aliases
- [ ] Partial support #1739
- [x] `TypeAliasType` introspection (`__name__`, `__value__`)
- [ ] Self-referential generic aliases #1738
## Type checker directives
[Official documentation](https://typing.python.org/en/latest/spec/directives.html)
**tests:** [`directives/`](https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/resources/mdtest/directives/)
- [x] `cast(T, value)`
- [x] Redundant `cast` diagnostic
- [x] `assert_type(value, T)`
- [x] `assert_never(value)`
- [x] `reveal_type(value)`
- [x] `TYPE_CHECKING` constant
- [x] `@no_type_check` decorator
- [x] `type: ignore` comments
- [x] `ty: ignore` comments
- [x] `@deprecated` decorator
- [x] `@override` decorator
- [ ] Diagnostic: override without `@override` decorator #155
## Module resolution, imports, packages
[Official documentation](https://typing.python.org/en/latest/spec/distributing.html)
**tests:** [`import/`](https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/resources/mdtest/import/)
- [x] Stub files (`.pyi`)
- [x] Stub packages (`<package>-stubs`)
- [x] Partial stub packages (`py.typed` with `partial`)
- [x] Namespace packages (PEP 420)
- [x] Relative imports
- [x] `__all__` declarations
- [x] `__all__` mutations (`.append`, `.extend`, `+=`)
- [x] `__all__` with submodule `__all__`
- [x] Wildcard (`*`) imports
- [x] Wildcard imports in stubs re-export
- [x] Re-export conventions (`import X as X`)
- [x] Conditional re-exports in stub files
- [x] Reachability constraints in imports
- [x] Cyclic imports
- [x] `py.typed` marker files
- [x] `conftest.py` resolution (pytest)
- [x] conda/pixi environment support
- [ ] PEP 723 inline script metadata #691
- [ ] Custom builtins (`__builtins__.pyi`) #374
- [ ] Mono-repository support #819
- [ ] Compiled extensions (`.so` files) #487
- [ ] Per-library import suppression #1354
## Control flow analysis
**tests:** [`terminal_statements.md`](https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/resources/mdtest/terminal_statements.md), [`exhaustiveness_checking.md`](https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/resources/mdtest/exhaustiveness_checking.md), [`unreachable.md`](https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/resources/mdtest/unreachable.md), [`exception/control_flow.md`](https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/resources/mdtest/exception/control_flow.md)
- [x] Terminal statements (`return`, `raise`)
- [x] Loop control flow (`break`, `continue`)
- [x] `for`/`while` loop analysis
- [x] `try`/`except`/`else`/`finally` control flow
- [ ] `finally` limitations #233
- [x] `Never`/`NoReturn` function propagation
- [x] Exhaustiveness checking (`if`/`elif`/`else`)
- [x] Exhaustiveness checking (`match`)
- [ ] Advanced `match` pattern inference #887
- [x] `assert_never()`
- [x] `sys.version_info` comparisons
- [x] `sys.platform` checks
- [x] Statically known branches
- [ ] Return type inference #128
- [ ] Walrus operator in boolean expressions #626
- [ ] Cyclic control flow (loop back edges) #232
- [ ] Gray out unreachable code #784
## Invalid overrides
(Liskov Substitution Principle checks)
**tests:** [`liskov.md`](https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/resources/mdtest/liskov.md), [`override.md`](https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/resources/mdtest/override.md)
- [x] Covariant return types
- [x] Contravariant parameter types
- [x] Invariant mutable attributes
- [x] Full class hierarchy checked
- [x] Positional/keyword parameter kind changes
- [x] Additional optional parameters
- [x] `*args`/`**kwargs` compatibility
- [x] `@staticmethod` and `@classmethod` overrides
- [x] Synthesized method overrides (dataclasses)
- [ ] Method overridden by non-method
- [ ] Non-method overridden by non-method
## Abstract base classes
**tests:** [`return_type.md`](https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/resources/mdtest/function/return_type.md), [`overloads.md`](https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/resources/mdtest/overloads.md)
- [x] `@abstractmethod` decorator
- [x] Empty body allowed for abstract methods
- [x] `@abstractmethod` with `@overload` validation
- [ ] Diagnostic: instantiating abstract class #1877
## `__slots__`
**tests:** [`instance_layout_conflict.md`](https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/resources/mdtest/instance_layout_conflict.md)
- [x] `__slots__` (string or tuple of strings)
- [ ] `__slots__` (list, dict, set literals)
- [ ] Attribute resolution from `__slots__` #1268
- [ ] Diagnostic: access outside `__slots__` #1268
- [ ] Diagnostic: class variable shadowing `__slots__` name #1268
- [ ] `__dict__`/`__weakref__` presence validation #1268
- [ ] Diagnostic: non-empty `__slots__` on builtin subclasses #1268
## Special library features
Standard library:
- [ ] `@cached_property` #1446
- [ ] `functools.partial` #1536
- [ ] `functools.total_ordering` #1202
Third-party library support (currently not decided how far we want to go here):
- [ ] Pydantic #291
- [ ] Django #291
- [ ] `attrs` #291

View File

@ -1,272 +0,0 @@
# Typing FAQ
This page answers some commonly asked questions about ty and Python's type system.
## Why does ty report an error on my code?
Check the [documentation](https://docs.astral.sh/ty/reference/rules/) for the specific error code
you are seeing; it may explain the problem.
## What is the `Unknown` type and when does it appear?
`Unknown` is ty's way of representing a type that could not be fully inferred. It behaves the same
way as `Any`, but appears implicitly, rather than through an explicit `Any` annotation:
```py
from missing_module import MissingClass # error: unresolved-import
reveal_type(MissingClass) # Unknown
```
ty also uses unions with `Unknown` to maintain the
[gradual guarantee](../features/type-system.md#gradual-guarantee), which helps avoid false positive
errors in untyped code while still providing useful type information where possible.
For example, consider the following untyped `Message` class (which could come from a third-party
dependency that you have no control over). ty treats the `data` attribute as having type
`Unknown | None`, since there is no type annotation that restricts it further. The `Unknown` in the
union allows ty to avoid raising errors on the `msg.data = …` assignment. On the other hand, the
`None` in the union reflects the fact that `data` *could* possibly be `None`, and requires code that
uses `msg.data` to handle that case explicitly.
```py
class Message:
data = None
def __init__(self, title):
self.title = title
def receive(msg: Message):
reveal_type(msg.data) # Unknown | None
msg = Message("Favorite color")
msg.data = {"color": "blue"}
```
([Full example in the playground](https://play.ty.dev/862941a8-a3f6-4818-9ea1-d9d59b0bd2fa))
## Why does ty show `int | float` when I annotate something as `float`?
The [Python typing specification](https://typing.python.org/en/latest/spec/special-types.html)
includes a special rule for numeric types where an `int` can be used wherever a `float` is expected:
```py
def circle_area(radius: float) -> float:
return 3.14 * radius * radius
circle_area(2) # OK: int is allowed where float is expected
```
This rule is a special case, since `int` is not actually a subclass of `float`. To support this, ty
treats `float` annotations as meaning `int | float`. Unlike some other type checkers, ty makes this
behavior explicit in type hints and error messages. For example, if you
[hover over the `radius` parameter](https://play.ty.dev/fdc144c6-031c-4af9-b520-a4c6ccde9261), ty
will show `int | float`.
A similar rule applies to `complex`, which is treated as `int | float | complex`.
!!! info
These special rules for `float` and `complex` exist for a reason. In almost all cases, you
probably want to accept both `int` and `float` when you annotate something as `float`.
If you really need to accept *only* `float` and not `int`, you can use ty's `JustFloat`
type. At the time of writing, this import needs to be guarded by a `TYPE_CHECKING` block:
```py
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from ty_extensions import JustFloat
else:
JustFloat = float
def only_actual_floats_allowed(f: JustFloat) -> None: ...
only_actual_floats_allowed(1.0) # OK
only_actual_floats_allowed(1) # error: invalid-argument-type
```
([Full example in the playground](https://play.ty.dev/fb034780-3ba7-4c6a-9449-5b0f44128bab))
If you need this for `complex`, you can use `ty_extensions.JustComplex` in a similar way.
## Why does ty say `Callable` has no attribute `__name__`?
When you access `__name__`, `__qualname__`, `__module__`, or `__doc__` on a value typed as `Callable`,
ty reports an `unresolved-attribute` error. This is because not all callables have these attributes.
Functions do (including lambdas), but other callable objects do not. The `FileUpload` class below, for
example, is callable, but instances of `FileUpload` do not have a `__name__` attribute. Passing a
`FileUpload` instance to `retry` would lead to an `AttributeError` at runtime.
```py
from typing import Callable
def retry(times: int, operation: Callable[[], bool]) -> bool:
for i in range(times):
# WRONG: `operation` does not necessarily have a `__name__` attribute
print(f"Calling {operation.__name__}, attempt {i + 1} of {times}")
if operation():
return True
return False
class FileUpload:
def __init__(self, name: str) -> None:
# …
def __call__(self) -> bool:
# …
retry(3, FileUpload("image.png"))
```
To fix this, you could use `getattr` with a fall back to a default name when the
attribute is not present (or use a `hasattr(…, "__name__")` check if you access
it multiple times):
```py
name = getattr(operation, "__name__", "operation")
```
Alternatively, you could use an `isinstance(…, types.FunctionType)` check to narrow the type of
`operation` to something that definitely has a `__name__` attribute:
```py
if isinstance(operation, FunctionType):
print(f"Calling {operation.__name__}, attempt {i + 1} of {times}")
else:
print(f"Calling operation, attempt {i + 1} of {times}")
```
You can try various approaches in [this playground example](https://play.ty.dev/f6f7f35a-47c3-423d-be8d-33d03c61d40c).
See also [this discussion](https://github.com/astral-sh/ty/issues/1495) for some plans to improve
the developer experience around this in the future.
!!! info
ty has first-class support for intersection types. If you only want to accept function-like
callables, you could define `FunctionLikeCallable` as an intersection of `Callable` and
`types.FunctionType`:
```py
from typing import Callable, TYPE_CHECKING
from types import FunctionType
if TYPE_CHECKING:
from ty_extensions import Intersection
type FunctionLikeCallable[**P, R] = Intersection[Callable[P, R], FunctionType]
else:
FunctionLikeCallable = Callable
def retry(times: int, operation: FunctionLikeCallable[[], bool]) -> bool:
...
```
You can check out the full example [here](https://play.ty.dev/7a1ea4ab-04e1-4271-adf5-ddc3a5d2fcfd),
which demonstrates that `FileUpload` instances are no longer accepted by `retry`.
## Does ty have a strict mode?
Not yet. A stricter inference mode is tracked in
[this issue](https://github.com/astral-sh/ty/issues/1240). In the meantime, you can consider using Ruff's
[`flake8-annotations` rules](https://docs.astral.sh/ruff/rules/#flake8-annotations-ann) to enforce
more explicit type annotations in your code.
## Why can't ty resolve my imports?
Import resolution issues are often caused by a missing or incorrect environment configuration. When
ty reports *"Cannot resolve imported module …"*, check the following:
1. **Virtual environment**: Make sure your virtual environment is discoverable. ty looks for an
active virtual environment via `VIRTUAL_ENV` or a `.venv` directory in your project root. See the
[module discovery](../modules.md#python-environment) documentation for more details.
1. **Project structure**: If your source code is not in the project root or `src/` directory,
configure [`environment.root`](./configuration.md#root) in your `pyproject.toml`:
```toml
[tool.ty.environment]
root = ["./app"]
```
1. **Third-party packages**: Ensure dependencies are installed in your virtual environment. Run ty
with `-v` to see the search paths being used.
1. **Compiled extensions**: ty requires `.py` or `.pyi` files for type information. If a package
contains only compiled extensions (`.so` or `.pyd` files), you'll need stub files (`.pyi`) for ty
to understand the types. See also [this issue](https://github.com/astral-sh/ty/issues/487) which
tracks improvements in this area.
## Does ty support monorepos?
ty can work with monorepos, but automatic discovery of nested projects is limited. By default, ty
uses the current working directory or the `--project` option to determine the project root.
For monorepos with multiple Python packages, you have a few options:
1. **Run ty per-package**: Run `ty check` from each package directory, or use `--project` to specify
the package:
```bash
ty check --project packages/package-a
ty check --project packages/package-b
```
1. **Configure multiple source roots**: Use [`environment.root`](./configuration.md#root) to specify
multiple source directories:
```toml
[tool.ty.environment]
root = ["packages/package-a", "packages/package-b"]
```
This has the disadvantage of treating all packages as a single project, which may lead to cases
in which ty thinks something is importable when it wouldn't be at runtime.
You can follow [this issue](https://github.com/astral-sh/ty/issues/819) to get updates on this
topic.
## Does ty support PEP 723 inline-metadata scripts?
It depends on what you want to do. If you have a single inline-metadata script, you can type check
it with ty by using uv's `--with-requirements` flag to install the dependencies specified in the
script header:
```bash
uvx --with-requirements script.py ty check script.py
```
If you have multiple scripts in your workspace, ty does not yet recognize that they have different
dependencies based on their inline metadata.
You can follow [this issue](https://github.com/astral-sh/ty/issues/691) for updates.
## Is there a pre-commit hook for ty?
Not yet. You can track progress in [this issue](https://github.com/astral-sh/ty/issues/269), which
also includes some suggested manual hooks you can use in the meantime.
## Does ty support (mypy) plugins?
No. ty does not have a plugin system and there is currently no plan to add one.
We prefer extending the type system with well-specified features rather than relying on
type-checker-specific plugins. That said, we are considering adding support for popular third-party
libraries like pydantic, SQLAlchemy, attrs, or django directly into ty.
## What is `Top[list[Unknown]]`, and why does it appear?
This type represents "all possible lists of any element type" (as opposed to `list[Unknown]`, which
represents "a list of some unknown element type"). It usually arises from a check such as
`if isinstance(x, list):`. If `x` was previously of type `Item | list[Item]`, you might expect this
check to narrow the type to `list[Item]`, but ty respects the possibility that there could be a
common subclass of both `Item` and `list` (which may not be a list of `Item`!), and so the narrowed
type is instead `(Item & Top[list[Unknown]]) | list[Item]`. This code can be made more robust by
instead checking `if instance(x, Item)`, or by declaring the `Item` type as `@typing.final`.
See also the [discussion
here](https://docs.astral.sh/ty/features/type-system/#top-and-bottom-materializations) and [in this
issue](https://github.com/astral-sh/ty/issues/1578).

View File

@ -6,7 +6,7 @@ specific pattern and can be turned on or off depending on your projects needs
!!! tip
See the [rules reference](./reference/rules.md) for an enumeration of all supported rules.
See [rules](./reference/rules.md) for an enumeration of all supported rules.
## Rule levels
@ -35,7 +35,7 @@ Rule levels can also be changed in the [`rules`](./reference/configuration.md#ru
For example, the following is equivalent to the command above:
```toml title="pyproject.toml"
```toml
[tool.ty.rules]
unused-ignore-comment = "warn"
redundant-cast = "ignore"

View File

@ -19,18 +19,18 @@ Rule violations spanning multiple lines can be suppressed by adding the comment
violation's first or last line:
```py
def sum_three_numbers(a: int, b: int, c: int) -> int: ...
def add_three(a: int, b: int, c: int): ...
# on the first line
sum_three_numbers( # ty: ignore[missing-argument]
add_three( # ty: ignore[missing-argument]
3,
2
)
# or, on the last line
sum_three_numbers(
add_three(
3,
2
) # ty: ignore[missing-argument]
@ -39,7 +39,7 @@ sum_three_numbers(
To suppress multiple violations on a single line, enumerate each rule separated by a comma:
```python
sum_three_numbers("one", 5) # ty: ignore[missing-argument, invalid-argument-type]
add_three("one", 5) # ty: ignore[missing-argument, invalid-argument-type]
```
!!! note
@ -49,7 +49,7 @@ sum_three_numbers("one", 5) # ty: ignore[missing-argument, invalid-argument-typ
## Standard suppression comments
ty supports the standard [`type: ignore`](https://typing.python.org/en/latest/spec/directives.html#type-ignore-comments) comment
ty supports the standard [`type:ignore`](https://typing.python.org/en/latest/spec/directives.html#type-ignore-comments) comment
format introduced by PEP 484.
ty handles these similarly to `ty: ignore` comments, but suppresses all violations on that line,
@ -57,7 +57,7 @@ even when `type: ignore[code]` is used.
```python
# Ignore all typing errors on the next line
sum_three_numbers("one", 5) # type: ignore
add_three("one", 5) # type: ignore
```
## Multiple suppressions comments
@ -91,12 +91,12 @@ to suppress all violations inside a function.
```python
from typing import no_type_check
def sum_three_numbers(a: int, b: int, c: int) -> int:
return a + b + c
def add_three(a: int, b: int, c: int):
a + b + c
@no_type_check
def main():
sum_three_numbers(1, 2) # no error for the missing argument
add_three(3, 4)
```
Decorating a class with `@no_type_check` isn't supported.

View File

@ -1,67 +0,0 @@
# Type checking
After [installing ty](./installation.md), it's time to type check some code!
## Running the type checker
To run the type checker, use the `check` command:
```shell
ty check
```
!!! tip
If you're in a project, you may need to use `uv run` or activate your virtual environment first
for ty to find your dependencies.
## Environment discovery
The type checker needs to discover your installed packages in order to check your use of imported
dependencies.
ty will find installed packages in the active virtual environment (via `VIRTUAL_ENV`) or discover a
virtual environment named `.venv` in the project root or working directory. It will not find
packages in non-virtual environments without specifying the target path with `--python`.
See the [module discovery](./modules.md) documentation for details.
## File selection
ty will run on all Python files in the working directory (including subdirectories, recursively).
If used from a project, ty will run on all Python files in the project (starting in the directory
with the `pyproject.toml`).
You can also provide specific paths to check:
```shell
ty check example.py
```
You can also persistently configure [included and excluded files](./exclusions.md).
## Rule selection and severity
ty's type checking diagnostics are often associated with a rule.
ty's type checking rules can be configured to your project's needs. See the [rules](./rules.md)
documentation for details.
You can also suppress specific violations of rules using [suppression comments](./suppression.md).
## Watch mode
ty can be run in an incremental watch mode:
```shell
ty check --watch
```
ty will watch files for changes and recheck any affected files — including files that depend on the
changed file. ty uses [fine-grained incrementality](./features/language-server.md#fine-grained-incrementality)
to perform subsequent checks much faster than running `ty check` repeatedly.
## The type system
To learn more about what makes type checking in ty unique, read about the
[type system](./features/type-system.md).

View File

@ -81,30 +81,24 @@ extra:
- icon: fontawesome/brands/x-twitter
link: https://x.com/astral_sh
nav:
- Introduction: index.md
- Guides:
- Installation: installation.md
- Type checking: type-checking.md
- Editor integration: editors.md
- Getting started: index.md
- Concepts:
- Installation: installation.md
- Configuration: configuration.md
- Module discovery: modules.md
- Python version: python-version.md
- File exclusions: exclusions.md
- Rules: rules.md
- Suppression: suppression.md
- Features:
- Type system: features/type-system.md
- Diagnostics: features/diagnostics.md
- Language server: features/language-server.md
- Editors: editors.md
- Reference:
- Configuration: reference/configuration.md
- Typing FAQ: reference/typing-faq.md
- Rules: reference/rules.md
- CLI: reference/cli.md
- Exit codes: reference/exit-codes.md
- Environment variables: reference/environment.md
- Editor settings: reference/editor-settings.md
- Type system features: reference/type-system-features.md
validation:
omitted_files: warn
absolute_links: warn

View File

@ -1,6 +1,6 @@
[project]
name = "ty"
version = "0.0.8"
version = "0.0.1a34"
requires-python = ">=3.8"
dependencies = []
description = "An extremely fast Python type checker, written in Rust."
@ -8,7 +8,7 @@ readme = "README.md"
authors = [{ name = "Astral Software Inc.", email = "hey@astral.sh" }]
keywords = ["ty", "typing", "analysis", "check"]
classifiers = [
"Development Status :: 4 - Beta",
"Development Status :: 3 - Alpha",
"Environment :: Console",
"Intended Audience :: Developers",
"Operating System :: OS Independent",
@ -102,7 +102,6 @@ include = [
version-files = [
"pyproject.toml",
{ path = "dist-workspace.toml", field = "workspace.version", format = "cargo" },
"docs/installation.md",
]
submodules = ["ruff"]
require-labels = [{ submodule = "ruff", labels = ["ty"] }]
@ -118,6 +117,7 @@ changelog-ignore-authors = ["github-actions"]
major-labels = [] # We do not use the major version number yet
minor-labels = [] # We do not use the minor version number yet
version-format = "cargo"
default-bump-type = "pre"
trim-title-prefixes = ["[ty]"]
[tool.rooster.section-labels]

2
ruff

@ -1 +1 @@
Subproject commit e71fd9c0408dbedff0c80b6855c5612c82091f59
Subproject commit 90b29c9e87bc5bbe12df43bad74f368b84b90427

View File

@ -25,13 +25,6 @@ def main() -> None:
content = Path("README.md").read_text(encoding="utf8")
# Replace relative src="./..." attributes with absolute GitHub raw URLs.
def replace_src(match: re.Match) -> str:
path = match.group(1).lstrip("./")
return f'src="https://raw.githubusercontent.com/astral-sh/ty/{version}/{path}"'
content = re.sub(r'src="(\./[^"]+)"', replace_src, content)
# Replace any relative URLs (e.g., `[CONTRIBUTING.md`) with absolute URLs.
def replace(match: re.Match) -> str:
url = match.group(1)

View File

@ -165,7 +165,7 @@ def main() -> None:
if expected_ruff_revision != actual_ruff_revision:
print(
f"The ruff submodule is at {actual_ruff_revision} but main expects {expected_ruff_revision}"
f"The ruff submodule is at {expected_ruff_revision} but main expects {actual_ruff_revision}"
)
match input(
"How do you want to proceed (u=reset submodule, n=abort, y=continue)? "

View File

@ -624,7 +624,7 @@ wheels = [
[[package]]
name = "ty"
version = "0.0.8"
version = "0.0.1a34"
source = { editable = "." }
[package.dev-dependencies]