Skip to content

Add ty as type checker alongside pyright#20474

Open
LeonarddeR wants to merge 4 commits into
nvaccess:masterfrom
LeonarddeR:ty
Open

Add ty as type checker alongside pyright#20474
LeonarddeR wants to merge 4 commits into
nvaccess:masterfrom
LeonarddeR:ty

Conversation

@LeonarddeR

@LeonarddeR LeonarddeR commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator

Link to issue number:

Part of #19393

Summary of the issue:

NVDA type-checks with pyright, which is slow and bundles a Node.js runtime. Many pyright rules are disabled to suppress pre-existing violations, leaving those categories unprotected against new violations. In #19393 I proposed swapping pyright for ty (Astral, Rust-based: fast, no Node, gradual typing).

Description of user facing changes:

None.

Description of developer facing changes:

  • ty (0.0.57) added as a dev dependency and configured in pyproject.toml ([tool.ty]). The config only contains what deviates from ty's defaults (e.g. directories covered by ty's built-in excludes are not repeated).
  • New CI job "Check types with ty" (typeCheckTy, ci/scripts/tests/typeCheckTy.ps1) runs in parallel with the existing pyright job. The existing job and script are renamed to typeCheckPyright for symmetry. Both jobs gate allTestsPass, so ty failures block PRs.
  • runlint.bat now runs both pyright and ty.
  • ty added as a pre-commit hook (upstream astral-sh/ty-pre-commit, rev: v0.0.57, kept in sync with the pyproject pin). The upstream hook's always_run is overridden so commits without Python changes don't pay for a full ty check, and the hook is skipped on pre-commit.ci for the same reason as pyright (it needs the project .venv).
  • pyright is retained; this PR only adds ty.

Description of development approach:

ty's rule taxonomy differs entirely from pyright's, so the config was tuned empirically: rules that flood violations on the current codebase are set to "ignore" (each annotated with its count, analogous to the existing [tool.pyright] leniency), reaching a clean ty check with zero code changes. pyright removal is a planned follow-up once ty proves stable in CI.

Testing strategy:

  • uv run ty check exits 0 ("All checks passed!") on the codebase.
  • uv run pyright still exits 0 (its config is untouched).
  • Verified ty flags real errors on non-ignored rules (e.g. unresolved-reference), including in .pyw files discovered project-wide without an explicit include.
  • ty pre-commit hook runs and passes (uv run prek run ty --all-files); CI ty job added.
  • actionlint, check-yaml, check-toml and check-pre-commit-ci-config pass on the changed files.

Known issues with pull request:

  • The config sets ~24 error rules and 7 warning rules to "ignore" (annotated with counts, ~82 warnings total), matching the current pyright leniency rather than fixing the underlying issues.
  • Broad ignores (unresolved-attribute, not-subscriptable) likely hide some None-safety issues; a follow-up can progressively re-enable rules.
  • VS Code integration (ty extension + disabling pylance type-checking) lives in the vscode-nvda submodule and is a separate PR.

Code Review Checklist:

  • Documentation:
    • Change log entry
    • User Documentation
    • Developer / Technical Documentation
    • Context sensitive help for GUI changes
  • Testing:
    • Unit tests
    • System (end to end) tests
    • Manual testing
  • UX of all users considered:
    • Speech
    • Braille
    • Low Vision
    • Different web browsers
    • Localization in other languages / culture than English
  • API is compatible with existing add-ons.
  • Security precautions taken.

LeonarddeR and others added 3 commits July 9, 2026 22:17
- Drop [tool.ty.src] entries that duplicate ty's built-in defaults
  (.git, .tox, .venv, __pycache__) or are dead for ty (include,
  sconstruct/sconscript: ty only checks .py/.pyw files)
- Skip ty hook on pre-commit.ci (needs project .venv, like pyright)
  and on commits without Python changes (upstream hook sets always_run)
- Note that hook rev matches the ty version pinned in pyproject
- Gate allTestsPass on typeCheckTy; add permissions block to the job
- Rename typeCheck job and script to typeCheckPyright for symmetry
  with typeCheckTy

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The ty pre-commit hook needs the built comInterfaces COM stubs
(same as pyright), which the autofix job's plain checkout does not
generate. Without this it fails with spurious unresolved-reference
errors on wildcard-imported UIA constants. The dedicated typeCheckTy
job in testAndPublish.yml still runs it against the built cache.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@hwf1324

hwf1324 commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

ty v0.0.58 has been released. ty is updated frequently—what is our update strategy? Do we update promptly?

@LeonarddeR

Copy link
Copy Markdown
Collaborator Author

ty v0.0.58 has been released. ty is updated frequently—what is our update strategy? Do we update promptly?

Fair point. I think this has to be added with the regular update cadence, so when ruff/uv are updated.

@LeonarddeR LeonarddeR marked this pull request as ready for review July 10, 2026 16:24
@LeonarddeR LeonarddeR requested review from a team as code owners July 10, 2026 16:24

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces ty as an additional Python type checker alongside the existing pyright tooling, wiring it into NVDA’s dependency set, local lint script, pre-commit, CI, and developer documentation so ty can gate changes during an evaluation period.

Changes:

  • Add ty==0.0.57 to the lint dependency group and lockfile, and configure ty in pyproject.toml.
  • Add a dedicated CI job + script for ty check, and rename the existing pyright CI script/job for symmetry.
  • Run ty as part of runlint.bat and add a pre-commit hook for ty; update automated testing docs accordingly.

Reviewed changes

Copilot reviewed 7 out of 9 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
uv.lock Adds ty to the locked lint dependencies for Windows.
pyproject.toml Introduces [tool.ty] configuration and pins ty==0.0.57 in the lint group.
runlint.bat Runs ty check in addition to existing ruff + pyright steps.
ci/scripts/tests/typeCheckTy.ps1 New CI helper script to run ty and publish failures to the job summary.
ci/scripts/tests/typeCheckPyright.ps1 New/renamed CI helper script to run pyright and publish failures to the job summary.
.github/workflows/testAndPublish.yml Adds typeCheckTy job and renames the existing pyright type-check job; both gate allTestsPass.
.pre-commit-config.yaml Adds an upstream ty pre-commit hook and skips it on pre-commit.ci.
.github/workflows/autofix.yml Skips the new ty hook in autofix workflow’s lint gate.
projectDocs/testing/automated.md Documents that both pyright and ty are used and that runlint.bat runs both.

Comment thread runlint.bat
Comment on lines +30 to +34
if "%1" NEQ "" (
call uv run --group lint --directory "%here%" ty check > %1/ty-output.txt
) else (
call uv run --group lint --directory "%here%" ty check
)
Comment thread .pre-commit-config.yaml
Comment on lines +148 to +154
- id: ty
name: type check with ty
# The upstream hook sets always_run, making every commit
# (even ones without python changes) pay for a full ty check.
always_run: false
types: [python]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants