ty/docs
Dhruv Manilawala 2feba5eb22
Some checks are pending
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / Check generated files unedited (push) Waiting to run
Bump version to 0.0.1-alpha.9 (#634)
2025-06-11 11:05:43 +00:00
..
reference Bump version to 0.0.1-alpha.9 (#634) 2025-06-11 11:05:43 +00:00
README.md Update docs README for Python version inference from environment (#565) 2025-06-02 11:24:46 +00:00

ty

Installation | Usage | Module discovery | Editor integration | Rules | Suppressions | Exit codes | Reference

Getting started

For a quick guide on getting started, see the top-level README.

Installation

Adding ty to your project

Use uv (or your project manager of choice) to add ty as a 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:

uv run ty

Installing globally

Install ty globally with uv:

uv tool install ty@latest

Or, pipx:

pipx install ty

Installing with pip

Install ty into your current Python environment with pip:

pip install ty

Usage

Run ty check, in your project's top-level directory, to check the project for type errors using ty's default configuration.

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.

Module discovery

First-party modules

First-party modules are Python files that are part of your project source code.

By default, ty searches for first-party modules in the project's root directory or the src directory, if present.

If your project uses a different layout, configure the project's src.root in your pyproject.toml or ty.toml. For example, if your project's code is in an app/ directory:

example-pkg
├── README.md
├── pyproject.toml
└── app
    └── example_pkg
        └── __init__.py

then set src.root in your pyproject.toml to ./app:

[tool.ty.src]
root = "./app"

Third-party modules

Third-party modules are Python packages that are not part of your project or the standard library. These are usually declared as dependencies in a pyproject.toml or requirements.txt file and installed using a package manager like uv or pip. Examples of popular third-party modules are requests, numpy and django.

ty searches for third-party modules in the configured Python environment.

Python environment

The Python environment is used for discovery of third-party modules.

By default, ty will attempt to discover a virtual environment.

First, ty checks for an active virtual environment using the VIRTUAL_ENV environment variable. If not set, ty will search for a .venv directory in the project root or working directory. ty only supports discovery of virtual environments at this time.

Note

When using project management tools, such as uv or Poetry, the run command usually automatically activates the virtual environment and will be detected by ty.

The Python environment may be explicitly configured using the environment.python setting or --python flag.

When setting the environment explicitly, non-virtual environments can be provided.

Python version

The Python version affects allowed syntax, type definitions of the standard library, and type definitions of first- and third-party modules that are conditional on the Python version.

For example, Python 3.10 introduced support for match statements and added the sys.stdlib_module_names symbol to the standard library. Syntactic features always need to be available in the lowest supported Python version, but symbols may be used in a sys.version_info conditional branch:

import sys

# `invalid-syntax` error if `python-version` is set to 3.9 or lower:
match "echo hello".split():
    case ["echo", message]:
        print(message)
    case _:
        print("unknown command")

# `unresolved-attribute` error if `python-version` is set to 3.9 or lower:
print(sys.stdlib_module_names)

if sys.version_info >= (3, 10):
    # ok, because the usage is guarded by a version check:
    print(sys.stdlib_module_names)

By default, the lower bound of the project's requires-python field (from the pyproject.toml) is used as the target Python version, ensuring that features and symbols only available in newer Python versions are not used.

If the requires-python field is not available but a virtual environment has been configured or detected, ty will try to infer the Python version being used from the virtual 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.13).

The Python version may also be explicitly specified using the python-version setting or the --python-version flag.

Excluding files

By default, ty ignores files listed in an .ignore or .gitignore file.

To disable this functionality, set respect-ignore-files to false.

You may also explicitly pass the paths that ty should check, e.g.:

ty check src scripts/benchmark.py

We plan on adding dedicated options for including and excluding files in future releases.

Editor integration

ty can be integrated with various editors to provide a seamless development experience.

VS Code

The Astral team maintains an official VS Code extension.

Install the ty extension from the VS Code Marketplace.

See the extension's README for more details on usage.

Other editors

ty can be used with any editor that supports the language server protocol.

To start the language server, use the server subcommand:

ty server

Refer to your editor's documentation to learn how to connect to an LSP server.

See the editor settings for more details on configuring the language server.

Neovim

For Neovim 0.10 or earlier (with nvim-lspconfig):

require('lspconfig').ty.setup({
  init_options = {
    settings = {
      -- ty language server settings go here
    }
  }
})

For Neovim 0.11+ (with vim.lsp.config):

-- Optional: Only required if you need to update the language server settings
vim.lsp.config('ty', {
  init_options = {
    settings = {
      -- ty language server settings go here
    }
  }
})

-- Required: Enable the language server
vim.lsp.enable('ty')

Rules

Rules are individual checks that ty performs to detect common issues in your code, such as incompatible assignments, missing imports, or invalid type annotations. Each rule focuses on a specific pattern and can be turned on or off depending on your projects needs.

See rules for an enumeration of all supported rules.

Rule levels

Each rule has a configurable level:

  • error: violations are reported as errors and ty exits with an exit code of 1 if there's any.
  • warn: violations are reported as warnings. Depending on your configuration, ty exits with an exit code of 0 if there are only warning violations (default) or 1 when using --error-on-warning.
  • ignore: the rule is turned off

You can configure the level for each rule on the command line using the --warn, --error, and --ignore flags. For example:


ty check \
    --warn unused-ignore-comment \          # Make `unused-ignore-comment` a warning
    --ignore redundant-cast \               # Disable `redundant-cast`
    --error possibly-unbound-attribute \    # Error on `possibly-unbound-attribute`
    --error possibly-unbound-import         # Error on `possibly-unbound-import`

The options can be repeated. Subsequent options override earlier options.

Rule levels can also be changed in the rules section of a configuration file.

For example, the following is equivalent to the command above:

[tool.ty.rules]
unused-ignore-comment = "warn"
redundant-cast = "ignore"
possibly-unbound-attribute = "error"
possibly-unbound-import = "error"

Suppressions

Rules can also be ignored in specific locations in your code (instead of disabling the rule entirely) to silence false positives or permissible violations.

Note

To disable a rule entirely, set it to the ignore level as described in rule levels.

ty suppression comments

To suppress a rule violation inline add a # ty: ignore[<rule>] comment at the end of the line:

a = 10 + "test"  # ty: ignore[unsupported-operator]

Rule violations spanning multiple lines can be suppressed by adding the comment at the end of the violation's first or last line:

def add_three(a: int, b: int, c: int): ...

# on the first line

add_three(  # ty: ignore[missing-argument]
    3,
    2
)

# or, on the last line

add_three(
    3,
    2
)  # ty: ignore[missing-argument]

To suppress multiple violations on a single line, enumerate each rule separated by a comma:

add_three("one", 5)  # ty: ignore[missing-argument, invalid-argument-type]

Note

Enumerating rule names (e.g., [rule1, rule2]) is optional. However, we strongly recommend including suppressing specific rules to avoid accidental suppression of other errors.

Standard suppression comments

ty supports the standard type:ignore comment format introduced by PEP 484.

ty handles these similarly to ty: ignore comments, but suppresses all violations on that line, even when type: ignore[code] is used.

# Ignore all typing errors on the next line
add_three("one", 5)  # type: ignore

Unused suppression comments

If the unused-ignore-comment rule is enabled, ty will report unused ty: ignore and type: ignore comments.

unused-ignore-comment violations can only be suppressed using # ty: ignore[unused-ignore-comment]. They cannot be suppressed using # ty: ignore without a rule code or # type: ignore.

@no_type_check directive

ty supports the @no_type_check decorator to suppress all violations inside a function.

from typing import no_type_check

def add_three(a: int, b: int, c: int):
    a + b + c

@no_type_check
def main():
    add_three(3, 4)

Decorating a class with @no_type_check isn't supported.

Configuration

Configuration files

ty supports persistent configuration files at both the project- and user-level.

Specifically, ty will search for a pyproject.toml or ty.toml file in the current directory, or in the nearest parent directory.

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:

pyproject.toml:

[tool.ty.rules]
index-out-of-bounds = "ignore"

(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:

ty.toml:

[rules]
index-out-of-bounds = "ignore"

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.

ty will also discover user-level configuration at ~/.config/ty/ty.toml (or $XDG_CONFIG_HOME/ty/ty.toml) on macOS and Linux, or %APPDATA%\ty\ty.toml on Windows. User-level configuration must use the ty.toml format, rather than the pyproject.toml format, as a pyproject.toml is intended to define a Python project.

If project- and user-level configuration files are found, the settings will be merged, with project-level configuration taking precedence over the user-level configuration.

For example, if a string, number, or boolean is present in both the project- and user-level configuration tables, the project-level value will be used, and the user-level value will be ignored. If an array is present in both tables, the arrays will be merged, with the project-level settings appearing later in the merged array.

Settings provided via command line take precedence over persistent configuration.

See the configuration reference for an enumeration of the available settings.

Exit codes

  • 0 if no violations with severity error or higher were found.
  • 1 if any violations with severity error were found.
  • 2 if ty terminates abnormally due to invalid CLI options.
  • 101 if ty terminates abnormally due to an internal error.

ty supports two command line arguments that change how exit codes work:

  • --exit-zero: ty will exit with 0 even if violations were found.
  • --error-on-warning: ty will exit with 1 if it finds any violations with severity warning or higher.

Reference

For more details, see the reference documentation: