[
  {
    "path": ".editorconfig",
    "content": "# Check http://editorconfig.org for more information\n# This is the main config file for this project:\nroot = true\n\n[*]\ncharset = utf-8\ntrim_trailing_whitespace = true\nend_of_line = lf\nindent_style = space\ninsert_final_newline = true\nindent_size = 2\n\n[*.{rs,py,pyi,toml}]\nindent_size = 4\n\n[*.md]\nmax_line_length = 100\n"
  },
  {
    "path": ".gitattributes",
    "content": "* text=auto eol=lf\n\ndocs/reference/cli.md linguist-generated=true\ndocs/reference/configuration.md linguist-generated=true\ndocs/reference/rules.md linguist-generated=true\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/1_bug_report.yaml",
    "content": "name: Bug report\ndescription: Report an error or unexpected behavior\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        Thank you for taking the time to report an issue! We're glad to have you involved with ty.\n\n        **Before reporting, please make sure to search through [existing issues](https://github.com/astral-sh/ty/issues?q=is:issue+is:open+label:bug) (including [closed](https://github.com/astral-sh/ty/issues?q=is:issue%20state:closed%20label:bug)).**<br>\n        **In particular, check out the list of [frequently encountered problems](https://github.com/astral-sh/ty/issues/445).**\n\n  - type: textarea\n    attributes:\n      label: Summary\n      description: |\n        A clear and concise description of the bug, including a minimal reproducible example.\n\n        Be sure to include the command you invoked (e.g., `ty check`) and\n        the current ty settings (e.g., relevant sections from your `pyproject.toml`).\n\n        If possible, try to include the [playground](https://play.ty.dev) link that reproduces this issue.\n\n    validations:\n      required: true\n\n  - type: input\n    attributes:\n      label: Version\n      description: What version of ty are you using? (see `ty version`)\n      placeholder: e.g., ty 0.0.1 (ff9000864 2025-05-06)\n    validations:\n      required: false\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/2_question.yaml",
    "content": "name: Question\ndescription: Ask a question about ty\nlabels: [\"question\"]\nbody:\n  - type: textarea\n    attributes:\n      label: Question\n      description: Describe your question in detail.\n    validations:\n      required: true\n\n  - type: input\n    attributes:\n      label: Version\n      description: What version of ty are you using? (see `ty version`)\n      placeholder: e.g., ty 0.0.1 (ff9000864 2025-05-06)\n    validations:\n      required: false\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: true\ncontact_links:\n  - name: Documentation\n    url: https://github.com/astral-sh/ty/blob/main/README.md\n    about: Please consult the documentation before creating an issue.\n  - name: Community\n    url: https://discord.com/invite/astral-sh\n    about: Join our Discord community to ask questions and collaborate.\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "<!--\nThank you for contributing to ty! To help us out with reviewing, please consider the following:\n\n- Does this pull request include a summary of the change? (See below.)\n- Does this pull request include a descriptive title?\n- Does this pull request include references to any relevant issues?\n-->\n\n## Summary\n\n<!-- What's the purpose of the change? What does it do, and why? -->\n\n## Test Plan\n\n<!-- How was it tested? -->\n"
  },
  {
    "path": ".github/actionlint.yaml",
    "content": "# Configuration for the actionlint tool, which we run via prek\n# to verify the correctness of the syntax in our GitHub Actions workflows.\n\nself-hosted-runner:\n  # Various runners we use that aren't recognized out-of-the-box by actionlint:\n  labels:\n    - depot-ubuntu-latest-8\n    - depot-ubuntu-22.04-16\n    - depot-ubuntu-22.04-32\n    - github-windows-2025-x86_64-8\n    - github-windows-2025-x86_64-16\n"
  },
  {
    "path": ".github/renovate.json5",
    "content": "{\n  $schema: \"https://docs.renovatebot.com/renovate-schema.json\",\n  dependencyDashboard: true,\n  suppressNotifications: [\"prEditedNotification\"],\n  extends: [\"github>astral-sh/renovate-config\"],\n  labels: [\"internal\"],\n  schedule: [\"before 4am on Monday\"],\n  semanticCommits: \"disabled\",\n  separateMajorMinor: false,\n  prHourlyLimit: 10,\n  enabledManagers: [\"github-actions\", \"pre-commit\"],\n  \"pre-commit\": {\n    enabled: true,\n  },\n  packageRules: [\n    // Pin GitHub Actions to immutable SHAs.\n    {\n      matchDepTypes: [\"action\"],\n      pinDigests: true,\n    },\n    // Annotate GitHub Actions SHAs with a SemVer version.\n    {\n      extends: [\"helpers:pinGitHubActionDigests\"],\n      extractVersion: \"^(?<version>v?\\\\d+\\\\.\\\\d+\\\\.\\\\d+)$\",\n      versioning: \"regex:^v?(?<major>\\\\d+)(\\\\.(?<minor>\\\\d+)\\\\.(?<patch>\\\\d+))?$\",\n    },\n    {\n      // Group upload/download artifact updates, the versions are dependent\n      groupName: \"Artifact GitHub Actions dependencies\",\n      matchManagers: [\"github-actions\"],\n      matchDatasources: [\"gitea-tags\", \"github-tags\"],\n      matchPackageNames: [\"actions/upload-artifact\", \"actions/download-artifact\"],\n      description: \"Weekly update of artifact-related GitHub Actions dependencies\",\n    },\n    {\n      // This package rule disables updates for GitHub runners:\n      // we'd only pin them to a specific version\n      // if there was a deliberate reason to do so\n      groupName: \"GitHub runners\",\n      matchManagers: [\"github-actions\"],\n      matchDatasources: [\"github-runners\"],\n      description: \"Disable PRs updating GitHub runners (e.g. 'runs-on: macos-14')\",\n      enabled: false,\n    },\n    {\n      groupName: \"prek dependencies\",\n      matchManagers: [\"pre-commit\"],\n      description: \"Weekly update of prek dependencies\",\n    }\n  ],\n  vulnerabilityAlerts: {\n    commitMessageSuffix: \"\",\n    labels: [\"internal\", \"security\"],\n  },\n}\n"
  },
  {
    "path": ".github/workflows/build-binaries.yml",
    "content": "# Build ty on all platforms.\n#\n# Generates both wheels (for PyPI) and archived binaries (for GitHub releases).\n#\n# Assumed to run as a subworkflow of .github/workflows/release.yml; specifically, as a local\n# artifacts job within `cargo-dist`.\nname: \"Build binaries\"\n\non:\n  workflow_call:\n    inputs:\n      plan:\n        required: true\n        type: string\n  pull_request:\n    paths:\n      # When we change pyproject.toml, we want to ensure that the maturin builds still work.\n      - pyproject.toml\n      # And when we change this workflow itself...\n      - .github/workflows/build-binaries.yml\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\n\npermissions:\n  contents: read\n\nenv:\n  PACKAGE_NAME: ty\n  MODULE_NAME: ty\n  PYTHON_VERSION: \"3.13\"\n  CARGO_INCREMENTAL: 0\n  CARGO_NET_RETRY: 10\n  CARGO_TERM_COLOR: always\n  RUSTUP_MAX_RETRIES: 10\n\njobs:\n  sdist:\n    if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-build') }}\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n        with:\n          submodules: recursive\n          persist-credentials: false\n      - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0\n        with:\n          python-version: ${{ env.PYTHON_VERSION }}\n      - name: \"Prep README.md\"\n        run: python scripts/transform_readme.py\n      - name: \"Build sdist\"\n        uses: PyO3/maturin-action@04ac600d27cdf7a9a280dadf7147097c42b757ad # v1.50.1\n        with:\n          maturin-version: v1.11.5\n          command: sdist\n          args: --out dist\n      - name: \"Test sdist\"\n        run: |\n          pip install dist/\"${PACKAGE_NAME}\"-*.tar.gz --force-reinstall\n          \"${MODULE_NAME}\" version\n          \"${MODULE_NAME}\" --help\n          python -m \"${MODULE_NAME}\" --help\n      - name: \"Upload sdist\"\n        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0\n        with:\n          name: wheels-sdist\n          path: dist\n\n  macos-x86_64:\n    if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-build') }}\n    runs-on: macos-14\n    steps:\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n        with:\n          submodules: recursive\n          persist-credentials: false\n      - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0\n        with:\n          python-version: ${{ env.PYTHON_VERSION }}\n          architecture: x64\n      - name: \"Prep README.md\"\n        run: python scripts/transform_readme.py\n      - name: \"Build wheels - x86_64\"\n        uses: PyO3/maturin-action@04ac600d27cdf7a9a280dadf7147097c42b757ad # v1.50.1\n        with:\n          maturin-version: v1.11.5\n          target: x86_64\n          args: --release --locked --out dist --compatibility pypi\n      - name: \"Upload wheels\"\n        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0\n        with:\n          name: wheels-macos-x86_64\n          path: dist\n      - name: \"Archive binary\"\n        run: |\n          TARGET=x86_64-apple-darwin\n          ARCHIVE_NAME=ty-$TARGET\n          ARCHIVE_FILE=$ARCHIVE_NAME.tar.gz\n\n          mkdir -p $ARCHIVE_NAME\n          cp ruff/target/$TARGET/release/ty $ARCHIVE_NAME/ty\n          tar czvf $ARCHIVE_FILE $ARCHIVE_NAME\n          shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256\n      - name: \"Upload binary\"\n        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0\n        with:\n          name: artifacts-macos-x86_64\n          path: |\n            *.tar.gz\n            *.sha256\n\n  macos-aarch64:\n    if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-build') }}\n    runs-on: macos-14\n    steps:\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n        with:\n          submodules: recursive\n          persist-credentials: false\n      - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0\n        with:\n          python-version: ${{ env.PYTHON_VERSION }}\n          architecture: arm64\n      - name: \"Prep README.md\"\n        run: python scripts/transform_readme.py\n      - name: \"Build wheels - aarch64\"\n        uses: PyO3/maturin-action@04ac600d27cdf7a9a280dadf7147097c42b757ad # v1.50.1\n        with:\n          maturin-version: v1.11.5\n          target: aarch64\n          args: --release --locked --out dist --compatibility pypi\n      - name: \"Test wheel - aarch64\"\n        run: |\n          pip install dist/\"${PACKAGE_NAME}\"-*.whl --force-reinstall\n          ty --help\n          python -m ty --help\n      - name: \"Upload wheels\"\n        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0\n        with:\n          name: wheels-aarch64-apple-darwin\n          path: dist\n      - name: \"Archive binary\"\n        run: |\n          TARGET=aarch64-apple-darwin\n          ARCHIVE_NAME=ty-$TARGET\n          ARCHIVE_FILE=$ARCHIVE_NAME.tar.gz\n\n          mkdir -p $ARCHIVE_NAME\n          cp ruff/target/$TARGET/release/ty $ARCHIVE_NAME/ty\n          tar czvf $ARCHIVE_FILE $ARCHIVE_NAME\n          shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256\n      - name: \"Upload binary\"\n        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0\n        with:\n          name: artifacts-aarch64-apple-darwin\n          path: |\n            *.tar.gz\n            *.sha256\n\n  windows:\n    if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-build') }}\n    runs-on: windows-latest\n    strategy:\n      matrix:\n        platform:\n          - target: x86_64-pc-windows-msvc\n            arch: x64\n          - target: i686-pc-windows-msvc\n            arch: x86\n          - target: aarch64-pc-windows-msvc\n            arch: x64\n    steps:\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n        with:\n          submodules: recursive\n          persist-credentials: false\n      - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0\n        with:\n          python-version: ${{ env.PYTHON_VERSION }}\n          architecture: ${{ matrix.platform.arch }}\n      - name: \"Prep README.md\"\n        run: python scripts/transform_readme.py\n      - name: \"Build wheels\"\n        uses: PyO3/maturin-action@04ac600d27cdf7a9a280dadf7147097c42b757ad # v1.50.1\n        with:\n          maturin-version: v1.11.5\n          target: ${{ matrix.platform.target }}\n          args: --release --locked --out dist --compatibility pypi\n        env:\n          # aarch64 build fails, see https://github.com/PyO3/maturin/issues/2110\n          XWIN_VERSION: 16\n      - name: \"Test wheel\"\n        if: ${{ !startsWith(matrix.platform.target, 'aarch64') }}\n        shell: bash\n        run: |\n          python -m pip install dist/\"${PACKAGE_NAME}\"-*.whl --force-reinstall\n          \"${MODULE_NAME}\" version\n          \"${MODULE_NAME}\" --help\n          python -m \"${MODULE_NAME}\" --help\n      - name: \"Upload wheels\"\n        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0\n        with:\n          name: wheels-${{ matrix.platform.target }}\n          path: dist\n      - name: \"Archive binary\"\n        shell: bash\n        run: |\n          ARCHIVE_FILE=ty-${{ matrix.platform.target }}.zip\n          7z a $ARCHIVE_FILE ./ruff/target/${{ matrix.platform.target }}/release/ty.exe\n          sha256sum $ARCHIVE_FILE > $ARCHIVE_FILE.sha256\n      - name: \"Upload binary\"\n        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0\n        with:\n          name: artifacts-${{ matrix.platform.target }}\n          path: |\n            *.zip\n            *.sha256\n\n  linux:\n    if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-build') }}\n    runs-on: ubuntu-latest\n    strategy:\n      matrix:\n        target:\n          - x86_64-unknown-linux-gnu\n          - i686-unknown-linux-gnu\n    steps:\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n        with:\n          submodules: recursive\n          persist-credentials: false\n      - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0\n        with:\n          python-version: ${{ env.PYTHON_VERSION }}\n          architecture: x64\n      - name: \"Prep README.md\"\n        run: python scripts/transform_readme.py\n      - name: \"Build wheels\"\n        uses: PyO3/maturin-action@04ac600d27cdf7a9a280dadf7147097c42b757ad # v1.50.1\n        with:\n          maturin-version: v1.11.5\n          target: ${{ matrix.target }}\n          manylinux: 2_17\n          args: --release --locked --out dist --compatibility pypi\n      - name: \"Test wheel\"\n        if: ${{ startsWith(matrix.target, 'x86_64') }}\n        run: |\n          pip install dist/\"${PACKAGE_NAME}\"-*.whl --force-reinstall\n          \"${MODULE_NAME}\" version\n          \"${MODULE_NAME}\" --help\n          python -m \"${MODULE_NAME}\" --help\n      - name: \"Upload wheels\"\n        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0\n        with:\n          name: wheels-${{ matrix.target }}\n          path: dist\n      - name: \"Archive binary\"\n        shell: bash\n        run: |\n          set -euo pipefail\n\n          TARGET=${{ matrix.target }}\n          ARCHIVE_NAME=ty-$TARGET\n          ARCHIVE_FILE=$ARCHIVE_NAME.tar.gz\n\n          mkdir -p $ARCHIVE_NAME\n          cp ruff/target/$TARGET/release/ty $ARCHIVE_NAME/ty\n          tar czvf $ARCHIVE_FILE $ARCHIVE_NAME\n          shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256\n      - name: \"Upload binary\"\n        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0\n        with:\n          name: artifacts-${{ matrix.target }}\n          path: |\n            *.tar.gz\n            *.sha256\n\n  linux-cross:\n    if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-build') }}\n    runs-on: ubuntu-latest\n    strategy:\n      matrix:\n        platform:\n          - target: aarch64-unknown-linux-gnu\n            arch: aarch64\n            manylinux: 2_17\n            # see https://github.com/astral-sh/ruff/issues/3791\n            # and https://github.com/gnzlbg/jemallocator/issues/170#issuecomment-1503228963\n            maturin_docker_options: -e JEMALLOC_SYS_WITH_LG_PAGE=16\n          - target: armv7-unknown-linux-gnueabihf\n            arch: armv7\n            manylinux: 2_17\n          - target: s390x-unknown-linux-gnu\n            arch: s390x\n            manylinux: 2_17\n          - target: powerpc64le-unknown-linux-gnu\n            arch: ppc64le\n            manylinux: 2_17\n            # see https://github.com/astral-sh/ruff/issues/10073\n            maturin_docker_options: -e JEMALLOC_SYS_WITH_LG_PAGE=16\n          - target: arm-unknown-linux-musleabihf\n            # Use the cross container, but tag as `linux_armv6l`\n            manylinux: auto\n            arch: arm\n\n    steps:\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n        with:\n          submodules: recursive\n          persist-credentials: false\n      - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0\n        with:\n          python-version: ${{ env.PYTHON_VERSION }}\n      - name: \"Prep README.md\"\n        run: python scripts/transform_readme.py\n      - name: \"Build wheels\"\n        uses: PyO3/maturin-action@04ac600d27cdf7a9a280dadf7147097c42b757ad # v1.50.1\n        with:\n          maturin-version: v1.11.5\n          target: ${{ matrix.platform.target }}\n          manylinux: ${{ matrix.platform.manylinux }}\n          docker-options: ${{ matrix.platform.maturin_docker_options }}\n          args: --release --locked --out dist --compatibility pypi\n      - uses: uraimo/run-on-arch-action@d94c13912ea685de38fccc1109385b83fd79427d # v3.0.1\n        if: ${{ matrix.platform.arch != 'ppc64le'}}\n        name: Test wheel\n        with:\n          arch: ${{ matrix.platform.arch == 'arm' && 'armv6' || matrix.platform.arch }}\n          distro: ${{ matrix.platform.arch == 'arm' && 'bullseye' || 'ubuntu20.04' }}\n          githubToken: ${{ github.token }}\n          install: |\n            apt-get update\n            apt-get install -y --no-install-recommends python3 python3-pip\n            pip3 install -U pip\n          run: |\n            pip3 install ${{ env.PACKAGE_NAME }} --no-index --find-links dist/ --force-reinstall\n            ty --help\n      - name: \"Upload wheels\"\n        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0\n        with:\n          name: wheels-${{ matrix.platform.target }}\n          path: dist\n      - name: \"Archive binary\"\n        shell: bash\n        run: |\n          set -euo pipefail\n\n          TARGET=${{ matrix.platform.target }}\n          ARCHIVE_NAME=ty-$TARGET\n          ARCHIVE_FILE=$ARCHIVE_NAME.tar.gz\n\n          mkdir -p $ARCHIVE_NAME\n          cp ruff/target/$TARGET/release/ty $ARCHIVE_NAME/ty\n          tar czvf $ARCHIVE_FILE $ARCHIVE_NAME\n          shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256\n      - name: \"Upload binary\"\n        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0\n        with:\n          name: artifacts-${{ matrix.platform.target }}\n          path: |\n            *.tar.gz\n            *.sha256\n\n  musllinux:\n    if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-build') }}\n    runs-on: ubuntu-latest\n    strategy:\n      matrix:\n        target:\n          - x86_64-unknown-linux-musl\n          - i686-unknown-linux-musl\n    steps:\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n        with:\n          submodules: recursive\n          persist-credentials: false\n      - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0\n        with:\n          python-version: ${{ env.PYTHON_VERSION }}\n          architecture: x64\n      - name: \"Prep README.md\"\n        run: python scripts/transform_readme.py\n      - name: \"Build wheels\"\n        uses: PyO3/maturin-action@04ac600d27cdf7a9a280dadf7147097c42b757ad # v1.50.1\n        with:\n          maturin-version: v1.11.5\n          target: ${{ matrix.target }}\n          manylinux: musllinux_1_2\n          args: --release --locked --out dist --compatibility pypi\n      - name: \"Test wheel\"\n        if: matrix.target == 'x86_64-unknown-linux-musl'\n        run: |\n          docker run --rm -v ${{ github.workspace }}:/io -w /io --env MODULE_NAME --env PACKAGE_NAME alpine:latest sh -c \"\n            apk add python3;\n            python -m venv .venv;\n            .venv/bin/pip3 install ${PACKAGE_NAME} --no-index --find-links dist/ --force-reinstall;\n            .venv/bin/${MODULE_NAME} --help;\n            \"\n      - name: \"Upload wheels\"\n        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0\n        with:\n          name: wheels-${{ matrix.target }}\n          path: dist\n      - name: \"Archive binary\"\n        shell: bash\n        run: |\n          set -euo pipefail\n\n          TARGET=${{ matrix.target }}\n          ARCHIVE_NAME=ty-$TARGET\n          ARCHIVE_FILE=$ARCHIVE_NAME.tar.gz\n\n          mkdir -p $ARCHIVE_NAME\n          cp ruff/target/$TARGET/release/ty $ARCHIVE_NAME/ty\n          tar czvf $ARCHIVE_FILE $ARCHIVE_NAME\n          shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256\n      - name: \"Upload binary\"\n        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0\n        with:\n          name: artifacts-${{ matrix.target }}\n          path: |\n            *.tar.gz\n            *.sha256\n\n  musllinux-cross:\n    if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-build') }}\n    runs-on: ubuntu-latest\n    strategy:\n      matrix:\n        platform:\n          - target: aarch64-unknown-linux-musl\n            arch: aarch64\n            maturin_docker_options: -e JEMALLOC_SYS_WITH_LG_PAGE=16\n          - target: armv7-unknown-linux-musleabihf\n            arch: armv7\n\n    steps:\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n        with:\n          submodules: recursive\n          persist-credentials: false\n      - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0\n        with:\n          python-version: ${{ env.PYTHON_VERSION }}\n      - name: \"Prep README.md\"\n        run: python scripts/transform_readme.py\n      - name: \"Build wheels\"\n        uses: PyO3/maturin-action@04ac600d27cdf7a9a280dadf7147097c42b757ad # v1.50.1\n        with:\n          maturin-version: v1.11.5\n          target: ${{ matrix.platform.target }}\n          manylinux: musllinux_1_2\n          args: --release --locked --out dist --compatibility pypi\n          docker-options: ${{ matrix.platform.maturin_docker_options }}\n      - uses: uraimo/run-on-arch-action@d94c13912ea685de38fccc1109385b83fd79427d # v3.0.1\n        name: Test wheel\n        with:\n          arch: ${{ matrix.platform.arch }}\n          distro: alpine_latest\n          githubToken: ${{ github.token }}\n          install: |\n            apk add python3\n          run: |\n            python -m venv .venv\n            .venv/bin/pip3 install ${{ env.PACKAGE_NAME }} --no-index --find-links dist/ --force-reinstall\n            .venv/bin/${{ env.MODULE_NAME }} --help\n      - name: \"Upload wheels\"\n        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0\n        with:\n          name: wheels-${{ matrix.platform.target }}\n          path: dist\n      - name: \"Archive binary\"\n        shell: bash\n        run: |\n          set -euo pipefail\n\n          TARGET=${{ matrix.platform.target }}\n          ARCHIVE_NAME=ty-$TARGET\n          ARCHIVE_FILE=$ARCHIVE_NAME.tar.gz\n\n          mkdir -p $ARCHIVE_NAME\n          cp ruff/target/$TARGET/release/ty $ARCHIVE_NAME/ty\n          tar czvf $ARCHIVE_FILE $ARCHIVE_NAME\n          shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256\n      - name: \"Upload binary\"\n        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0\n        with:\n          name: artifacts-${{ matrix.platform.target }}\n          path: |\n            *.tar.gz\n            *.sha256\n"
  },
  {
    "path": ".github/workflows/build-docker.yml",
    "content": "# Build and publish a Docker image.\n#\n# Assumed to run as a subworkflow of .github/workflows/release.yml; specifically, as a local\n# artifacts job within `cargo-dist`.\n#\n# TODO(charlie): Ideally, the publish step would happen as a publish job within `cargo-dist`, but\n# sharing the built image as an artifact between jobs is challenging.\nname: \"Build Docker image\"\n\non:\n  workflow_call:\n    inputs:\n      plan:\n        required: true\n        type: string\n  pull_request:\n    paths:\n      - .github/workflows/build-docker.yml\n\nenv:\n  TY_BASE_IMG: ghcr.io/${{ github.repository_owner }}/ty\n\npermissions:\n  contents: read\n  # TODO(zanieb): Ideally, this would be `read` on dry-run but that will require\n  # significant changes to the workflow.\n  packages: write # zizmor: ignore[excessive-permissions]\n\njobs:\n  docker-build:\n    name: Build Docker image (ghcr.io/astral-sh/ty) for ${{ matrix.platform }}\n    runs-on: ubuntu-latest\n    environment:\n      name: release\n    strategy:\n      fail-fast: false\n      matrix:\n        platform:\n          - linux/amd64\n          - linux/arm64\n    steps:\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n        with:\n          submodules: recursive\n          persist-credentials: false\n\n      - uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0\n\n      - uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0\n        with:\n          registry: ghcr.io\n          username: ${{ github.repository_owner }}\n          password: ${{ secrets.GITHUB_TOKEN }}\n\n      - name: Check tag consistency\n        if: ${{ inputs.plan != '' && !fromJson(inputs.plan).announcement_tag_is_implicit }}\n        env:\n          TAG: ${{ inputs.plan != '' && fromJson(inputs.plan).announcement_tag || 'dry-run' }}\n        run: |\n          version=$(grep -m 1 \"^version = \" pyproject.toml | sed -e 's/version = \"\\(.*\\)\"/\\1/g')\n          if [ \"${TAG}\" != \"${version}\" ]; then\n            echo \"The input tag does not match the version from pyproject.toml:\" >&2\n            echo \"${TAG}\" >&2\n            echo \"${version}\" >&2\n            exit 1\n          else\n            echo \"Releasing ${version}\"\n          fi\n\n      - name: Extract metadata (tags, labels) for Docker\n        id: meta\n        uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0\n        with:\n          images: ${{ env.TY_BASE_IMG }}\n          # Defining this makes sure the org.opencontainers.image.version OCI label becomes the actual release version and not the branch name\n          tags: |\n            type=raw,value=dry-run,enable=${{ inputs.plan == '' || fromJson(inputs.plan).announcement_tag_is_implicit }}\n            type=pep440,pattern={{ version }},value=${{ inputs.plan != '' && fromJson(inputs.plan).announcement_tag || 'dry-run' }},enable=${{ inputs.plan != '' && !fromJson(inputs.plan).announcement_tag_is_implicit }}\n\n      - name: Normalize Platform Pair (replace / with -)\n        run: |\n          platform=${{ matrix.platform }}\n          echo \"PLATFORM_TUPLE=${platform//\\//-}\" >> \"$GITHUB_ENV\"\n\n      # Adapted from https://docs.docker.com/build/ci/github-actions/multi-platform/\n      - name: Build and push by digest\n        id: build\n        uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0\n        with:\n          context: .\n          platforms: ${{ matrix.platform }}\n          cache-from: type=gha,scope=ty-${{ env.PLATFORM_TUPLE }}\n          cache-to: type=gha,mode=min,scope=ty-${{ env.PLATFORM_TUPLE }}\n          labels: ${{ steps.meta.outputs.labels }}\n          outputs: type=image,name=${{ env.TY_BASE_IMG }},push-by-digest=true,name-canonical=true,push=${{ inputs.plan != '' && !fromJson(inputs.plan).announcement_tag_is_implicit }}\n\n      - name: Export digests\n        env:\n          digest: ${{ steps.build.outputs.digest }}\n        run: |\n          mkdir -p /tmp/digests\n          touch \"/tmp/digests/${digest#sha256:}\"\n\n      - name: Upload digests\n        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0\n        with:\n          name: digests-${{ env.PLATFORM_TUPLE }}\n          path: /tmp/digests/*\n          if-no-files-found: error\n          retention-days: 1\n\n  docker-publish:\n    name: Publish Docker image (ghcr.io/astral-sh/ty)\n    runs-on: ubuntu-latest\n    environment:\n      name: release\n    needs:\n      - docker-build\n    if: ${{ inputs.plan != '' && !fromJson(inputs.plan).announcement_tag_is_implicit }}\n    permissions:\n      attestations: write\n      id-token: write\n      packages: write\n    steps:\n      - name: Download digests\n        uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0\n        with:\n          path: /tmp/digests\n          pattern: digests-*\n          merge-multiple: true\n\n      - uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0\n\n      - name: Extract metadata (tags, labels) for Docker\n        id: meta\n        uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0\n        with:\n          images: ${{ env.TY_BASE_IMG }}\n          # Order is on purpose such that the label org.opencontainers.image.version has the first pattern with the full version\n          tags: |\n            type=pep440,pattern={{ version }},value=${{ fromJson(inputs.plan).announcement_tag }}\n            type=pep440,pattern={{ major }}.{{ minor }},value=${{ fromJson(inputs.plan).announcement_tag }}\n\n      - uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0\n        with:\n          registry: ghcr.io\n          username: ${{ github.repository_owner }}\n          password: ${{ secrets.GITHUB_TOKEN }}\n\n      # Adapted from https://docs.docker.com/build/ci/github-actions/multi-platform/\n      - name: Create manifest list and push\n        working-directory: /tmp/digests\n        # The jq command expands the docker/metadata json \"tags\" array entry to `-t tag1 -t tag2 ...` for each tag in the array\n        # The printf will expand the base image with the `<TY_BASE_IMG>@sha256:<sha256> ...` for each sha256 in the directory\n        # The final command becomes `docker buildx imagetools create -t tag1 -t tag2 ... <TY_BASE_IMG>@sha256:<sha256_1> <TY_BASE_IMG>@sha256:<sha256_2> ...`\n        run: |\n          # shellcheck disable=SC2046\n          docker buildx imagetools create \\\n            $(jq -cr '.tags | map(\"-t \" + .) | join(\" \")' <<< \"$DOCKER_METADATA_OUTPUT_JSON\") \\\n            $(printf \"${TY_BASE_IMG}@sha256:%s \" *)\n\n      - name: Export manifest digest\n        id: manifest-digest\n        env:\n          IMAGE: ${{ env.TY_BASE_IMG }}\n          VERSION: ${{ steps.meta.outputs.version }}\n        run: |\n          digest=\"$(\n            docker buildx imagetools inspect \\\n              \"${IMAGE}:${VERSION}\" \\\n              --format '{{json .Manifest}}' \\\n            | jq -r '.digest'\n          )\"\n          echo \"digest=${digest}\" >> \"$GITHUB_OUTPUT\"\n\n      - name: Generate artifact attestation\n        uses: actions/attest-build-provenance@a2bbfa25375fe432b6a289bc6b6cd05ecd0c4c32 # v4.1.0\n        with:\n          subject-name: ${{ env.TY_BASE_IMG }}\n          subject-digest: ${{ steps.manifest-digest.outputs.digest }}\n\n  docker-publish-extra:\n    name: Publish additional Docker image based on ${{ matrix.image-mapping }}\n    runs-on: ubuntu-latest\n    environment:\n      name: release\n    needs:\n      - docker-publish\n    if: ${{ inputs.plan != '' && !fromJson(inputs.plan).announcement_tag_is_implicit }}\n    permissions:\n      attestations: write\n      id-token: write\n      packages: write\n    strategy:\n      fail-fast: false\n      matrix:\n        # Mapping of base image followed by a comma followed by one or more base tags (comma separated)\n        # Note, org.opencontainers.image.version label will use the first base tag (use the most specific tag first)\n        image-mapping:\n          - alpine:3.23,alpine3.23,alpine\n          - debian:trixie-slim,trixie-slim,debian-slim\n          - buildpack-deps:trixie,trixie,debian\n    steps:\n      - uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0\n\n      - uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0\n        with:\n          registry: ghcr.io\n          username: ${{ github.repository_owner }}\n          password: ${{ secrets.GITHUB_TOKEN }}\n\n      - name: Generate Dynamic Dockerfile Tags\n        shell: bash\n        env:\n          TAG_VALUE: ${{ fromJson(inputs.plan).announcement_tag }}\n        run: |\n          set -euo pipefail\n\n          # Extract the image and tags from the matrix variable\n          IFS=',' read -r BASE_IMAGE BASE_TAGS <<< \"${{ matrix.image-mapping }}\"\n\n          # Generate Dockerfile content\n          cat <<EOF > Dockerfile\n          FROM ${BASE_IMAGE}\n          COPY --from=${TY_BASE_IMG}:latest /ty /usr/local/bin/ty\n          ENTRYPOINT []\n          CMD [\"/usr/local/bin/ty\"]\n          EOF\n\n          # Initialize a variable to store all tag docker metadata patterns\n          TAG_PATTERNS=\"\"\n\n          # Loop through all base tags and append its docker metadata pattern to the list\n          # Order is on purpose such that the label org.opencontainers.image.version has the first pattern with the full version\n          IFS=','; for TAG in ${BASE_TAGS}; do\n            TAG_PATTERNS=\"${TAG_PATTERNS}type=pep440,pattern={{ version }},suffix=-${TAG},value=${TAG_VALUE}\\n\"\n            TAG_PATTERNS=\"${TAG_PATTERNS}type=pep440,pattern={{ major }}.{{ minor }},suffix=-${TAG},value=${TAG_VALUE}\\n\"\n            TAG_PATTERNS=\"${TAG_PATTERNS}type=raw,value=${TAG}\\n\"\n          done\n\n          # Remove the trailing newline from the pattern list\n          TAG_PATTERNS=\"${TAG_PATTERNS%\\\\n}\"\n\n          # Export image cache name\n          echo \"IMAGE_REF=${BASE_IMAGE//:/-}\" >> \"$GITHUB_ENV\"\n\n          # Export tag patterns using the multiline env var syntax\n          {\n            echo \"TAG_PATTERNS<<EOF\"\n            echo -e \"${TAG_PATTERNS}\"\n            echo EOF\n          } >> \"$GITHUB_ENV\"\n\n      - name: Extract metadata (tags, labels) for Docker\n        id: meta\n        uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0\n        # ghcr.io prefers index level annotations\n        env:\n          DOCKER_METADATA_ANNOTATIONS_LEVELS: index\n        with:\n          images: ${{ env.TY_BASE_IMG }}\n          flavor: |\n            latest=false\n          tags: |\n            ${{ env.TAG_PATTERNS }}\n\n      - name: Build and push\n        id: build-and-push\n        uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0\n        with:\n          context: .\n          platforms: linux/amd64,linux/arm64\n          # We do not really need to cache here as the Dockerfile is tiny\n          #cache-from: type=gha,scope=ty-${{ env.IMAGE_REF }}\n          #cache-to: type=gha,mode=min,scope=ty-${{ env.IMAGE_REF }}\n          push: true\n          tags: ${{ steps.meta.outputs.tags }}\n          labels: ${{ steps.meta.outputs.labels }}\n          annotations: ${{ steps.meta.outputs.annotations }}\n\n      - name: Generate artifact attestation\n        uses: actions/attest-build-provenance@a2bbfa25375fe432b6a289bc6b6cd05ecd0c4c32 # v4.1.0\n        with:\n          subject-name: ${{ env.TY_BASE_IMG }}\n          subject-digest: ${{ steps.build-and-push.outputs.digest }}\n\n  # This is effectively a duplicate of `docker-publish` to make https://github.com/astral-sh/ty/pkgs/container/ty\n  # show the ty base image first since GitHub always shows the last updated image digests\n  # This works by annotating the original digests (previously non-annotated) which triggers an update to ghcr.io\n  docker-republish:\n    name: Annotate Docker image (ghcr.io/astral-sh/ty)\n    runs-on: ubuntu-latest\n    environment:\n      name: release\n    needs:\n      - docker-publish-extra\n    if: ${{ inputs.plan != '' && !fromJson(inputs.plan).announcement_tag_is_implicit }}\n    permissions:\n      attestations: write\n      id-token: write\n      packages: write\n    steps:\n      - name: Download digests\n        uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0\n        with:\n          path: /tmp/digests\n          pattern: digests-*\n          merge-multiple: true\n\n      - uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0\n\n      - name: Extract metadata (tags, labels) for Docker\n        id: meta\n        uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0\n        env:\n          DOCKER_METADATA_ANNOTATIONS_LEVELS: index\n        with:\n          images: ${{ env.TY_BASE_IMG }}\n          # Order is on purpose such that the label org.opencontainers.image.version has the first pattern with the full version\n          tags: |\n            type=pep440,pattern={{ version }},value=${{ fromJson(inputs.plan).announcement_tag }}\n            type=pep440,pattern={{ major }}.{{ minor }},value=${{ fromJson(inputs.plan).announcement_tag }}\n\n      - uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0\n        with:\n          registry: ghcr.io\n          username: ${{ github.repository_owner }}\n          password: ${{ secrets.GITHUB_TOKEN }}\n\n      # Adapted from https://docs.docker.com/build/ci/github-actions/multi-platform/\n      - name: Create manifest list and push\n        working-directory: /tmp/digests\n        # The readarray part is used to make sure the quoting and special characters are preserved on expansion (e.g. spaces)\n        # The jq command expands the docker/metadata json \"tags\" array entry to `-t tag1 -t tag2 ...` for each tag in the array\n        # The printf will expand the base image with the `<TY_BASE_IMG>@sha256:<sha256> ...` for each sha256 in the directory\n        # The final command becomes `docker buildx imagetools create -t tag1 -t tag2 ... <TY_BASE_IMG>@sha256:<sha256_1> <TY_BASE_IMG>@sha256:<sha256_2> ...`\n        run: |\n          readarray -t lines <<< \"$DOCKER_METADATA_OUTPUT_ANNOTATIONS\"; annotations=(); for line in \"${lines[@]}\"; do annotations+=(--annotation \"$line\"); done\n\n          # shellcheck disable=SC2046\n          docker buildx imagetools create \\\n            \"${annotations[@]}\" \\\n            $(jq -cr '.tags | map(\"-t \" + .) | join(\" \")' <<< \"$DOCKER_METADATA_OUTPUT_JSON\") \\\n            $(printf \"${TY_BASE_IMG}@sha256:%s \" *)\n\n      - name: Export manifest digest\n        id: manifest-digest\n        env:\n          IMAGE: ${{ env.TY_BASE_IMG }}\n          VERSION: ${{ steps.meta.outputs.version }}\n        run: |\n          digest=\"$(\n            docker buildx imagetools inspect \\\n              \"${IMAGE}:${VERSION}\" \\\n              --format '{{json .Manifest}}' \\\n            | jq -r '.digest'\n          )\"\n          echo \"digest=${digest}\" >> \"$GITHUB_OUTPUT\"\n\n      - name: Generate artifact attestation\n        uses: actions/attest-build-provenance@a2bbfa25375fe432b6a289bc6b6cd05ecd0c4c32 # v4.1.0\n        with:\n          subject-name: ${{ env.TY_BASE_IMG }}\n          subject-digest: ${{ steps.manifest-digest.outputs.digest }}\n"
  },
  {
    "path": ".github/workflows/ci.yaml",
    "content": "name: CI\n\npermissions:\n  contents: read\n\non:\n  push:\n    branches: [main]\n  pull_request:\n  workflow_dispatch:\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.event.pull_request.number || github.sha }}\n  cancel-in-progress: true\n\nenv:\n  CARGO_INCREMENTAL: 0\n  CARGO_NET_RETRY: 10\n  CARGO_TERM_COLOR: always\n  RUSTUP_MAX_RETRIES: 10\n  PACKAGE_NAME: ty\n\njobs:\n  python-package:\n    name: \"python package\"\n    runs-on: ubuntu-latest\n    timeout-minutes: 20\n    steps:\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n        with:\n          persist-credentials: false\n          submodules: recursive\n      - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0\n        with:\n          python-version: ${{ env.PYTHON_VERSION }}\n          architecture: x64\n      - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2\n      - name: \"Build wheels\"\n        uses: PyO3/maturin-action@04ac600d27cdf7a9a280dadf7147097c42b757ad # v1.50.1\n        with:\n          args: --out dist\n      - name: \"Test wheel\"\n        run: |\n          pip install --force-reinstall --find-links dist \"${PACKAGE_NAME}\" --pre\n          ty --help\n          python -m ty --help\n      - name: \"Remove wheels from cache\"\n        run: rm -rf target/wheels\n\n  prek:\n    name: \"prek\"\n    runs-on: depot-ubuntu-22.04-16\n    timeout-minutes: 10\n    steps:\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n        with:\n          persist-credentials: false\n      - uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0\n      - name: \"Cache prek\"\n        uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3\n        with:\n          path: ~/.cache/prek\n          key: prek-${{ hashFiles('.pre-commit-config.yaml') }}\n      - name: \"Run prek\"\n        run: |\n          echo '```console' > \"$GITHUB_STEP_SUMMARY\"\n          # Enable color output for prek and remove it for the summary\n          # Use --hook-stage=manual to enable slower hooks that are skipped by default\n          SKIP=cargo-fmt,clippy,dev-generate-all uvx prek run --all-files --show-diff-on-failure --color always --hook-stage manual | \\\n            tee >(sed -E 's/\\x1B\\[([0-9]{1,2}(;[0-9]{1,2})*)?[mGK]//g' >> \"$GITHUB_STEP_SUMMARY\") >&1\n          exit_code=\"${PIPESTATUS[0]}\"\n          echo '```' >> \"$GITHUB_STEP_SUMMARY\"\n          exit \"$exit_code\"\n\n  generated-check:\n    name: \"Check generated files unedited\"\n    runs-on: ubuntu-latest\n    timeout-minutes: 5\n    steps:\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n        with:\n          persist-credentials: false\n          submodules: recursive\n\n      - uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0\n\n      - name: \"Run auto generation scripts\"\n        run: |\n          ./scripts/autogenerate_files.sh\n\n      - name: \"Check for uncommitted changes\"\n        run: |\n          if [[ -n \"$(git status --porcelain)\" ]]; then\n            echo \"Error: Auto-generated files were manually edited.\"\n            echo \"Files with changes:\"\n            git status --porcelain\n            exit 1\n          fi\n\n  docs:\n    timeout-minutes: 10\n    name: \"mkdocs\"\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n        with:\n          fetch-depth: 0\n          persist-credentials: false\n      - uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0\n      - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0\n\n      - name: \"Build docs\"\n        run: uvx --with-requirements docs/requirements.txt mkdocs build --strict -f mkdocs.yml\n"
  },
  {
    "path": ".github/workflows/daily_property_tests.yml",
    "content": "name: Daily property test run\n\non:\n  workflow_dispatch:\n  schedule:\n    - cron: \"0 12 * * *\"\n  pull_request:\n    paths:\n      - \".github/workflows/daily_property_tests.yml\"\n\npermissions:\n  contents: read\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}\n  cancel-in-progress: true\n\nenv:\n  CARGO_INCREMENTAL: 0\n  CARGO_NET_RETRY: 10\n  CARGO_TERM_COLOR: always\n  RUSTUP_MAX_RETRIES: 10\n  FORCE_COLOR: 1\n\njobs:\n  property_tests:\n    name: Property tests\n    runs-on: ubuntu-latest\n    timeout-minutes: 20\n    # Don't run the cron job on forks:\n    if: ${{ github.repository == 'astral-sh/ty' || github.event_name != 'schedule' }}\n    steps:\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n        with:\n          persist-credentials: false\n          repository: astral-sh/ruff\n      - name: \"Install Rust toolchain\"\n        run: rustup show\n      - name: \"Install mold\"\n        uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1\n      - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2\n      - name: Build ty\n        # A release build takes longer (2 min vs 1 min), but the property tests run much faster in release\n        # mode (1.5 min vs 14 min), so the overall time is shorter with a release build.\n        run: cargo build --locked --release --package ty_python_semantic --tests\n      - name: Run property tests\n        shell: bash\n        run: |\n          export QUICKCHECK_TESTS=100000\n          for _ in {1..5}; do\n            cargo test --locked --release --package ty_python_semantic -- --ignored list::property_tests\n            cargo test --locked --release --package ty_python_semantic -- --ignored types::property_tests::stable\n          done\n\n  create-issue-on-failure:\n    name: Create an issue if the daily property test run surfaced any bugs\n    runs-on: ubuntu-latest\n    needs: property_tests\n    if: ${{ github.repository == 'astral-sh/ty' && always() && github.event_name == 'schedule' && needs.property_tests.result == 'failure' }}\n    permissions:\n      issues: write\n    steps:\n      - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0\n        with:\n          github-token: ${{ secrets.GITHUB_TOKEN }}\n          script: |\n            await github.rest.issues.create({\n              owner: \"astral-sh\",\n              repo: \"ty\",\n              title: `Daily property test run failed on ${new Date().toDateString()}`,\n              body: \"Run listed here: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}\",\n              labels: [\"bug\", \"type properties\"],\n            })\n"
  },
  {
    "path": ".github/workflows/publish-docs.yml",
    "content": "# Publish the ty documentation.\n#\n# Assumed to run as a subworkflow of .github/workflows/release.yml; specifically, as a post-announce\n# job within `cargo-dist`.\nname: mkdocs\n\non:\n  workflow_dispatch:\n    inputs:\n      ref:\n        description: \"The commit SHA, tag, or branch to publish. Uses the default branch if not specified.\"\n        default: \"\"\n        type: string\n  workflow_call:\n    inputs:\n      plan:\n        required: true\n        type: string\n\npermissions:\n  contents: read\n\njobs:\n  mkdocs:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n        with:\n          ref: ${{ inputs.ref }}\n          persist-credentials: true\n\n      - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0\n        with:\n          python-version: 3.14\n\n      - name: \"Set docs version\"\n        env:\n          version: ${{ (inputs.plan != '' && fromJson(inputs.plan).announcement_tag) || inputs.ref }}\n        run: |\n          # if version is missing, use 'latest'\n          if [ -z \"$version\" ]; then\n            echo \"Using 'latest' as version\"\n            version=\"latest\"\n          fi\n\n          # Use version as display name for now\n          display_name=\"$version\"\n\n          echo \"version=$version\" >> \"$GITHUB_ENV\"\n          echo \"display_name=$display_name\" >> \"$GITHUB_ENV\"\n\n      - name: \"Set branch name\"\n        run: |\n          timestamp=\"$(date +%s)\"\n\n          # create branch_display_name from display_name by replacing all\n          # characters disallowed in git branch names with hyphens\n          branch_display_name=\"$(echo \"${display_name}\" | tr -c '[:alnum:]._' '-' | tr -s '-')\"\n\n          echo \"branch_name=update-docs-$branch_display_name-$timestamp\" >> \"$GITHUB_ENV\"\n          echo \"timestamp=$timestamp\" >> \"$GITHUB_ENV\"\n\n      - name: \"Install dependencies\"\n        run: pip install -r docs/requirements.txt\n\n      - name: \"Build docs\"\n        run: mkdocs build --strict -f mkdocs.yml\n\n      - name: \"Clone docs repo\"\n        run: git clone https://${{ secrets.ASTRAL_DOCS_PAT }}@github.com/astral-sh/docs.git astral-docs\n\n      - name: \"Copy docs\"\n        run: rm -rf astral-docs/site/ty && mkdir -p astral-docs/site && cp -r site/ty astral-docs/site/\n\n      - name: \"Commit docs\"\n        working-directory: astral-docs\n        run: |\n          git config user.name \"astral-docs-bot\"\n          git config user.email \"176161322+astral-docs-bot@users.noreply.github.com\"\n\n          git checkout -b \"${branch_name}\"\n          git add site/ty\n          git commit -m \"Update ty documentation for $version\"\n\n      - name: \"Create Pull Request\"\n        working-directory: astral-docs\n        env:\n          GITHUB_TOKEN: ${{ secrets.ASTRAL_DOCS_PAT }}\n        run: |\n          # set the PR title\n          pull_request_title=\"Update ty documentation for ${display_name}\"\n\n          # Delete any existing pull requests that are open for this version\n          # by checking against pull_request_title because the new PR will\n          # supersede the old one.\n          gh pr list --state open --json title --jq '.[] | select(.title == \"$pull_request_title\") | .number' | \\\n            xargs -I {} gh pr close {}\n\n          # push the branch to GitHub\n          git push origin \"${branch_name}\"\n\n          # create the PR\n          gh pr create \\\n            --base=main \\\n            --head=\"${branch_name}\" \\\n            --title=\"${pull_request_title}\" \\\n            --body=\"Automated documentation update for ${display_name}\" \\\n            --label=\"documentation\"\n\n      - name: \"Merge Pull Request\"\n        if: ${{ inputs.plan != '' && !fromJson(inputs.plan).announcement_tag_is_implicit }}\n        working-directory: astral-docs\n        env:\n          GITHUB_TOKEN: ${{ secrets.ASTRAL_DOCS_PAT }}\n        run: |\n          # auto-merge the PR if the build was triggered by a release. Manual builds should be reviewed by a human.\n          # give the PR a few seconds to be created before trying to auto-merge it\n          sleep 10\n          gh pr merge --squash \"${branch_name}\"\n"
  },
  {
    "path": ".github/workflows/publish-mirror.yml",
    "content": "# Publish ty releases to a mirror\n#\n# Assumed to run as a subworkflow of .github/workflows/release.yml as a custom publish job\nname: publish-mirror\n\non:\n  workflow_call:\n    inputs:\n      plan:\n        required: true\n        type: string\n\npermissions: {}\n\njobs:\n  publish-mirror:\n    runs-on: ubuntu-latest\n    environment:\n      name: release\n    env:\n      VERSION: ${{ fromJson(inputs.plan).announcement_tag }}\n    steps:\n      - name: \"Download GitHub Artifacts\"\n        uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3\n        with:\n          pattern: artifacts-*\n          path: artifacts\n          merge-multiple: true\n      - name: \"Upload to R2\"\n        env:\n          AWS_ACCESS_KEY_ID: ${{ secrets.MIRROR_R2_ACCESS_KEY_ID }}\n          AWS_SECRET_ACCESS_KEY: ${{ secrets.MIRROR_R2_SECRET_ACCESS_KEY }}\n          AWS_ENDPOINT_URL: https://${{ secrets.MIRROR_R2_CLOUDFLARE_ACCOUNT_ID }}.r2.cloudflarestorage.com\n          AWS_DEFAULT_REGION: auto\n          R2_BUCKET: ${{ secrets.MIRROR_R2_BUCKET_NAME }}\n          PROJECT: ty\n        run: |\n          aws s3 cp --recursive --output table --color on \\\n            --exclude '*' \\\n            --include '*.zip' --include '*.zip.sha256' \\\n            --include '*.tar.gz' --include '*.tar.gz.sha256' \\\n            --include sha256.sum --include '*.ps1' --include '*.sh' \\\n            --cache-control \"public, max-age=31536000, immutable\" \\\n            artifacts/ \\\n            \"s3://${R2_BUCKET}/github/${PROJECT}/releases/download/${VERSION}/\"\n"
  },
  {
    "path": ".github/workflows/publish-pypi.yml",
    "content": "# Publish a release to PyPI.\n#\n# Assumed to run as a subworkflow of .github/workflows/release.yml; specifically, as a publish job\n# within `cargo-dist`.\nname: \"Publish to PyPI\"\n\non:\n  workflow_call:\n    inputs:\n      plan:\n        required: true\n        type: string\n\njobs:\n  pypi-publish:\n    name: Upload to PyPI\n    runs-on: ubuntu-latest\n    environment:\n      name: release\n    permissions:\n      # For PyPI's trusted publishing.\n      id-token: write\n    steps:\n      - name: \"Install uv\"\n        uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0\n      - uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0\n        with:\n          pattern: wheels-*\n          path: wheels\n          merge-multiple: true\n      - name: Publish to PyPi\n        run: uv publish -v wheels/*\n"
  },
  {
    "path": ".github/workflows/release.yml",
    "content": "# This file was autogenerated by dist: https://axodotdev.github.io/cargo-dist\n#\n# Copyright 2022-2024, axodotdev\n# SPDX-License-Identifier: MIT or Apache-2.0\n#\n# CI that:\n#\n# * checks for a Git Tag that looks like a release\n# * builds artifacts with dist (archives, installers, hashes)\n# * uploads those artifacts to temporary workflow zip\n# * on success, uploads the artifacts to a GitHub Release\n#\n# Note that the GitHub Release will be created with a generated\n# title/body based on your changelogs.\n\nname: Release\npermissions:\n  \"contents\": \"write\"\n\n# This task will run whenever you workflow_dispatch with a tag that looks like a version\n# like \"1.0.0\", \"v0.1.0-prerelease.1\", \"my-app/0.1.0\", \"releases/v1.0.0\", etc.\n# Various formats will be parsed into a VERSION and an optional PACKAGE_NAME, where\n# PACKAGE_NAME must be the name of a Cargo package in your workspace, and VERSION\n# must be a Cargo-style SemVer Version (must have at least major.minor.patch).\n#\n# If PACKAGE_NAME is specified, then the announcement will be for that\n# package (erroring out if it doesn't have the given version or isn't dist-able).\n#\n# If PACKAGE_NAME isn't specified, then the announcement will be for all\n# (dist-able) packages in the workspace with that version (this mode is\n# intended for workspaces with only one dist-able package, or with all dist-able\n# packages versioned/released in lockstep).\n#\n# If you push multiple tags at once, separate instances of this workflow will\n# spin up, creating an independent announcement for each one. However, GitHub\n# will hard limit this to 3 tags per commit, as it will assume more tags is a\n# mistake.\n#\n# If there's a prerelease-style suffix to the version, then the release(s)\n# will be marked as a prerelease.\non:\n  pull_request:\n  workflow_dispatch:\n    inputs:\n      tag:\n        description: Release Tag\n        required: true\n        default: dry-run\n        type: string\n\njobs:\n  # Run 'dist plan' (or host) to determine what tasks we need to do\n  plan:\n    runs-on: \"depot-ubuntu-latest-4\"\n    outputs:\n      val: ${{ steps.plan.outputs.manifest }}\n      tag: ${{ (inputs.tag != 'dry-run' && inputs.tag) || '' }}\n      tag-flag: ${{ inputs.tag && inputs.tag != 'dry-run' && format('--tag={0}', inputs.tag) || '' }}\n      publishing: ${{ inputs.tag && inputs.tag != 'dry-run' }}\n    env:\n      GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n    steps:\n      - uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98\n        with:\n          persist-credentials: false\n          submodules: recursive\n      - name: Install dist\n        # we specify bash to get pipefail; it guards against the `curl` command\n        # failing. otherwise `sh` won't catch that `curl` returned non-0\n        shell: bash\n        run: \"curl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/cargo-dist/releases/download/v0.31.0/cargo-dist-installer.sh | sh\"\n      - name: Cache dist\n        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f\n        with:\n          name: cargo-dist-cache\n          path: ~/.cargo/bin/dist\n      # sure would be cool if github gave us proper conditionals...\n      # so here's a doubly-nested ternary-via-truthiness to try to provide the best possible\n      # functionality based on whether this is a pull_request, and whether it's from a fork.\n      # (PRs run on the *source* but secrets are usually on the *target* -- that's *good*\n      # but also really annoying to build CI around when it needs secrets to work right.)\n      - id: plan\n        run: |\n          dist ${{ (inputs.tag && inputs.tag != 'dry-run' && format('host --steps=create --tag={0}', inputs.tag)) || 'plan' }} --output-format=json > plan-dist-manifest.json\n          echo \"dist ran successfully\"\n          cat plan-dist-manifest.json\n          echo \"manifest=$(jq -c \".\" plan-dist-manifest.json)\" >> \"$GITHUB_OUTPUT\"\n      - name: \"Upload dist-manifest.json\"\n        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f\n        with:\n          name: artifacts-plan-dist-manifest\n          path: plan-dist-manifest.json\n\n  custom-build-binaries:\n    needs:\n      - plan\n    if: ${{ needs.plan.outputs.publishing == 'true' || fromJson(needs.plan.outputs.val).ci.github.pr_run_mode == 'upload' || inputs.tag == 'dry-run' }}\n    uses: ./.github/workflows/build-binaries.yml\n    with:\n      plan: ${{ needs.plan.outputs.val }}\n    secrets: inherit\n\n  custom-build-docker:\n    needs:\n      - plan\n    if: ${{ needs.plan.outputs.publishing == 'true' || fromJson(needs.plan.outputs.val).ci.github.pr_run_mode == 'upload' || inputs.tag == 'dry-run' }}\n    uses: ./.github/workflows/build-docker.yml\n    with:\n      plan: ${{ needs.plan.outputs.val }}\n    secrets: inherit\n    permissions:\n      \"attestations\": \"write\"\n      \"contents\": \"read\"\n      \"id-token\": \"write\"\n      \"packages\": \"write\"\n\n  # Build and package all the platform-agnostic(ish) things\n  build-global-artifacts:\n    needs:\n      - plan\n      - custom-build-binaries\n      - custom-build-docker\n    runs-on: \"depot-ubuntu-latest-4\"\n    env:\n      GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n      BUILD_MANIFEST_NAME: target/distrib/global-dist-manifest.json\n    steps:\n      - uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98\n        with:\n          persist-credentials: false\n          submodules: recursive\n      - name: Install cached dist\n        uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3\n        with:\n          name: cargo-dist-cache\n          path: ~/.cargo/bin/\n      - run: chmod +x ~/.cargo/bin/dist\n      # Get all the local artifacts for the global tasks to use (for e.g. checksums)\n      - name: Fetch local artifacts\n        uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3\n        with:\n          pattern: artifacts-*\n          path: target/distrib/\n          merge-multiple: true\n      - id: cargo-dist\n        shell: bash\n        run: |\n          dist build ${{ needs.plan.outputs.tag-flag }} --output-format=json \"--artifacts=global\" > dist-manifest.json\n          echo \"dist ran successfully\"\n\n          # Parse out what we just built and upload it to scratch storage\n          echo \"paths<<EOF\" >> \"$GITHUB_OUTPUT\"\n          jq --raw-output \".upload_files[]\" dist-manifest.json >> \"$GITHUB_OUTPUT\"\n          echo \"EOF\" >> \"$GITHUB_OUTPUT\"\n\n          cp dist-manifest.json \"$BUILD_MANIFEST_NAME\"\n      - name: \"Upload artifacts\"\n        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f\n        with:\n          name: artifacts-build-global\n          path: |\n            ${{ steps.cargo-dist.outputs.paths }}\n            ${{ env.BUILD_MANIFEST_NAME }}\n  # Determines if we should publish/announce\n  host:\n    needs:\n      - plan\n      - custom-build-binaries\n      - custom-build-docker\n      - build-global-artifacts\n    # Only run if we're \"publishing\", and only if plan, local and global didn't fail (skipped is fine)\n    if: ${{ always() && needs.plan.result == 'success' && needs.plan.outputs.publishing == 'true' && (needs.build-global-artifacts.result == 'skipped' || needs.build-global-artifacts.result == 'success') && (needs.custom-build-binaries.result == 'skipped' || needs.custom-build-binaries.result == 'success') && (needs.custom-build-docker.result == 'skipped' || needs.custom-build-docker.result == 'success') }}\n    env:\n      GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n    runs-on: \"depot-ubuntu-latest-4\"\n    outputs:\n      val: ${{ steps.host.outputs.manifest }}\n    steps:\n      - uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98\n        with:\n          persist-credentials: false\n          submodules: recursive\n      - name: Install cached dist\n        uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3\n        with:\n          name: cargo-dist-cache\n          path: ~/.cargo/bin/\n      - run: chmod +x ~/.cargo/bin/dist\n      # Fetch artifacts from scratch-storage\n      - name: Fetch artifacts\n        uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3\n        with:\n          pattern: artifacts-*\n          path: target/distrib/\n          merge-multiple: true\n      # This is a harmless no-op for GitHub Releases, hosting for that happens in \"announce\"\n      - id: host\n        shell: bash\n        run: |\n          dist host ${{ needs.plan.outputs.tag-flag }} --steps=upload --steps=release --output-format=json > dist-manifest.json\n          echo \"artifacts uploaded and released successfully\"\n          cat dist-manifest.json\n          echo \"manifest=$(jq -c \".\" dist-manifest.json)\" >> \"$GITHUB_OUTPUT\"\n      - name: \"Upload dist-manifest.json\"\n        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f\n        with:\n          # Overwrite the previous copy\n          name: artifacts-dist-manifest\n          path: dist-manifest.json\n\n  custom-publish-pypi:\n    needs:\n      - plan\n      - host\n    if: ${{ !fromJson(needs.plan.outputs.val).announcement_is_prerelease || fromJson(needs.plan.outputs.val).publish_prereleases }}\n    uses: ./.github/workflows/publish-pypi.yml\n    with:\n      plan: ${{ needs.plan.outputs.val }}\n    secrets: inherit\n    # publish jobs get escalated permissions\n    permissions:\n      \"id-token\": \"write\"\n      \"packages\": \"write\"\n\n  # Create a GitHub Release while uploading all files to it\n  announce:\n    needs:\n      - plan\n      - host\n      - custom-publish-pypi\n    # use \"always() && ...\" to allow us to wait for all publish jobs while\n    # still allowing individual publish jobs to skip themselves (for prereleases).\n    # \"host\" however must run to completion, no skipping allowed!\n    if: ${{ always() && needs.host.result == 'success' && (needs.custom-publish-pypi.result == 'skipped' || needs.custom-publish-pypi.result == 'success') }}\n    runs-on: \"depot-ubuntu-latest-4\"\n    permissions:\n      \"attestations\": \"write\"\n      \"contents\": \"write\"\n      \"id-token\": \"write\"\n    env:\n      GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n    steps:\n      - uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98\n        with:\n          persist-credentials: false\n          submodules: recursive\n      # Create a GitHub Release while uploading all files to it\n      - name: \"Download GitHub Artifacts\"\n        uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3\n        with:\n          pattern: artifacts-*\n          path: artifacts\n          merge-multiple: true\n      - name: Cleanup\n        run: |\n          # Remove the granular manifests\n          rm -f artifacts/*-dist-manifest.json\n      - name: Attest\n        uses: actions/attest-build-provenance@00014ed6ed5efc5b1ab7f7f34a39eb55d41aa4f8\n        with:\n          subject-path: |\n            artifacts/*.json\n            artifacts/*.sh\n            artifacts/*.ps1\n            artifacts/*.zip\n            artifacts/*.tar.gz\n      - name: Create GitHub Release\n        env:\n          PRERELEASE_FLAG: \"${{ fromJson(needs.host.outputs.val).announcement_is_prerelease && '--prerelease' || '' }}\"\n          ANNOUNCEMENT_TITLE: \"${{ fromJson(needs.host.outputs.val).announcement_title }}\"\n          ANNOUNCEMENT_BODY: \"${{ fromJson(needs.host.outputs.val).announcement_github_body }}\"\n          RELEASE_COMMIT: \"${{ github.sha }}\"\n        run: |\n          # Write and read notes from a file to avoid quoting breaking things\n          echo \"$ANNOUNCEMENT_BODY\" > $RUNNER_TEMP/notes.txt\n\n          gh release create \"${{ needs.plan.outputs.tag }}\" --target \"$RELEASE_COMMIT\" $PRERELEASE_FLAG --title \"$ANNOUNCEMENT_TITLE\" --notes-file \"$RUNNER_TEMP/notes.txt\" artifacts/*\n\n  custom-publish-docs:\n    needs:\n      - plan\n      - announce\n    uses: ./.github/workflows/publish-docs.yml\n    with:\n      plan: ${{ needs.plan.outputs.val }}\n    secrets: inherit\n\n  custom-publish-mirror:\n    needs:\n      - plan\n      - announce\n    uses: ./.github/workflows/publish-mirror.yml\n    with:\n      plan: ${{ needs.plan.outputs.val }}\n    secrets: inherit\n    permissions:\n      \"contents\": \"read\"\n"
  },
  {
    "path": ".github/zizmor.yml",
    "content": "rules:\n  secrets-outside-env:\n    ignore:\n      # TODO: move the ASTRAL_DOCS_PAT secret to the release environment\n      - publish-docs.yml\n"
  },
  {
    "path": ".gitignore",
    "content": "# Python-generated files\n__pycache__/\n*.py[oc]\nbuild/\ndist/\nwheels/\n*.egg-info\n\n# Virtual environments\n.venv\n"
  },
  {
    "path": ".gitmodules",
    "content": "[submodule \"ruff\"]\n\tpath = ruff\n\turl = https://github.com/astral-sh/ruff\n"
  },
  {
    "path": ".markdownlint.yaml",
    "content": "# default to true for all rules\ndefault: true\n\n# MD007/unordered-list-indent\nMD007:\n  indent: 4\n\n# MD033/no-inline-html\nMD033: false\n\n# MD041/first-line-h1\nMD041: false\n\n# MD013/line-length\nMD013: false\n\n# MD014/commands-show-output\nMD014: false\n\n# MD024/no-duplicate-heading\nMD024:\n  # Allow when nested under different parents e.g. CHANGELOG.md\n  siblings_only: true\n\n# MD046/code-block-style\n#\n# Ignore this because it conflicts with the code block style used in content\n# tabs of mkdocs-material which is to add a blank line after the content title.\n#\n# Ref: https://github.com/astral-sh/ruff/pull/15011#issuecomment-2544790854\nMD046: false\n\n# Link text should be descriptive\n# Disallows link text like *here* which is annoying.\nMD059: false\n"
  },
  {
    "path": ".pre-commit-config.yaml",
    "content": "fail_fast: false\n\nexclude: |\n  (?x)^(\n    .github/workflows/release.yml|\n    ruff/.*|\n    docs/reference/(cli|configuration|rules|environment).md\n  )$\n\nrepos:\n  # Priority 0: Read-only hooks; hooks that modify disjoint file types.\n  - repo: https://github.com/astral-sh/uv-pre-commit\n    rev: 0.10.9\n    hooks:\n      - id: uv-lock\n        priority: 0\n\n  - repo: https://github.com/pre-commit/pre-commit-hooks\n    rev: v6.0.0\n    hooks:\n      - id: check-merge-conflict\n        priority: 0\n\n  - repo: https://github.com/astral-sh/ruff-pre-commit\n    rev: v0.15.5\n    hooks:\n      - id: ruff-format\n        priority: 0\n      - id: ruff\n        args: [--fix, --exit-non-zero-on-fix]\n        types_or: [python, pyi]\n        require_serial: true\n        priority: 1\n\n  - repo: https://github.com/abravalheri/validate-pyproject\n    rev: v0.25\n    hooks:\n      - id: validate-pyproject\n        priority: 0\n\n  - repo: https://github.com/executablebooks/mdformat\n    rev: 1.0.0\n    hooks:\n      - id: mdformat\n        language: python # means renovate will also update `additional_dependencies`\n        additional_dependencies:\n          - mdformat-mkdocs==5.1.4\n          - mdformat-footnote==0.1.3\n        priority: 0\n\n  - repo: https://github.com/igorshubovych/markdownlint-cli\n    rev: v0.48.0\n    hooks:\n      - id: markdownlint-fix\n        priority: 1\n\n  - repo: https://github.com/crate-ci/typos\n    rev: v1.44.0\n    hooks:\n      - id: typos\n        priority: 0\n\n  # Prettier\n  - repo: https://github.com/rbubley/mirrors-prettier\n    rev: v3.8.1\n    hooks:\n      - id: prettier\n        types: [yaml]\n        priority: 0\n\n  # zizmor detects security vulnerabilities in GitHub Actions workflows.\n  # Additional configuration for the tool is found in `.github/zizmor.yml`\n  - repo: https://github.com/zizmorcore/zizmor-pre-commit\n    rev: v1.23.1\n    hooks:\n      - id: zizmor\n        priority: 0\n\n  - repo: https://github.com/shellcheck-py/shellcheck-py\n    rev: v0.11.0.1\n    hooks:\n      - id: shellcheck\n        priority: 0\n\n  - repo: https://github.com/python-jsonschema/check-jsonschema\n    rev: 0.37.0\n    hooks:\n      - id: check-github-workflows\n        priority: 0\n\n  # `actionlint` hook, for verifying correct syntax in GitHub Actions workflows.\n  # Some additional configuration for `actionlint` can be found in `.github/actionlint.yaml`.\n  - repo: https://github.com/rhysd/actionlint\n    rev: v1.7.11\n    hooks:\n      - id: actionlint\n        stages:\n          # This hook is disabled by default, since it's quite slow.\n          # To run all hooks *including* this hook, use `uvx pre-commit run -a --hook-stage=manual`.\n          # To run *just* this hook, use `uvx pre-commit run -a actionlint --hook-stage=manual`.\n          - manual\n        args:\n          - \"-ignore=SC2129\" # ignorable stylistic lint from shellcheck\n          - \"-ignore=SC2016\" # another shellcheck lint: seems to have false positives?\n        language: golang # means renovate will also update `additional_dependencies`\n        additional_dependencies:\n          # actionlint has a shellcheck integration which extracts shell scripts in `run:` steps from GitHub Actions\n          # and checks these with shellcheck. This is arguably its most useful feature,\n          # but the integration only works if shellcheck is installed\n          - \"github.com/wasilibs/go-shellcheck/cmd/shellcheck@v0.11.1\"\n        priority: 0\n"
  },
  {
    "path": ".python-version",
    "content": "3.13\n"
  },
  {
    "path": "BENCHMARKS.md",
    "content": "# Benchmarks\n\nAll benchmarks were computed on macOS (Apple M4 Pro 14, 48 GB) with the following tool versions:\n\n- [Pyrefly](https://pypi.org/project/pyrefly/) 0.45.2\n- [Pyright](https://www.npmjs.com/package/pyright) 1.1.407\n- [mypy](https://pypi.org/project/mypy/) \\<=1.19.0\n- [ty](https://pypi.org/project/ty/) 0.0.2\n\nBenchmark performance may vary across operating systems, and from project to project. This document\nincludes benchmarks from a variety of projects to provide a representative example of real-world\nusage: [Black](https://github.com/psf/black), [discord.py](https://github.com/Rapptz/discord.py),\n[Home Assistant](https://github.com/home-assistant/core), [isort](https://github.com/pycqa/isort),\n[Jinja](https://github.com/pallets/jinja), [pandas](https://github.com/pandas-dev/pandas),\n[pandas-stubs](https://github.com/pandas-dev/pandas-stubs),\n[Prefect](https://github.com/PrefectHQ/prefect), and [PyTorch](https://github.com/pytorch/pytorch).\n\nFor instructions on running the benchmarks, see\n[`ty_benchmark/README.md`](https://github.com/astral-sh/ruff/blob/7f7485d608d2da19a0632a1238f2d4be551f612f/scripts/ty_benchmark/README.md).\n\n## CLI\n\n```text\nblack\n-----\n\nBenchmark 1: ty\n  Time (mean ± σ):      53.8 ms ±   1.6 ms    [User: 344.9 ms, System: 36.3 ms]\n  Range (min … max):    51.4 ms …  57.9 ms    49 runs\n\n  Warning: Ignoring non-zero exit code.\n\nBenchmark 2: Pyrefly\n  Time (mean ± σ):     167.4 ms ±   5.2 ms    [User: 648.8 ms, System: 157.8 ms]\n  Range (min … max):   159.3 ms … 177.0 ms    18 runs\n\n  Warning: Ignoring non-zero exit code.\n\nBenchmark 3: mypy\n  Time (mean ± σ):      1.197 s ±  0.008 s    [User: 1.144 s, System: 0.051 s]\n  Range (min … max):    1.186 s …  1.212 s    10 runs\n\nBenchmark 4: Pyright\n  Time (mean ± σ):      1.193 s ±  0.020 s    [User: 13.264 s, System: 0.808 s]\n  Range (min … max):    1.173 s …  1.240 s    10 runs\n\n  Warning: Ignoring non-zero exit code.\n\nSummary\n  ty ran\n    3.11 ± 0.13 times faster than Pyrefly\n   22.16 ± 0.74 times faster than Pyright\n   22.25 ± 0.66 times faster than mypy\n\n-------------------------------------------------------------------------------\n\ndiscord.py\n----------\n\nBenchmark 1: ty\n  Time (mean ± σ):     272.3 ms ±   1.4 ms    [User: 1436.3 ms, System: 99.3 ms]\n  Range (min … max):   270.5 ms … 275.6 ms    10 runs\n\n  Warning: Ignoring non-zero exit code.\n\nBenchmark 2: Pyrefly\n  Time (mean ± σ):     312.7 ms ±  23.9 ms    [User: 2585.5 ms, System: 244.1 ms]\n  Range (min … max):   283.4 ms … 367.9 ms    10 runs\n\n  Warning: Ignoring non-zero exit code.\n\nBenchmark 3: mypy\n  Time (mean ± σ):      6.617 s ±  0.212 s    [User: 6.521 s, System: 0.091 s]\n  Range (min … max):    6.233 s …  6.852 s    10 runs\n\n  Warning: Ignoring non-zero exit code.\n\nBenchmark 4: Pyright\n  Time (mean ± σ):      2.874 s ±  0.078 s    [User: 35.269 s, System: 1.710 s]\n  Range (min … max):    2.753 s …  2.964 s    10 runs\n\n  Warning: Ignoring non-zero exit code.\n\nSummary\n  ty ran\n    1.15 ± 0.09 times faster than Pyrefly\n   10.55 ± 0.29 times faster than Pyright\n   24.30 ± 0.79 times faster than mypy\n\n-------------------------------------------------------------------------------\n\nhomeassistant\n-------------\n\nBenchmark 1: ty\n  Time (mean ± σ):      2.186 s ±  0.083 s    [User: 23.139 s, System: 2.920 s]\n  Range (min … max):    2.067 s …  2.355 s    10 runs\n\n  Warning: Ignoring non-zero exit code.\n\nBenchmark 2: Pyrefly\n  Time (mean ± σ):      5.320 s ±  0.020 s    [User: 25.054 s, System: 33.545 s]\n  Range (min … max):    5.294 s …  5.365 s    10 runs\n\n  Warning: Ignoring non-zero exit code.\n\nBenchmark 3: mypy\n  Time (mean ± σ):     45.662 s ±  0.224 s    [User: 43.882 s, System: 1.767 s]\n  Range (min … max):   45.328 s … 46.009 s    10 runs\n\n  Warning: Ignoring non-zero exit code.\n\nBenchmark 4: Pyright\n  Time (mean ± σ):     19.623 s ±  0.425 s    [User: 227.040 s, System: 21.942 s]\n  Range (min … max):   19.255 s … 20.748 s    10 runs\n\n  Warning: Ignoring non-zero exit code.\n\nSummary\n  ty ran\n    2.43 ± 0.09 times faster than Pyrefly\n    8.98 ± 0.39 times faster than Pyright\n   20.89 ± 0.80 times faster than mypy\n\n-------------------------------------------------------------------------------\n\nisort\n-----\n\nBenchmark 1: ty\n  Time (mean ± σ):      39.0 ms ±   1.1 ms    [User: 161.0 ms, System: 21.0 ms]\n  Range (min … max):    36.2 ms …  41.2 ms    67 runs\n\n  Warning: Ignoring non-zero exit code.\n\nBenchmark 2: Pyrefly\n  Time (mean ± σ):     138.5 ms ±   2.8 ms    [User: 462.0 ms, System: 82.2 ms]\n  Range (min … max):   132.2 ms … 143.8 ms    21 runs\n\n  Warning: Ignoring non-zero exit code.\n\nBenchmark 3: mypy\n  Time (mean ± σ):     581.2 ms ±   2.2 ms    [User: 547.8 ms, System: 31.2 ms]\n  Range (min … max):   578.4 ms … 584.9 ms    10 runs\n\nBenchmark 4: Pyright\n  Time (mean ± σ):      2.453 s ±  0.032 s    [User: 13.608 s, System: 0.743 s]\n  Range (min … max):    2.402 s …  2.504 s    10 runs\n\n  Warning: Ignoring non-zero exit code.\n\nSummary\n  ty ran\n    3.55 ± 0.13 times faster than Pyrefly\n   14.91 ± 0.44 times faster than mypy\n   62.90 ± 2.02 times faster than Pyright\n\n-------------------------------------------------------------------------------\n\njinja\n-----\n\nBenchmark 1: ty\n  Time (mean ± σ):     110.2 ms ±   3.3 ms    [User: 326.8 ms, System: 27.6 ms]\n  Range (min … max):   107.0 ms … 119.0 ms    26 runs\n\n  Warning: Ignoring non-zero exit code.\n\nBenchmark 2: Pyrefly\n  Time (mean ± σ):     134.5 ms ±   1.7 ms    [User: 444.8 ms, System: 87.5 ms]\n  Range (min … max):   131.5 ms … 137.8 ms    21 runs\n\n  Warning: Ignoring non-zero exit code.\n\nBenchmark 3: mypy\n  Time (mean ± σ):     700.9 ms ±  13.2 ms    [User: 665.5 ms, System: 33.0 ms]\n  Range (min … max):   693.7 ms … 737.7 ms    10 runs\n\n  Warning: Ignoring non-zero exit code.\n\nBenchmark 4: Pyright\n  Time (mean ± σ):      1.099 s ±  0.014 s    [User: 12.235 s, System: 0.736 s]\n  Range (min … max):    1.081 s …  1.127 s    10 runs\n\n  Warning: Ignoring non-zero exit code.\n\nSummary\n  ty ran\n    1.22 ± 0.04 times faster than Pyrefly\n    6.36 ± 0.23 times faster than mypy\n    9.97 ± 0.33 times faster than Pyright\n\n-------------------------------------------------------------------------------\n\npandas\n------\n\nBenchmark 1: ty\n  Time (mean ± σ):     551.5 ms ±  56.7 ms    [User: 4906.6 ms, System: 222.6 ms]\n  Range (min … max):   467.6 ms … 614.8 ms    10 runs\n\n  Warning: Ignoring non-zero exit code.\n\nBenchmark 2: Pyrefly\n  Time (mean ± σ):      1.174 s ±  0.012 s    [User: 11.917 s, System: 1.035 s]\n  Range (min … max):    1.149 s …  1.186 s    10 runs\n\n  Warning: Ignoring non-zero exit code.\n\nBenchmark 3: mypy\n  Time (mean ± σ):     21.366 s ±  0.083 s    [User: 21.112 s, System: 0.247 s]\n  Range (min … max):   21.234 s … 21.539 s    10 runs\n\nBenchmark 4: Pyright\n  Time (mean ± σ):      6.878 s ±  0.082 s    [User: 80.281 s, System: 3.504 s]\n  Range (min … max):    6.749 s …  7.001 s    10 runs\n\n  Warning: Ignoring non-zero exit code.\n\nSummary\n  ty ran\n    2.13 ± 0.22 times faster than Pyrefly\n   12.47 ± 1.29 times faster than Pyright\n   38.74 ± 3.99 times faster than mypy\n\n-------------------------------------------------------------------------------\n\npandas-stubs\n------------\n\nBenchmark 1: ty\n  Time (mean ± σ):      83.2 ms ±   2.8 ms    [User: 377.9 ms, System: 50.1 ms]\n  Range (min … max):    75.3 ms …  87.1 ms    36 runs\n\n  Warning: Ignoring non-zero exit code.\n\nBenchmark 2: Pyrefly\n  Time (mean ± σ):     253.6 ms ±   6.0 ms    [User: 853.5 ms, System: 322.0 ms]\n  Range (min … max):   245.2 ms … 264.2 ms    11 runs\n\n  Warning: Ignoring non-zero exit code.\n\nBenchmark 3: mypy\n  Time (mean ± σ):      5.290 s ±  0.028 s    [User: 5.150 s, System: 0.135 s]\n  Range (min … max):    5.248 s …  5.332 s    10 runs\n\nBenchmark 4: Pyright\n  Time (mean ± σ):      1.792 s ±  0.030 s    [User: 17.300 s, System: 1.199 s]\n  Range (min … max):    1.760 s …  1.843 s    10 runs\n\nSummary\n  ty ran\n    3.05 ± 0.12 times faster than Pyrefly\n   21.55 ± 0.80 times faster than Pyright\n   63.61 ± 2.15 times faster than mypy\n\n-------------------------------------------------------------------------------\n\nprefect\n-------\n\nBenchmark 1: ty\n  Time (mean ± σ):      92.4 ms ±   1.1 ms    [User: 524.8 ms, System: 70.1 ms]\n  Range (min … max):    90.8 ms …  95.1 ms    30 runs\n\n  Warning: Ignoring non-zero exit code.\n\nBenchmark 2: Pyrefly\n  Time (mean ± σ):     322.3 ms ±   7.9 ms    [User: 1061.7 ms, System: 691.8 ms]\n  Range (min … max):   305.0 ms … 330.5 ms    10 runs\n\n  Warning: Ignoring non-zero exit code.\n\nBenchmark 3: mypy\n  Time (mean ± σ):     742.5 ms ±   3.4 ms    [User: 702.0 ms, System: 38.1 ms]\n  Range (min … max):   737.6 ms … 749.0 ms    10 runs\n\n  Warning: Ignoring non-zero exit code.\n\nBenchmark 4: Pyright\n  Time (mean ± σ):      3.545 s ±  0.042 s    [User: 41.849 s, System: 2.252 s]\n  Range (min … max):    3.507 s …  3.641 s    10 runs\n\n  Warning: Ignoring non-zero exit code.\n\nSummary\n  ty ran\n    3.49 ± 0.10 times faster than Pyrefly\n    8.03 ± 0.10 times faster than mypy\n   38.35 ± 0.64 times faster than Pyright\n\n-------------------------------------------------------------------------------\n\npytorch\n-------\n\nBenchmark 1: ty\n  Time (mean ± σ):      1.160 s ±  0.115 s    [User: 11.200 s, System: 1.344 s]\n  Range (min … max):    1.034 s …  1.314 s    10 runs\n\n  Warning: Ignoring non-zero exit code.\n\nBenchmark 2: Pyrefly\n  Time (mean ± σ):      2.084 s ±  0.029 s    [User: 19.660 s, System: 4.377 s]\n  Range (min … max):    2.051 s …  2.143 s    10 runs\n\n  Warning: Ignoring non-zero exit code.\n\nBenchmark 3: mypy\n  Time (mean ± σ):     30.157 s ±  0.155 s    [User: 29.776 s, System: 0.373 s]\n  Range (min … max):   29.956 s … 30.454 s    10 runs\n\n  Warning: Ignoring non-zero exit code.\n\nBenchmark 4: Pyright\n  Time (mean ± σ):     12.770 s ±  0.294 s    [User: 149.537 s, System: 8.990 s]\n  Range (min … max):   12.357 s … 13.175 s    10 runs\n\n  Warning: Ignoring non-zero exit code.\n\nSummary\n  ty ran\n    1.80 ± 0.18 times faster than Pyrefly\n   11.01 ± 1.12 times faster than Pyright\n   26.01 ± 2.59 times faster than mypy\n```\n\n## LSP\n\n### Incremental edit\n\n```shell\n----------------------------------------------------------------------------------------- benchmark 'black': 3 tests ----------------------------------------------------------------------------------------\nName (time in ms)                             Min                 Max                Mean            StdDev              Median               IQR            Outliers       OPS            Rounds  Iterations\n-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\ntest_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\ntest_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\ntest_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\n-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n\n----------------------------------------------------------------------------------------- benchmark 'discord.py': 3 tests -----------------------------------------------------------------------------------------\nName (time in ms)                                  Min                 Max                Mean             StdDev              Median                IQR            Outliers      OPS            Rounds  Iterations\n-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\ntest_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\ntest_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\ntest_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\n-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n\n--------------------------------------------------------------------------------------------- benchmark 'homeassistant': 3 tests ---------------------------------------------------------------------------------------------\nName (time in ms)                                       Min                   Max                  Mean             StdDev                Median                IQR            Outliers      OPS            Rounds  Iterations\n------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\ntest_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\ntest_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\ntest_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\n------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n\n---------------------------------------------------------------------------------------- benchmark 'isort': 3 tests ----------------------------------------------------------------------------------------\nName (time in ms)                             Min                 Max                Mean            StdDev              Median               IQR            Outliers      OPS            Rounds  Iterations\n------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\ntest_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\ntest_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\ntest_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\n------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n\n---------------------------------------------------------------------------------------- benchmark 'jinja': 3 tests ----------------------------------------------------------------------------------------\nName (time in ms)                             Min                 Max                Mean            StdDev              Median               IQR            Outliers      OPS            Rounds  Iterations\n------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\ntest_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\ntest_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\ntest_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\n------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n\n---------------------------------------------------------------------------------------------- benchmark 'pandas': 3 tests ----------------------------------------------------------------------------------------------\nName (time in ms)                                Min                   Max                  Mean              StdDev                Median                 IQR            Outliers      OPS            Rounds  Iterations\n-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\ntest_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\ntest_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\ntest_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\n-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n\n----------------------------------------------------------------------------------------------- benchmark 'prefect': 3 tests ----------------------------------------------------------------------------------------------\nName (time in ms)                                 Min                   Max                  Mean              StdDev                Median                 IQR            Outliers       OPS            Rounds  Iterations\n---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\ntest_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\ntest_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\ntest_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\n---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n\n----------------------------------------------------------------------------------------------- benchmark 'pytorch': 3 tests ----------------------------------------------------------------------------------------------\nName (time in ms)                                 Min                   Max                  Mean              StdDev                Median                 IQR            Outliers       OPS            Rounds  Iterations\n---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\ntest_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\ntest_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\ntest_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\n---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n```\n\n### Fetch diagnostics\n\n```shell\n----------------------------------------------------------------------------------------- benchmark 'black': 3 tests ----------------------------------------------------------------------------------------\nName (time in ms)                              Min                 Max                Mean            StdDev              Median               IQR            Outliers      OPS            Rounds  Iterations\n-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\ntest_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\ntest_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\ntest_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\n-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n\n---------------------------------------------------------------------------------------- benchmark 'discord.py': 3 tests -----------------------------------------------------------------------------------------\nName (time in ms)                                   Min                 Max                Mean            StdDev              Median               IQR            Outliers      OPS            Rounds  Iterations\n------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\ntest_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\ntest_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\ntest_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\n------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n\n----------------------------------------------------------------------------------------- benchmark 'homeassistant': 3 tests ----------------------------------------------------------------------------------------\nName (time in ms)                                      Min                 Max                Mean             StdDev              Median               IQR            Outliers     OPS            Rounds  Iterations\n---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\ntest_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\ntest_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\ntest_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\n---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n\n----------------------------------------------------------------------------------------- benchmark 'isort': 3 tests ----------------------------------------------------------------------------------------\nName (time in ms)                              Min                 Max                Mean            StdDev              Median               IQR            Outliers      OPS            Rounds  Iterations\n-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\ntest_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\ntest_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\ntest_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\n-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n\n----------------------------------------------------------------------------------------- benchmark 'jinja': 3 tests ----------------------------------------------------------------------------------------\nName (time in ms)                              Min                 Max                Mean            StdDev              Median                IQR            Outliers     OPS            Rounds  Iterations\n-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\ntest_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\ntest_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\ntest_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\n-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n\n---------------------------------------------------------------------------------------- benchmark 'pandas': 3 tests ----------------------------------------------------------------------------------------\nName (time in ms)                               Min                 Max                Mean            StdDev              Median               IQR            Outliers     OPS            Rounds  Iterations\n-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\ntest_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\ntest_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\ntest_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\n-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n\n----------------------------------------------------------------------------------------- benchmark 'prefect': 3 tests ----------------------------------------------------------------------------------------\nName (time in ms)                                Min                 Max                Mean             StdDev              Median               IQR            Outliers     OPS            Rounds  Iterations\n---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\ntest_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\ntest_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\ntest_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\n---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n\n----------------------------------------------------------------------------------------- benchmark 'pytorch': 3 tests -----------------------------------------------------------------------------------------\nName (time in ms)                                Min                 Max                Mean            StdDev              Median                IQR            Outliers      OPS            Rounds  Iterations\n----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\ntest_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\ntest_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\ntest_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\n----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n```\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Changelog\n\n## 0.0.24\n\nReleased on 2026-03-19.\n\n### Bug fixes\n\n- Ensure `TypedDict` subscripts for unknown keys return `Unknown` ([#23926](https://github.com/astral-sh/ruff/pull/23926))\n- Fix overflow with recursive `TypeIs` ([#23784](https://github.com/astral-sh/ruff/pull/23784))\n- Fix variance of frozen dataclass-transform models ([#23931](https://github.com/astral-sh/ruff/pull/23931))\n\n### LSP server\n\n- Improve [semantic token](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_semanticTokens) classification for attribute access on union types ([#23841](https://github.com/astral-sh/ruff/pull/23841))\n\n### Core type checking\n\n- Improve performance and correctness by avoiding inferring intersection types for call arguments as a result of bidirectional inference ([#23933](https://github.com/astral-sh/ruff/pull/23933))\n- Narrow keyword arguments when unpacking dictionary instances ([#23436](https://github.com/astral-sh/ruff/pull/23436))\n- Discover `/usr/local/lib` dist-packages on Debian/Ubuntu ([#23797](https://github.com/astral-sh/ruff/pull/23797))\n- Sync vendored typeshed stubs ([#23963](https://github.com/astral-sh/ruff/pull/23963)). [Typeshed diff](https://github.com/python/typeshed/compare/fa659b1def704dea3dc8e25c7857b23eac69df4d...f8f0794d0fe249c06dc9f31a004d85be6cca6ced)\n\n## Performance\n\n- Introduce fast path for protocol non-assignability ([#23952](https://github.com/astral-sh/ruff/pull/23952))\n- Improved generic-solver performance in cases involving overload sets ([#23881](https://github.com/astral-sh/ruff/pull/23881))\n\n### Contributors\n\n- [@Geo5](https://github.com/Geo5)\n- [@ibraheemdev](https://github.com/ibraheemdev)\n- [@charliermarsh](https://github.com/charliermarsh)\n- [@dcreager](https://github.com/dcreager)\n- [@ollema](https://github.com/ollema)\n- [@sharkdp](https://github.com/sharkdp)\n\n## 0.0.23\n\nReleased on 2026-03-13.\n\n### Bug fixes\n\n- Fix false-positive diagnostics for PEP-604 union annotations on attribute targets on Python 3.9 when `from __future__ import annotations` is active ([#23915](https://github.com/astral-sh/ruff/pull/23915))\n- `dataclass_transform`: Respect `kw_only` overwrites in dataclasses ([#23930](https://github.com/astral-sh/ruff/pull/23930))\n- Fix too-many-cycle panics when inferring loop variables with `Literal` types ([#23875](https://github.com/astral-sh/ruff/pull/23875))\n\n### Server\n\n- Fix [folding range](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_foldingRange) classification of lines starting with `#` ([#23831](https://github.com/astral-sh/ruff/pull/23831))\n- Fix [folding ranges](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_foldingRange) for notebooks ([#23830](https://github.com/astral-sh/ruff/pull/23830))\n\n### Core type checking\n\n- Split errors for possibly missing submodules into a new `possibly-missing-submodule` error code (enabled by default), and make `possibly-missing-attribute` ignored by default ([#23918](https://github.com/astral-sh/ruff/pull/23918))\n- Improve handling of bidirectional inference when ([#23844](https://github.com/astral-sh/ruff/pull/23844))\n- Fix inference of conditionally defined properties ([#23925](https://github.com/astral-sh/ruff/pull/23925))\n\n### Improvements to diagnostics\n\n- Clarify in diagnostics that `from __future__ import annotations` only stringifies type annotations ([#23928](https://github.com/astral-sh/ruff/pull/23928))\n\n### Performance improvements\n\n- Avoid duplicated work during multi-inference ([#23923](https://github.com/astral-sh/ruff/pull/23923))\n\n### Contributors\n\n- [@ibraheemdev](https://github.com/ibraheemdev)\n- [@sharkdp](https://github.com/sharkdp)\n- [@oconnor663](https://github.com/oconnor663)\n- [@mtshiba](https://github.com/mtshiba)\n- [@MichaReiser](https://github.com/MichaReiser)\n- [@carljm](https://github.com/carljm)\n- [@AlexWaygood](https://github.com/AlexWaygood)\n\n## 0.0.22\n\nReleased on 2026-03-12.\n\n### Bug fixes\n\n- Fix issue where variables could be inferred as `Divergent` if they were assigned using tuple unpacking in loops ([#23812](https://github.com/astral-sh/ruff/pull/23812))\n- Allow `error = \"all\"` in a root `pyproject.toml` file to be overridden using `tool.ty.overrides` in a subdirectory's `pyproject.toml` file ([#23712](https://github.com/astral-sh/ruff/pull/23712))\n- Only unsoundly upcast `type[]` types to their constructor `Callable` type during assignability checks, not during redundancy/subtyping checks ([#23834](https://github.com/astral-sh/ruff/pull/23834), [#23901](https://github.com/astral-sh/ruff/pull/23901))\n- Fix stack overflow that could occur with certain recursive protocols ([#23870](https://github.com/astral-sh/ruff/pull/23870))\n\n### LSP server\n\n- Improve syntax highlighting by fixing [semantic token](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_semanticTokens) classification for generic class members in annotations ([#23811](https://github.com/astral-sh/ruff/pull/23811))\n\n### CLI\n\n- Add `ty explain <RULE>` CLI command ([#23766](https://github.com/astral-sh/ruff/pull/23766))\n\n### Core type checking\n\n- Add validation for type parameters with defaults after `TypeVarTuple` parameters ([#23807](https://github.com/astral-sh/ruff/pull/23807))\n- Allow subtypes of `LiteralString` to be narrowed using equality checks ([#23794](https://github.com/astral-sh/ruff/pull/23794))\n- Detect invalid partially stringified PEP-604 unions ([#23285](https://github.com/astral-sh/ruff/pull/23285))\n- Disambiguate duplicate-looking overloaded callables in union display ([#23907](https://github.com/astral-sh/ruff/pull/23907))\n- Don't promote module-literal types to `types.ModuleType` ([#23786](https://github.com/astral-sh/ruff/pull/23786))\n- Improve type context support for `__setitem__` dunder calls ([#23800](https://github.com/astral-sh/ruff/pull/23800))\n- Infer `t | {\"foo\": int}` as `TD` if `t` is an instance of a TypedDict `td` with a `foo: int` key ([#23806](https://github.com/astral-sh/ruff/pull/23806))\n- Narrow `T` to `T & str` rather than `str` if `T` is a constrained TypeVar with `str` as one of its constraints ([#23850](https://github.com/astral-sh/ruff/pull/23850))\n- Promote `None` to `None | Unknown` in invariant contexts ([#23790](https://github.com/astral-sh/ruff/pull/23790))\n- Reject `type[Callable]` in type annotations ([#23753](https://github.com/astral-sh/ruff/pull/23753))\n- Support enum member access through enum instances and members ([#23772](https://github.com/astral-sh/ruff/pull/23772))\n- Eagerly narrow the type associated with keys of heterogeneous dict literals even when a dict literal appears as a subexpression inside a list or tuple literals ([#23569](https://github.com/astral-sh/ruff/pull/23569))\n- Ensure that `T & ~S` is always inferred as a subtype of `U` during generic inference if `T` is understood as a subtype of `U` ([#23728](https://github.com/astral-sh/ruff/pull/23728))\n- Optimize and improve cycle recovery by preventing \"tainted\" unions in cycle normalization ([#23563](https://github.com/astral-sh/ruff/pull/23563))\n\n### Installer\n\n- Prefer downloading releases from Astral's mirror over GitHub ([#2980](https://github.com/astral-sh/ty/pull/2980))\n\n### Contributors\n\n- [@charliermarsh](https://github.com/charliermarsh)\n- [@MichaReiser](https://github.com/MichaReiser)\n- [@mtshiba](https://github.com/mtshiba)\n- [@AlexWaygood](https://github.com/AlexWaygood)\n- [@ibraheemdev](https://github.com/ibraheemdev)\n- [@ntBre](https://github.com/ntBre)\n- [@oconnor663](https://github.com/oconnor663)\n- [@zsol](https://github.com/zsol)\n\n## 0.0.21\n\nReleased on 2026-03-05.\n\n### Bug fixes\n\n- Avoid stack overflow with recursive typevar ([#23652](https://github.com/astral-sh/ruff/pull/23652))\n- Fix panic on incomplete except handlers ([#23708](https://github.com/astral-sh/ruff/pull/23708))\n- Allow unions of different-length iterables in `*args` unpacking into optional positional parameters ([#23124](https://github.com/astral-sh/ruff/pull/23124))\n- Don't replace `Any` attributes with `object` after `isinstance` narrowing ([#23725](https://github.com/astral-sh/ruff/pull/23725))\n\n### LSP server\n\n- Exclude decorators from class/def code folding ([#23543](https://github.com/astral-sh/ruff/pull/23543))\n- Fix handling of non-Python text documents ([#23704](https://github.com/astral-sh/ruff/pull/23704))\n\n### Configuration\n\n- Add `all` selector to `ty.json` schema ([#23721](https://github.com/astral-sh/ruff/pull/23721))\n- Fix precedence of `all` selector in TOML configurations ([#23723](https://github.com/astral-sh/ruff/pull/23723))\n- Make `all` selector case-sensitive ([#23713](https://github.com/astral-sh/ruff/pull/23713))\n\n### Type checking\n\n- Add `invalid-enum-member-annotation` lint rule ([#23648](https://github.com/astral-sh/ruff/pull/23648))\n- Add a diagnostic for an unused awaitable ([#23650](https://github.com/astral-sh/ruff/pull/23650))\n- Add a diagnostic if a `TypeVar` is used to specialize a `ParamSpec`, or vice versa ([#23738](https://github.com/astral-sh/ruff/pull/23738))\n- Add more type-variable default validation ([#23639](https://github.com/astral-sh/ruff/pull/23639))\n- Add unbound type variable detection in annotations ([#23641](https://github.com/astral-sh/ruff/pull/23641))\n- Apply narrowing to walrus values ([#23687](https://github.com/astral-sh/ruff/pull/23687))\n- Do not union `Unknown` into unannotated container types ([#23718](https://github.com/astral-sh/ruff/pull/23718))\n- Avoid inferring generics with negative intersections ([#23750](https://github.com/astral-sh/ruff/pull/23750))\n- More precise types for `name` and `value` of an enum ([#23683](https://github.com/astral-sh/ruff/pull/23683))\n- Better preserve user-provided union order in inferred specializations ([#23715](https://github.com/astral-sh/ruff/pull/23715))\n- Support narrowing in ternary expressions ([#23726](https://github.com/astral-sh/ruff/pull/23726))\n- Validate bare ParamSpec usage in type annotations, and support stringified ParamSpecs as the first argument to `Callable` ([#23625](https://github.com/astral-sh/ruff/pull/23625))\n\n### Contributors\n\n- [@charliermarsh](https://github.com/charliermarsh)\n- [@zsol](https://github.com/zsol)\n- [@Gankra](https://github.com/Gankra)\n- [@MichaReiser](https://github.com/MichaReiser)\n- [@AlexWaygood](https://github.com/AlexWaygood)\n- [@rizzip](https://github.com/rizzip)\n- [@iksuddle](https://github.com/iksuddle)\n- [@dcreager](https://github.com/dcreager)\n- [@BurntSushi](https://github.com/BurntSushi)\n- [@carljm](https://github.com/carljm)\n- [@oconnor663](https://github.com/oconnor663)\n\n## 0.0.20\n\nReleased on 2026-03-02.\n\n### Bug fixes\n\n- Disallow negative narrowing for `isinstance()` or `issubclass()` checks involving `type[]` types ([#23598](https://github.com/astral-sh/ruff/pull/23598))\n- Fix binary operations between an instance of a `NewType` of `float` and an instance of `Any`/`Unknown` ([#23620](https://github.com/astral-sh/ruff/pull/23620))\n- Fix bug where ty would think that a `Callable` with a variadic positional parameter could be a subtype of a `Callable` with a positional-or-keyword parameter ([#23610](https://github.com/astral-sh/ruff/pull/23610))\n- Fix inference of `t.__mro__` if `t` is an instance of `type[Any]` ([#23632](https://github.com/astral-sh/ruff/pull/23632))\n- Fix overloaded callable assignability for unary `Callable` targets ([#23277](https://github.com/astral-sh/ruff/pull/23277))\n- Limit recursion depth when displaying self-referential function types ([#23647](https://github.com/astral-sh/ruff/pull/23647))\n- Ensure that `python -m ty` works even when ty was installed into an ephemeral virtual environment ([#2852](https://github.com/astral-sh/ty/pull/2852))\n\n### LSP server\n\n- Add support for the LSP protocol's \"type hierarchy\" feature ([#23566](https://github.com/astral-sh/ruff/pull/23566))\n\n### Type checking\n\n- Add more ParamSpec validation for `P.args` and `P.kwargs` ([#23640](https://github.com/astral-sh/ruff/pull/23640))\n- Ban nested `Required`/`NotRequired`, and ban them both outside of `TypedDict` fields ([#23627](https://github.com/astral-sh/ruff/pull/23627))\n- Detect inconsistent generic base class specializations that appear in the same MRO ([#23615](https://github.com/astral-sh/ruff/pull/23615))\n- Detect invalid uses of `@final` on non-methods ([#23604](https://github.com/astral-sh/ruff/pull/23604))\n- Add partial support and validation for `Unpack` when used with tuple types ([#23651](https://github.com/astral-sh/ruff/pull/23651))\n- Recurse into tuples and nested tuples when applying special-cased validation of arguments passed to `isinstance()` and `issubclass()` ([#23607](https://github.com/astral-sh/ruff/pull/23607))\n- Reject ellipsis literals in odd places in type/annotation expressions ([#23611](https://github.com/astral-sh/ruff/pull/23611))\n- Reject functions with PEP-695 type parameters that shadow type parameters from enclosing scopes ([#23619](https://github.com/astral-sh/ruff/pull/23619))\n- Reject generic metaclasses parameterized by type variables ([#23628](https://github.com/astral-sh/ruff/pull/23628))\n- Treat `dataclass_transform` dataclasses as neither frozen nor non-frozen ([#23366](https://github.com/astral-sh/ruff/pull/23366))\n- Validate that type variable defaults don't reference later type parameters or type parameters out of scope ([#23623](https://github.com/astral-sh/ruff/pull/23623))\n\n### Typeshed\n\n- Sync vendored typeshed stubs ([#23642](https://github.com/astral-sh/ruff/pull/23642)). [Typeshed diff](https://github.com/python/typeshed/compare/1b3cec156330a93f6bb22b6636bca38c27f8f721...843c1fd5a148da85e523c1b4ee680226f89986aa)\n\n### Contributors\n\n- [@Hugo-Polloli](https://github.com/Hugo-Polloli)\n- [@zanieb](https://github.com/zanieb)\n- [@sharkdp](https://github.com/sharkdp)\n- [@mtshiba](https://github.com/mtshiba)\n- [@carljm](https://github.com/carljm)\n- [@charliermarsh](https://github.com/charliermarsh)\n- [@sinon](https://github.com/sinon)\n- [@BurntSushi](https://github.com/BurntSushi)\n- [@oconnor663](https://github.com/oconnor663)\n- [@AlexWaygood](https://github.com/AlexWaygood)\n- [@zsol](https://github.com/zsol)\n\n## 0.0.19\n\nReleased on 2026-02-26.\n\n### Bug fixes\n\n- Fix panic in diagnostic rendering when attempting to render a code frame pointing to leading whitespace ([#23458](https://github.com/astral-sh/ruff/pull/23458))\n- Fix panics and incorrect inference stemming from incorrectly considering overloads in another file as being associated with a function in the file being checked ([#21977](https://github.com/astral-sh/ruff/pull/21977))\n- Fix panic when attempting to narrow the type of a dictionary key that was assigned using a multi-target assignment, e.g. `x = y = {\"a\": 1}` ([#23523](https://github.com/astral-sh/ruff/pull/23523))\n- Fix infinite hang on mutually recursive `TypeAliasType` definitions ([#23397](https://github.com/astral-sh/ruff/pull/23397))\n\n### LSP server\n\n- Fix inlay hints for starred unpacking targets ([#23454](https://github.com/astral-sh/ruff/pull/23454))\n\n### Core type checking\n\n- Fix assignability, subtyping and equivalence checks relating to `typing.Generator` prior to Python 3.13 ([#23386](https://github.com/astral-sh/ruff/pull/23386))\n- Understand that a scope's control flow terminates after `await foo()` if `foo` returns `typing.Awaitable[typing.Never]` or similar ([#23479](https://github.com/astral-sh/ruff/pull/23479))\n- Implement stricter handling of calls to instances of `type[T]` types ([#23472](https://github.com/astral-sh/ruff/pull/23472))\n- Support basic type narrowing for `case {...}:` patterns in `match` statements ([#23462](https://github.com/astral-sh/ruff/pull/23462))\n- Fix bugs that could manifest in incorrect overload evaluation, false-positive complaints regarding `assert_type` calls or false-positive `redundant-cast` diagnostics by reimplementing the equivalence type relation as mutual subtyping of top and bottom materializations ([#23428](https://github.com/astral-sh/ruff/pull/23428))\n- Fix equality and `__contains__` narrowing with PEP-695 type aliases ([#23545](https://github.com/astral-sh/ruff/pull/23545))\n- Support `_value_` annotations on enum classes ([#22228](https://github.com/astral-sh/ruff/pull/22228))\n\n### Improvements to diagnostics\n\n- Improve diagnostics when attempting to specialize non-generic types ([#23516](https://github.com/astral-sh/ruff/pull/23516))\n- Render subdiagnostics when `--output-format=github` is specified ([#23455](https://github.com/astral-sh/ruff/pull/23455))\n\n### Performance\n\n- Add a cached method for calculating the intersection of two types ([#23547](https://github.com/astral-sh/ruff/pull/23547))\n- Add a cached method for calculating the union of two types ([#23565](https://github.com/astral-sh/ruff/pull/23565))\n- Reduce the threshold above which `Literal` types in unions are upcasted to nominal-instance types in situations where the union type is recursively defined ([#23521](https://github.com/astral-sh/ruff/pull/23521))\n- Control flow: isolate the calculation of \"loop header reachability\" in a dedicated, cached function ([#23520](https://github.com/astral-sh/ruff/pull/23520))\n\n### Contributors\n\n- [@AlexWaygood](https://github.com/AlexWaygood)\n- [@silamon](https://github.com/silamon)\n- [@ibraheemdev](https://github.com/ibraheemdev)\n- [@Hugo-Polloli](https://github.com/Hugo-Polloli)\n- [@charliermarsh](https://github.com/charliermarsh)\n- [@knutwannheden](https://github.com/knutwannheden)\n- [@oconnor663](https://github.com/oconnor663)\n- [@carljm](https://github.com/carljm)\n- [@mtshiba](https://github.com/mtshiba)\n\n## 0.0.18\n\nReleased on 2026-02-20.\n\n### Bug fixes\n\n- Support classes dynamically created via `type(...)` with cyclic bases ([#22792](https://github.com/astral-sh/ruff/pull/22792))\n- Fix incorrect types inferred when unpacking mixed tuples ([#23437](https://github.com/astral-sh/ruff/pull/23437))\n- Fix stack overflow for self-referential `TypeOf` in annotations ([#23407](https://github.com/astral-sh/ruff/pull/23407))\n- Fix several server panics that could occur when computing semantic tokens for the current file ([#23403](https://github.com/astral-sh/ruff/pull/23403)), [#23398](https://github.com/astral-sh/ruff/pull/23398), [#23401](https://github.com/astral-sh/ruff/pull/23401))\n\n### LSP server\n\n- Add code folding support ([#23393](https://github.com/astral-sh/ruff/pull/23393))\n- Add warning message when running `ty server` interactively ([#23416](https://github.com/astral-sh/ruff/pull/23416))\n- Exclude test-related symbols from non-first-party packages in auto-import completions ([#23252](https://github.com/astral-sh/ruff/pull/23252))\n- Fix bug where diagnostics could disappear after opening an external file ([#23447](https://github.com/astral-sh/ruff/pull/23447))\n- Remove spurious destination for Go-To Definition on variables defined in a loop ([#23391](https://github.com/astral-sh/ruff/pull/23391))\n- Use the fully qualified name when \"baking\" an inlay hint into the source code if the scope already contains a variable with the same name as the unqualified name ([#23265](https://github.com/astral-sh/ruff/pull/23265))\n- Resolve TypeVars in `call_signature_details` parameter types ([#23149](https://github.com/astral-sh/ruff/pull/23149))\n\n### CLI\n\n- Add `--output-format` to `ty version` ([#23387](https://github.com/astral-sh/ruff/pull/23387))\n\n### Configuration\n\n- Add `replace-imports-with-any` option ([#23122](https://github.com/astral-sh/ruff/pull/23122))\n- Support shellexpand for configuration paths ([#23274](https://github.com/astral-sh/ruff/pull/23274))\n\n### Type checking\n\n- Add a new diagnostic to detect invalid class patterns in `match` statements ([#22939](https://github.com/astral-sh/ruff/pull/22939))\n- Allow `Self` in `ClassVar` type annotations ([#23362](https://github.com/astral-sh/ruff/pull/23362))\n- Consider synthesized methods and `ClassVar`-qualified declarations when determining whether an abstract method has been overridden in a subclass ([#23381](https://github.com/astral-sh/ruff/pull/23381))\n- Add a diagnostic when combining `Final` and `ClassVar` ([#23365](https://github.com/astral-sh/ruff/pull/23365))\n- Fix return type of `assert_never` ([#23389](https://github.com/astral-sh/ruff/pull/23389))\n- Fix `assert_type` diagnostic messages ([#23342](https://github.com/astral-sh/ruff/pull/23342))\n- Ban PEP-613 type alias values from containing type-qualifier special forms ([#23444](https://github.com/astral-sh/ruff/pull/23444))\n- Infer `LiteralString` for `f\"{literal_str_a} {literal_str_b}\"` ([#23346](https://github.com/astral-sh/ruff/pull/23346))\n- Infer precise types for bit-shift operations on integer literals ([#23301](https://github.com/astral-sh/ruff/pull/23301))\n- Make `[abstract-method-in-final-class]` diagnostics less verbose for classes with many abstract methods ([#23379](https://github.com/astral-sh/ruff/pull/23379))\n- Improve diagnostics for abstract `@final` classes ([#23376](https://github.com/astral-sh/ruff/pull/23376))\n- Only perform literal promotion for implicitly inferred literals ([#23107](https://github.com/astral-sh/ruff/pull/23107))\n- Parenthesize callable types when they appear in the return annotation of other callable types ([#23327](https://github.com/astral-sh/ruff/pull/23327))\n- Consider a call to a generic function returning `Never` to terminate control flow ([#23419](https://github.com/astral-sh/ruff/pull/23419))\n- Support calls to intersection types ([#22469](https://github.com/astral-sh/ruff/pull/22469))\n- Validate annotated assignments to attributes on self ([#23388](https://github.com/astral-sh/ruff/pull/23388))\n- Treat a bytes-literal type as a subtype of `Sequence[<constituent integers in the bytestring>]` ([#23329](https://github.com/astral-sh/ruff/pull/23329))\n- Allow a string-literal argument to match against an `Iterable` parameter in type variable inference. ([#23326](https://github.com/astral-sh/ruff/pull/23326))\n- Support narrowing from a `Callable` type returning a `TypeGuard` type ([#23280](https://github.com/astral-sh/ruff/pull/23280))\n\n### Performance\n\n- Consider all code paths as being ambiguously reachable in cases with pathologically large control-flow graphs ([#23399](https://github.com/astral-sh/ruff/pull/23399))\n\n### Typeshed\n\n- Sync vendored typeshed stubs ([#23279](https://github.com/astral-sh/ruff/pull/23279), [Typeshed diff](https://github.com/python/typeshed/compare/fa659b1def704dea3dc8e25c7857b23eac69df4d...1b3cec156330a93f6bb22b6636bca38c27f8f721))\n\n### Contributors\n\n- [@toby-bro](https://github.com/toby-bro)\n- [@Hugo-Polloli](https://github.com/Hugo-Polloli)\n- [@MatthewMckee4](https://github.com/MatthewMckee4)\n- [@BurntSushi](https://github.com/BurntSushi)\n- [@ibraheemdev](https://github.com/ibraheemdev)\n- [@knutwannheden](https://github.com/knutwannheden)\n- [@Glyphack](https://github.com/Glyphack)\n- [@charliermarsh](https://github.com/charliermarsh)\n- [@AlexWaygood](https://github.com/AlexWaygood)\n- [@abhijeetbodas2001](https://github.com/abhijeetbodas2001)\n- [@carljm](https://github.com/carljm)\n- [@sharkdp](https://github.com/sharkdp)\n\n## 0.0.17\n\nReleased on 2026-02-13.\n\n### Bug fixes\n\n- Avoid `Literal` promotion for constrained `TypeVar`s with `Literal` bounds ([#23209](https://github.com/astral-sh/ruff/pull/23209))\n- Fix false positives in `TypeVar` shadowing checks ([#23222](https://github.com/astral-sh/ruff/pull/23222))\n\n### Core type checking\n\n- Support generic protocols ([#21902](https://github.com/astral-sh/ruff/pull/21902))\n- Perform control-flow analysis in loops ([#22794](https://github.com/astral-sh/ruff/pull/22794))\n- Support `typing.Self` in attribute annotations ([#23108](https://github.com/astral-sh/ruff/pull/23108))\n- Support type narrowing in situations with calls to `NoReturn` functions ([#23109](https://github.com/astral-sh/ruff/pull/23109))\n- Support type narrowing and reachability analysis based on `os.name` checks ([#23230](https://github.com/astral-sh/ruff/pull/23230))\n- Detect overrides of `Final` class variables in subclasses ([#23180](https://github.com/astral-sh/ruff/pull/23180))\n- Fix bound method access on `None` ([#23246](https://github.com/astral-sh/ruff/pull/23246))\n- Fix method calls on subclasses of `Any` ([#23248](https://github.com/astral-sh/ruff/pull/23248))\n- Disallow type variables within PEP-695 type variable bounds and constraints ([#22982](https://github.com/astral-sh/ruff/pull/22982))\n- Emit error for attribute access on union where some elements lack the attribute ([#23042](https://github.com/astral-sh/ruff/pull/23042))\n- Emit error for invalid typevar defaults ([#23194](https://github.com/astral-sh/ruff/pull/23194))\n- Improve display of `ParamSpec`s in some situations ([#23211](https://github.com/astral-sh/ruff/pull/23211))\n\n### LSP server\n\n- Add hover and go-to-declaration support for subscript literals ([#22837](https://github.com/astral-sh/ruff/pull/22837))\n- Assign lower completion ranking to deprecated names in auto import ([#23188](https://github.com/astral-sh/ruff/pull/23188))\n- Improve spans of references to submodules imported in an `__init__.py` ([#21795](https://github.com/astral-sh/ruff/pull/21795))\n- Include conditional symbols (like `datetime.UTC`) in auto-import in more cases ([#23249](https://github.com/astral-sh/ruff/pull/23249))\n- Support auto-import for symbols in inlay hints ([#22111](https://github.com/astral-sh/ruff/pull/22111))\n- Include overload declarations in find-references ([#23215](https://github.com/astral-sh/ruff/pull/23215))\n\n### Performance\n\n- Avoid `UnionBuilder` overhead when creating a new union from the filtered elements of an existing union ([#22352](https://github.com/astral-sh/ruff/pull/22352))\n\n### Other changes\n\n- Allow discovering dependencies in system Python environments ([#22994](https://github.com/astral-sh/ruff/pull/22994))\n- Apply workspace settings to virtual files ([#23228](https://github.com/astral-sh/ruff/pull/23228))\n- Add support for `--output-format=junit` ([#22125](https://github.com/astral-sh/ruff/pull/22125))\n- Use a smaller diagnostic range for `inconsistent-mro` diagnostics ([#23213](https://github.com/astral-sh/ruff/pull/23213))\n\n### Contributors\n\n- [@carljm](https://github.com/carljm)\n- [@BurntSushi](https://github.com/BurntSushi)\n- [@charliermarsh](https://github.com/charliermarsh)\n- [@Glyphack](https://github.com/Glyphack)\n- [@cetanu](https://github.com/cetanu)\n- [@AlexWaygood](https://github.com/AlexWaygood)\n- [@joelostblom](https://github.com/joelostblom)\n- [@Gankra](https://github.com/Gankra)\n- [@mtshiba](https://github.com/mtshiba)\n- [@MatthewMckee4](https://github.com/MatthewMckee4)\n- [@Hugo-Polloli](https://github.com/Hugo-Polloli)\n- [@sharkdp](https://github.com/sharkdp)\n- [@alex](https://github.com/alex)\n- [@dcreager](https://github.com/dcreager)\n- [@oconnor663](https://github.com/oconnor663)\n\n## 0.0.16\n\nReleased on 2026-02-10.\n\n### Bug fixes\n\n- Allow stringified argument in PEP-613 alias to `Optional` ([#23200](https://github.com/astral-sh/ruff/pull/23200))\n- Fix fuzzer panic on slice expression in unclosed comprehension ([#23146](https://github.com/astral-sh/ruff/pull/23146))\n- Fix combinatorial explosion due to fixed-length tuple expansion in overload matching ([#23190](https://github.com/astral-sh/ruff/pull/23190))\n- Respect `@no_type_check` when combined with other decorators ([#23177](https://github.com/astral-sh/ruff/pull/23177))\n- Fix diagnostic location for an incorrect sub-call to a specialized ParamSpec ([#23036](https://github.com/astral-sh/ruff/pull/23036))\n\n### LSP server\n\n- Assign lower completions ranking to deprecated functions and classes ([#23089](https://github.com/astral-sh/ruff/pull/23089))\n- Change goto-def for class constructors to always go to class definition ([#23071](https://github.com/astral-sh/ruff/pull/23071))\n- Ensure diagnostic mode is consistent across projects inside the LSP server ([#23121](https://github.com/astral-sh/ruff/pull/23121))\n- Don't include the class `Foo` in autocomplete suggestions when the user is typing out `Foo`'s bases ([#23141](https://github.com/astral-sh/ruff/pull/23141))\n- Fix parameter references across files via keyword args ([#23012](https://github.com/astral-sh/ruff/pull/23012))\n- Fix wrong inlay hints for overloaded function arguments ([#23179](https://github.com/astral-sh/ruff/pull/23179))\n- Support diagnostics in newly created files inside neovim ([#23095](https://github.com/astral-sh/ruff/pull/23095))\n- Exclude already-included classes when providing completion suggestions for class bases ([#23085](https://github.com/astral-sh/ruff/pull/23085))\n\n### CLI\n\n- Add support for `TY_OUTPUT_FORMAT` environment variable ([#23123](https://github.com/astral-sh/ruff/pull/23123))\n- Fall back to `python3` found in `$PATH` if no environment is found ([#22843](https://github.com/astral-sh/ruff/pull/22843))\n\n### Type checking\n\n- Add `inconsistent-mro` autofix to move `Generic[]` to the end of the bases list ([#22998](https://github.com/astral-sh/ruff/pull/22998))\n- Add precise return-type inference for `struct.unpack` ([#22562](https://github.com/astral-sh/ruff/pull/22562), [#23130](https://github.com/astral-sh/ruff/pull/23130))\n- Disallow TypeVars within ClassVars ([#23184](https://github.com/astral-sh/ruff/pull/23184))\n- Emit diagnostic on unbound call to abstract `@classmethod` or `@staticmethod` ([#23182](https://github.com/astral-sh/ruff/pull/23182))\n- Fix false-positive diagnostics when providing the `total=` keyword to `TypedDict` classes that had PEP-695 type parameters ([#23114](https://github.com/astral-sh/ruff/pull/23114))\n- Narrow both left- and right-hand operands where possible ([#23084](https://github.com/astral-sh/ruff/pull/23084))\n- Narrow chained operators ([#23093](https://github.com/astral-sh/ruff/pull/23093))\n- Narrow equality subscripts on either operand ([#23104](https://github.com/astral-sh/ruff/pull/23104))\n- Recognize `__dataclass_transform__` to support SQLModel ([#23070](https://github.com/astral-sh/ruff/pull/23070))\n- Relax the attribute narrowing condition to support deeper-nested attribute type narrowing ([#22440](https://github.com/astral-sh/ruff/pull/22440))\n- Support constrained TypeVar compatibility across function boundaries ([#23103](https://github.com/astral-sh/ruff/pull/23103))\n- Support comparison methods (`__gt__`, etc.) where a parameter is annotated with a `Literal` type ([#23100](https://github.com/astral-sh/ruff/pull/23100))\n- Support partially specialized type context ([#22748](https://github.com/astral-sh/ruff/pull/22748))\n- Use type context when inferring constructor argument types ([#23139](https://github.com/astral-sh/ruff/pull/23139))\n- Validate `TypedDict` constructor calls for generic aliases and `type[...]` targets ([#23113](https://github.com/astral-sh/ruff/pull/23113))\n\n### Performance\n\n- Conservative narrowing places optimization ([#22734](https://github.com/astral-sh/ruff/pull/22734))\n\n### Contributors\n\n- [@rbange](https://github.com/rbange)\n- [@rayzeller](https://github.com/rayzeller)\n- [@charliermarsh](https://github.com/charliermarsh)\n- [@11happy](https://github.com/11happy)\n- [@figsoda](https://github.com/figsoda)\n- [@mtshiba](https://github.com/mtshiba)\n- [@ibraheemdev](https://github.com/ibraheemdev)\n- [@ngnpope](https://github.com/ngnpope)\n- [@sakgoyal](https://github.com/sakgoyal)\n- [@oconnor663](https://github.com/oconnor663)\n- [@ericmarkmartin](https://github.com/ericmarkmartin)\n- [@Hugo-Polloli](https://github.com/Hugo-Polloli)\n- [@Glyphack](https://github.com/Glyphack)\n- [@sharkdp](https://github.com/sharkdp)\n- [@carljm](https://github.com/carljm)\n- [@BurntSushi](https://github.com/BurntSushi)\n\n## 0.0.15\n\nReleased on 2026-02-04.\n\n### Bug fixes\n\n- Add support for resolving imports of packages installed into Debian/Ubuntu `dist-packages` directories ([#22466](https://github.com/astral-sh/ruff/pull/22466))\n- Avoid `not-iterable` false positives when iterating over an instance of an intersection type with only negated elements ([#22089](https://github.com/astral-sh/ruff/pull/22089))\n- Fix support for stringized annotations in very large files ([#22913](https://github.com/astral-sh/ruff/pull/22913))\n- Don't emit Liskov diagnostics for methods with mangled names ([#23062](https://github.com/astral-sh/ruff/pull/23062))\n- Enforce that a `Final` symbol cannot be reassigned even after a conditional binding ([#22986](https://github.com/astral-sh/ruff/pull/22986))\n- Fix TypedDict construction from existing TypedDict values ([#22904](https://github.com/astral-sh/ruff/pull/22904))\n- Fix `Self` resolution for classes nested within methods ([#22964](https://github.com/astral-sh/ruff/pull/22964))\n- Fix bidirectional inference with PEP 695 union type aliases ([#22988](https://github.com/astral-sh/ruff/pull/22988))\n- Fix edge-case bugs when narrowing tagged unions in `match` statements ([#22870](https://github.com/astral-sh/ruff/pull/22870))\n- Fix false-positive diagnostics when iterating over an instance of an intersection that includes a TypeVar of which the upper bound is a union where the union includes a non-iterable type ([#22117](https://github.com/astral-sh/ruff/pull/22117))\n- Fix lookup of `__contains__` to respect descriptors ([#23056](https://github.com/astral-sh/ruff/pull/23056))\n- Fix narrowing of `nonlocal` variables with conditional assignments ([#22966](https://github.com/astral-sh/ruff/pull/22966))\n- Fix several bugs that could affect `NewType`s of `NewType`s of `float` ([#22997](https://github.com/astral-sh/ruff/pull/22997))\n- Fix several type narrowing bugs involving PEP-695 type aliases ([#22894](https://github.com/astral-sh/ruff/pull/22894))\n- Fix spurious query cycles in decorated functions with parameter defaults, for improved performance and improved determinism ([#23014](https://github.com/astral-sh/ruff/pull/23014))\n- Fix unary and comparison operators for TypeVars with union bounds ([#22925](https://github.com/astral-sh/ruff/pull/22925))\n- Understand functions as method descriptors even if they are decorated with a decorator annotated as returning a PEP-695 alias to a `Callable` type ([#22902](https://github.com/astral-sh/ruff/pull/22902))\n- `dataclass_transform`: Fix visibility of field specifiers when models are nested inside methods ([#23069](https://github.com/astral-sh/ruff/pull/23069))\n\n### LSP server\n\n- Fix hover showing `Unknown` for bare `Final` instance attributes ([#23003](https://github.com/astral-sh/ruff/pull/23003))\n- Improve support for goto-type, goto-declaration, hover, and highlighting of string annotations ([#22878](https://github.com/astral-sh/ruff/pull/22878))\n- Include setters and deleters when renaming properties ([#22999](https://github.com/astral-sh/ruff/pull/22999))\n- Show type qualifiers like `Final` in on-hover hints ([#23005](https://github.com/astral-sh/ruff/pull/23005))\n\n### Configuration\n\n- Add new `unused-type-ignore-comment` rule ([#22790](https://github.com/astral-sh/ruff/pull/22790))\n- Add a mechanism to ignore/warn/select all rules ([#22832](https://github.com/astral-sh/ruff/pull/22832))\n- Support multiple workspace folders in a single ty LSP server instance ([#22953](https://github.com/astral-sh/ruff/pull/22953))\n- Only add `./src` as a search path if `./src/__init__.py(i)` does not exist ([#22851](https://github.com/astral-sh/ruff/pull/22851))\n\n### Type checking\n\n- Add a diagnostic detecting if a variable is declared as `Final` but never has any bindings ([#23001](https://github.com/astral-sh/ruff/pull/23001))\n- Add a diagnostic detecting overridden comparison dunder methods on `order=True` dataclasses ([#22689](https://github.com/astral-sh/ruff/pull/22689))\n- Add a hint to `invalid-argument-type` and `invalid-assignment` diagnostics if a variable is annotated with a type from the `numbers` module ([#22931](https://github.com/astral-sh/ruff/pull/22931), [#22938](https://github.com/astral-sh/ruff/pull/22938))\n- Add diagnostic hint on `unresolved-reference` to suggest using \"list\" instead of \"List\" ([#22827](https://github.com/astral-sh/ruff/pull/22827))\n- Add new diagnostic for invalid dataclass field orders ([#19825](https://github.com/astral-sh/ruff/pull/19825))\n- Allow a subclass method with a positional-only parameter to override a superclass method without that parameter if the parameter in the subclass method has a default value ([#23037](https://github.com/astral-sh/ruff/pull/23037))\n- Allow self-referential imports outside the global scope ([#22963](https://github.com/astral-sh/ruff/pull/22963))\n- Ban `...` in odd places inside tuple specializations ([#22889](https://github.com/astral-sh/ruff/pull/22889))\n- Ban `Required`, `NotRequired` and `ReadOnly` in parameter annotations ([#22888](https://github.com/astral-sh/ruff/pull/22888))\n- Ban legacy `TypeVar` bounds or constraints from containing type variables ([#22949](https://github.com/astral-sh/ruff/pull/22949))\n- Ban multiple unpacked variadic tuples in a `tuple` specialization ([#22884](https://github.com/astral-sh/ruff/pull/22884))\n- Detect generic `Callable`s in the return type of function signatures ([#22954](https://github.com/astral-sh/ruff/pull/22954))\n- Detect invalid `isinstance()` and `issubclass()` calls against `TypedDict` classes ([#22887](https://github.com/astral-sh/ruff/pull/22887))\n- Detect invalid `issubclass()` calls against `Protocol` classes with non-method members ([#22896](https://github.com/astral-sh/ruff/pull/22896))\n- Detect invalid attempts to subclass `Protocol[]` and `Generic[]` simultaneously ([#22948](https://github.com/astral-sh/ruff/pull/22948))\n- Emit a diagnostic on incorrect applications of the legacy convention for specifying positional-only parameters ([#22943](https://github.com/astral-sh/ruff/pull/22943))\n- Emit an error if a `TypeVarTuple` is used to subscript `Generic` or `Protocol` without being unpacked ([#22952](https://github.com/astral-sh/ruff/pull/22952))\n- Fallback to metaclass `__getattr__` or `__getattribute__` when looking up attributes on class objects ([#22985](https://github.com/astral-sh/ruff/pull/22985))\n- Fix a bug where an overridden type in a dataclass subclass would not be respected if the dataclass subclass field had a default value but the superclass field did not ([#22965](https://github.com/astral-sh/ruff/pull/22965))\n- Improve bidirectional type inference involving PEP-695 type aliases ([#22989](https://github.com/astral-sh/ruff/pull/22989))\n- Improve detection of invalid `NewType`s with generic bases ([#22961](https://github.com/astral-sh/ruff/pull/22961))\n- Improve reachability analysis when evaluating the truthiness of expressions that involve variables that may not be bound in all code paths ([#22971](https://github.com/astral-sh/ruff/pull/22971))\n- Improve the error message if `**` is used with a non-mapping in the context of a call to an overloaded function ([#22921](https://github.com/astral-sh/ruff/pull/22921))\n- Infer `ParamSpec` from class constructors for callable protocols ([#22853](https://github.com/astral-sh/ruff/pull/22853))\n- Move the location of some `invalid-overload` diagnostics ([#22933](https://github.com/astral-sh/ruff/pull/22933))\n- Point to an overload with an invalid `@final` decorator when emitting `invalid-overload` errors for invalid `@final` decorators ([#22893](https://github.com/astral-sh/ruff/pull/22893))\n- Avoid false positives when iterating over an instance of an intersection with only negated elements by preserving \"pure negation\" types in descriptor lookups ([#22907](https://github.com/astral-sh/ruff/pull/22907))\n- Promote `Literal` types when inferring elements for very large unannotated tuples, for improved performance ([#22841](https://github.com/astral-sh/ruff/pull/22841))\n- Recognize functions with stub bodies in `Protocol` classes as implicitly abstract ([#22838](https://github.com/astral-sh/ruff/pull/22838))\n- Reduce false positives involving heterogeneous dicts by tracking dictionary literal keys as individual places ([#22882](https://github.com/astral-sh/ruff/pull/22882))\n- Reduce false positives when subscripting classes generic over `TypeVarTuple`s ([#22950](https://github.com/astral-sh/ruff/pull/22950))\n- Remove special handling for `Any()` in `match` class patterns ([#23011](https://github.com/astral-sh/ruff/pull/23011))\n- Support `type[None]` in type expressions ([#22892](https://github.com/astral-sh/ruff/pull/22892))\n- Support legacy namespace packages declared using `pkg_resources.declare_namespace` ([#22987](https://github.com/astral-sh/ruff/pull/22987))\n- Sync vendored typeshed stubs ([#23006](https://github.com/astral-sh/ruff/pull/23006)), [Typeshed diff](https://github.com/python/typeshed/compare/cd8b26b0ceef26cd84ab614088140d48680ac7f7...fa659b1def704dea3dc8e25c7857b23eac69df4d)\n- Validate signatures of dataclass `__post_init__` methods ([#22730](https://github.com/astral-sh/ruff/pull/22730))\n\n### Contributors\n\n- [@charliermarsh](https://github.com/charliermarsh)\n- [@stefanvanburen](https://github.com/stefanvanburen)\n- [@ibraheemdev](https://github.com/ibraheemdev)\n- [@abhijeetbodas2001](https://github.com/abhijeetbodas2001)\n- [@MichaReiser](https://github.com/MichaReiser)\n- [@dcreager](https://github.com/dcreager)\n- [@PrettyWood](https://github.com/PrettyWood)\n- [@sharkdp](https://github.com/sharkdp)\n- [@oconnor663](https://github.com/oconnor663)\n- [@Feiyang472](https://github.com/Feiyang472)\n- [@denyszhak](https://github.com/denyszhak)\n- [@mtshiba](https://github.com/mtshiba)\n- [@AlexWaygood](https://github.com/AlexWaygood)\n- [@11happy](https://github.com/11happy)\n- [@BurntSushi](https://github.com/BurntSushi)\n- [@carljm](https://github.com/carljm)\n- [@Gankra](https://github.com/Gankra)\n- [@MentalMegalodon](https://github.com/MentalMegalodon)\n- [@thejchap](https://github.com/thejchap)\n\n## 0.0.14\n\nReleased on 2026-01-26.\n\n### Bug fixes\n\n- Consider keyword arguments when unpacking a variadic argument ([#22796](https://github.com/astral-sh/ruff/pull/22796))\n- Fix binary operator false-positive for constrained TypeVars ([#22782](https://github.com/astral-sh/ruff/pull/22782))\n- Fix docstring rendering for literal blocks after doctests ([#22676](https://github.com/astral-sh/ruff/pull/22676))\n- Fix false-positive `unsupported-operator` for \"symmetric\" TypeVars ([#22756](https://github.com/astral-sh/ruff/pull/22756))\n- Fix panic when overriding a final method using an assignment ([#22831](https://github.com/astral-sh/ruff/pull/22831))\n- Fix unary operator false-positive for constrained TypeVars ([#22783](https://github.com/astral-sh/ruff/pull/22783))\n- Fix generic functions with a generic (ParamSpec) decorator ([#22544](https://github.com/astral-sh/ruff/pull/22544))\n- Fix `memo.changed_at` assertion panics ([#22498](https://github.com/astral-sh/ruff/pull/22498))\n\n### LSP server\n\n- Look up attributes on metaclasses for Go to Definition ([#22758](https://github.com/astral-sh/ruff/pull/22758))\n- Suppress type inlay hints for leading-underscore assignments ([#22855](https://github.com/astral-sh/ruff/pull/22855))\n\n### Configuration\n\n- Add `allowed-unresolved-imports` setting ([#22800](https://github.com/astral-sh/ruff/pull/22800))\n\n### Other changes\n\n- Add `assert-type-unspellable-subtype` diagnostic, for failed `assert_type()` where the actual type is a subtype of the named type that can't be spelled in a type expression ([#22815](https://github.com/astral-sh/ruff/pull/22815))\n- Add a new `empty-body` return code for functions with stub bodies that have non-`None` return annotations ([#22846](https://github.com/astral-sh/ruff/pull/22846))\n- Add diagnostic disambiguation for different type aliases with the same name ([#22852](https://github.com/astral-sh/ruff/pull/22852))\n- Add support for dict literals and dict() calls as default values for parameters with TypedDict types ([#22161](https://github.com/astral-sh/ruff/pull/22161))\n- Add support for subscripts on intersections ([#22654](https://github.com/astral-sh/ruff/pull/22654))\n- Avoid duplicate syntax errors for `await` outside functions ([#22826](https://github.com/astral-sh/ruff/pull/22826))\n- Emit an error if the same type parameter appears more than once in a `Generic[]` subscript ([#22738](https://github.com/astral-sh/ruff/pull/22738))\n- Emit diagnostic for unimplemented abstract method on @final class ([#22753](https://github.com/astral-sh/ruff/pull/22753))\n- Fix GitLab Code Quality output format for empty diagnostics ([#22833](https://github.com/astral-sh/ruff/pull/22833))\n- Fix assignment in decorated method causing `Unknown` fallback ([#22778](https://github.com/astral-sh/ruff/pull/22778))\n- Fix false negative when using a non-runtime-checkable protocol in a `match` class pattern ([#22836](https://github.com/astral-sh/ruff/pull/22836))\n- Improve completion rankings for raise-from/except contexts ([#22775](https://github.com/astral-sh/ruff/pull/22775))\n- Improve invalid assignment diagnostics with type context ([#22643](https://github.com/astral-sh/ruff/pull/22643))\n- Improve support for kwarg splats in dictionary literals ([#22781](https://github.com/astral-sh/ruff/pull/22781))\n- Infer `TypedDict` types with >=1 required key as being always truthy ([#22808](https://github.com/astral-sh/ruff/pull/22808))\n- Point to an overload with an invalid `@final` decoator when emitting `invalid-overload` errors for invalid `@final` decorators ([#22812](https://github.com/astral-sh/ruff/pull/22812))\n- Require both `*args` and `**kwargs` when calling a `ParamSpec` callable ([#22820](https://github.com/astral-sh/ruff/pull/22820))\n- Stricter validation of `TypedDict` definitions ([#22811](https://github.com/astral-sh/ruff/pull/22811))\n- Support recursive and stringified annotations in functional `typing.NamedTuple`s ([#22718](https://github.com/astral-sh/ruff/pull/22718))\n- Support solving generics involving PEP 695 type aliases ([#22678](https://github.com/astral-sh/ruff/pull/22678))\n- Use a more lenient fallback type for failed `namedtuple()` and `NamedTuple` calls ([#22765](https://github.com/astral-sh/ruff/pull/22765))\n- Use type context from augmented assignment dunder calls ([#22540](https://github.com/astral-sh/ruff/pull/22540))\n- Check that starred arguments in function calls are iterable ([#22805](https://github.com/astral-sh/ruff/pull/22805))\n\n### Contributors\n\n- [@AlexWaygood](https://github.com/AlexWaygood)\n- [@maifeeulasad](https://github.com/maifeeulasad)\n- [@RasmusNygren](https://github.com/RasmusNygren)\n- [@ntBre](https://github.com/ntBre)\n- [@Imbuzi](https://github.com/Imbuzi)\n- [@dhruvmanila](https://github.com/dhruvmanila)\n- [@ibraheemdev](https://github.com/ibraheemdev)\n- [@carljm](https://github.com/carljm)\n- [@Hugo-Polloli](https://github.com/Hugo-Polloli)\n- [@charliermarsh](https://github.com/charliermarsh)\n- [@MichaReiser](https://github.com/MichaReiser)\n- [@bxff](https://github.com/bxff)\n- [@felixscherz](https://github.com/felixscherz)\n- [@denyszhak](https://github.com/denyszhak)\n\n## 0.0.13\n\nReleased on 2026-01-21.\n\n### Bug fixes\n\n- Fix `--force-exclude` when excluding entire directories ([#22595](https://github.com/astral-sh/ruff/pull/22595))\n- Fix missing syntax highlighting for aliased import names ([#22675](https://github.com/astral-sh/ruff/pull/22675))\n- Highlight interpolated-parts in t-strings ([#22674](https://github.com/astral-sh/ruff/pull/22674))\n- Fix the inferred MRO of functional namedtuple classes ([#22722](https://github.com/astral-sh/ruff/pull/22722))\n- Make special cases for subscript inference exhaustive, ensuring that the special casing for tuple subscripts is applied when a union of tuples or an alias to a tuple type is subscripted ([#22035](https://github.com/astral-sh/ruff/pull/22035))\n\n### LSP server\n\n- Improve completion suggestions inside class definitions ([#22571](https://github.com/astral-sh/ruff/pull/22571))\n- Improve performance of completions ([#22630](https://github.com/astral-sh/ruff/pull/22630))\n- Remove completion suggestions for redundant re-exports that share the same top-most module ([#22581](https://github.com/astral-sh/ruff/pull/22581))\n\n### Core type checking\n\n- Add basic support for overloads in `ParamSpec` ([#21946](https://github.com/astral-sh/ruff/pull/21946))\n- Allow `...` as a default value for any parameter if the function is in an `if TYPE_CHECKING` block ([#22624](https://github.com/astral-sh/ruff/pull/22624))\n- Allow `if type(x) is Y` narrowing for types other than class-literal types ([#22729](https://github.com/astral-sh/ruff/pull/22729))\n- Avoid overload errors when detecting dataclass-on-tuple ([#22687](https://github.com/astral-sh/ruff/pull/22687))\n- Avoid reporting overload errors for successful union variants ([#22688](https://github.com/astral-sh/ruff/pull/22688))\n- Ban `NewType`s with generic bases ([#22653](https://github.com/astral-sh/ruff/pull/22653))\n- Fix PEP 695 type aliases not expanding in overload resolution ([#22589](https://github.com/astral-sh/ruff/pull/22589))\n- Fix the return type for synthesized `NamedTuple.__new__` methods ([#22625](https://github.com/astral-sh/ruff/pull/22625))\n- Emit diagnostics for `NamedTuple`, `TypedDict`, `Enum` or `Protocol` classes decorated with `@dataclass` ([#22672](https://github.com/astral-sh/ruff/pull/22672))\n- Emit `invalid-type-form` diagnostics for stringified annotations where the quoted expression is invalid ([#22752](https://github.com/astral-sh/ruff/pull/22752))\n- Infer the implicit type of `cls` in `__new__` methods ([#22584](https://github.com/astral-sh/ruff/pull/22584))\n- Make `ModuleType` and `object` attributes available on namespace packages ([#22606](https://github.com/astral-sh/ruff/pull/22606))\n- Make `NamedTuple(...)` and `namedtuple(...)` calls stricter ([#22601](https://github.com/astral-sh/ruff/pull/22601))\n- Narrow on bool and byte subscripts ([#22684](https://github.com/astral-sh/ruff/pull/22684))\n- Narrow on negative subscript indexing ([#22682](https://github.com/astral-sh/ruff/pull/22682))\n- Override `__file__` to `str` when applicable on imported modules ([#22333](https://github.com/astral-sh/ruff/pull/22333))\n- Add bidirectional inference for comprehensions ([#22564](https://github.com/astral-sh/ruff/pull/22564))\n- Recognize string-literal types as subtypes of `Sequence[Literal[chars]]` ([#22415](https://github.com/astral-sh/ruff/pull/22415))\n- Add right-hand-side narrowing for `if Foo is type(x)` expressions ([#22608](https://github.com/astral-sh/ruff/pull/22608))\n- Add simple syntactic validation for the right-hand side of PEP-613 type aliases ([#22652](https://github.com/astral-sh/ruff/pull/22652))\n- Add support for passing `typename` and `field_names` by keyword argument to `collections.namedtuple()` calls ([#22660](https://github.com/astral-sh/ruff/pull/22660))\n- Add support for starred unpacking in class bases ([#22591](https://github.com/astral-sh/ruff/pull/22591))\n- Validate constructor arguments when a class is used as a decorator ([#22377](https://github.com/astral-sh/ruff/pull/22377))\n- Validate field names for `typing.NamedTuple(...)` ([#22599](https://github.com/astral-sh/ruff/pull/22599))\n- Add diagnostic on overridden `__setattr__` and `__delattr__` in frozen dataclasses ([#21430](https://github.com/astral-sh/ruff/pull/21430))\n- Fix unary operators on `NewType`s of `float` or `complex` ([#22605](https://github.com/astral-sh/ruff/pull/22605))\n\n### Configuration\n\n- Support overriding `respect-type-ignore-comments` ([#22615](https://github.com/astral-sh/ruff/pull/22615))\n\n### Diagnostics\n\n- Don't add a subdiagnostic pointing to the TypeVar definition if the TypeVar is `Self` ([#22646](https://github.com/astral-sh/ruff/pull/22646))\n- Show final search path instead of \"and 1 more paths\" ([#22776](https://github.com/astral-sh/ruff/pull/22776))\n- Group `type[]` elements together when displaying union types ([#22592](https://github.com/astral-sh/ruff/pull/22592))\n\n### Performance\n\n- Cache `ClassType::nearest_disjoint_base` ([#22065](https://github.com/astral-sh/ruff/pull/22065))\n\n### Other changes\n\n- Sync vendored typeshed stubs ([#22590](https://github.com/astral-sh/ruff/pull/22590), [Typeshed diff](https://github.com/python/typeshed/compare/d1d5fe58664b30a0c2dde3cd5c3dc8091f0f16ae...cd8b26b0ceef26cd84ab614088140d48680ac7f7)\n\n### Contributors\n\n- [@bxff](https://github.com/bxff)\n- [@jhartum](https://github.com/jhartum)\n- [@thejchap](https://github.com/thejchap)\n- [@AlexWaygood](https://github.com/AlexWaygood)\n- [@charliermarsh](https://github.com/charliermarsh)\n- [@RasmusNygren](https://github.com/RasmusNygren)\n- [@mswart](https://github.com/mswart)\n- [@MatthewMckee4](https://github.com/MatthewMckee4)\n- [@11happy](https://github.com/11happy)\n- [@ibraheemdev](https://github.com/ibraheemdev)\n- [@sinon](https://github.com/sinon)\n- [@MichaReiser](https://github.com/MichaReiser)\n- [@carljm](https://github.com/carljm)\n- [@BurntSushi](https://github.com/BurntSushi)\n- [@dhruvmanila](https://github.com/dhruvmanila)\n- [@oconnor663](https://github.com/oconnor663)\n- [@zanieb](https://github.com/zanieb)\n\n## 0.0.12\n\nReleased on 2026-01-14.\n\n### Bug fixes\n\n- Avoid panic that could occur when `cast`ing an object to a TypedDict or union of TypedDicts ([#22509](https://github.com/astral-sh/ruff/pull/22509))\n- Fix incorrect narrowing for `if type(x) == y` ([#22531](https://github.com/astral-sh/ruff/pull/22531))\n- Fix stack overflow with recursive type aliases containing tuple types ([#22543](https://github.com/astral-sh/ruff/pull/22543))\n- `functools.total_ordering`: ensure the signatures of generated methods reflect the signature of the user-provided method ([#22496](https://github.com/astral-sh/ruff/pull/22496))\n- Support `dataclass_transform` as a function call ([#22378](https://github.com/astral-sh/ruff/pull/22378))\n- Use the top materialization of classes for `if type(x) is y` narrowing. For example, `if type(x) is tuple` will cause the type of `x` to be intersected with `tuple[object, ...]` rather than `tuple[Unknown, ...]`. ([#22553](https://github.com/astral-sh/ruff/pull/22553))\n- Avoid emitting Liskov violations with respect to a grandparent class if such violations could not be fixed without introducing Liskov violations with respect to a parent class ([#22484](https://github.com/astral-sh/ruff/pull/22484))\n- Fix interaction between classmethod, contextmanager, and Self ([#22407](https://github.com/astral-sh/ruff/pull/22407))\n- Check contravariant type variable bounds contravariantly in specialization inference ([#22488](https://github.com/astral-sh/ruff/pull/22488))\n- Fix false positive for bounded type parameters with NewType ([#22542](https://github.com/astral-sh/ruff/pull/22542))\n\n### Core type checking\n\n- Add support for dynamic `type()` classes ([#22291](https://github.com/astral-sh/ruff/pull/22291), [#22499](https://github.com/astral-sh/ruff/pull/22499), [#22537](https://github.com/astral-sh/ruff/pull/22537), [#22480](https://github.com/astral-sh/ruff/pull/22480))\n- Add support for functional `namedtuple` creation ([#22327](https://github.com/astral-sh/ruff/pull/22327), [#22573](https://github.com/astral-sh/ruff/pull/22573), [#22575](https://github.com/astral-sh/ruff/pull/22575), [#22574](https://github.com/astral-sh/ruff/pull/22574))\n- Add a diagnostic for non-decorator uses of `final` ([#22555](https://github.com/astral-sh/ruff/pull/22555))\n- Add diagnostic to catch generic enums ([#22482](https://github.com/astral-sh/ruff/pull/22482))\n- Add diagnostics for `__init_subclass__` argument mismatch ([#22185](https://github.com/astral-sh/ruff/pull/22185))\n- Add diagnostics to validate `TypeIs` and `TypeGuard` definitions ([#22300](https://github.com/astral-sh/ruff/pull/22300))\n- Apply type narrowing to walrus targets ([#22369](https://github.com/astral-sh/ruff/pull/22369))\n- Detect invalid `@total_ordering` applications in non-decorator contexts ([#22486](https://github.com/astral-sh/ruff/pull/22486))\n- Fix `@Todo` type for starred expressions ([#22503](https://github.com/astral-sh/ruff/pull/22503))\n- Improve disambiguation of types in diagnostics ([#22547](https://github.com/astral-sh/ruff/pull/22547))\n- Include type parameters in the display for generic `Callable` types ([#22435](https://github.com/astral-sh/ruff/pull/22435))\n- Infer `type[Unknown]` for calls to `type()` when overload evaluation is ambiguous ([#22569](https://github.com/astral-sh/ruff/pull/22569))\n- Support assignment to unions of `TypedDict`s ([#22294](https://github.com/astral-sh/ruff/pull/22294))\n- Use the key and value parameter types as type context for `__setitem__` dunder calls ([#22148](https://github.com/astral-sh/ruff/pull/22148))\n- Narrow the right-hand side of `==`, `!=`, `is` and `is not` conditions when the left-hand side is not narrowable ([#22511](https://github.com/astral-sh/ruff/pull/22511))\n\n### LSP server\n\n- Fix `__file__` type in completions to show `str` instead of `str | None` when the inferred type is `str` ([#22510](https://github.com/astral-sh/ruff/pull/22510))\n- Improve rendering of ReST directives in docstrings ([#22512](https://github.com/astral-sh/ruff/pull/22512))\n\n### Contributors\n\n- [@eclbg](https://github.com/eclbg)\n- [@RasmusNygren](https://github.com/RasmusNygren)\n- [@carljm](https://github.com/carljm)\n- [@drbh](https://github.com/drbh)\n- [@AryanBagade](https://github.com/AryanBagade)\n- [@bxff](https://github.com/bxff)\n- [@ibraheemdev](https://github.com/ibraheemdev)\n- [@charliermarsh](https://github.com/charliermarsh)\n- [@AlexWaygood](https://github.com/AlexWaygood)\n\n## 0.0.11\n\nReleased on 2026-01-09.\n\n### Bug fixes\n\n- Fix `super()` with TypeVar-annotated `self` and `cls` parameter ([#22208](https://github.com/astral-sh/ruff/pull/22208))\n- Only consider fully static pivots when deriving transitive constraints ([#22444](https://github.com/astral-sh/ruff/pull/22444))\n\n### LSP server\n\n- Don't show diagnostics for excluded files ([#22455](https://github.com/astral-sh/ruff/pull/22455))\n- Fix goto definition for relative imports in third-party files ([#22457](https://github.com/astral-sh/ruff/pull/22457))\n- Improve completion ranking based on origin and exact match ([#22460](https://github.com/astral-sh/ruff/pull/22460))\n- Rank top-level module symbols above most other symbols ([#22465](https://github.com/astral-sh/ruff/pull/22465))\n\n### Configuration\n\n- Enable `unused-ignore-comment` by default ([#22474](https://github.com/astral-sh/ruff/pull/22474))\n\n### Performance\n\n- Improve `UnionBuilder` performance by changing `Type::is_subtype_of` calls to `Type::is_redundant_with` ([#22337](https://github.com/astral-sh/ruff/pull/22337))\n- Optimize union building for unions with many enum-literal members ([#22363](https://github.com/astral-sh/ruff/pull/22363))-\n\n### Other changes\n\n- Declare support for Python 3.14 ([#2407](https://github.com/astral-sh/ty/pull/2407))\n- Remove dark-mode handling from PyPI-uploaded README ([#2422](https://github.com/astral-sh/ty/pull/2422))\n\n### Contributors\n\n- [@dhruvmanila](https://github.com/dhruvmanila)\n- [@AlexWaygood](https://github.com/AlexWaygood)\n- [@charliermarsh](https://github.com/charliermarsh)\n- [@BurntSushi](https://github.com/BurntSushi)\n- [@MichaReiser](https://github.com/MichaReiser)\n- [@dcreager](https://github.com/dcreager)\n\n## 0.0.10\n\nReleased on 2026-01-07.\n\n### Bug fixes\n\n- Fix stack overflow due to too small stack size ([#22433](https://github.com/astral-sh/ruff/pull/22433))\n- Fix stale semantic tokens after opening the same document with new content ([#22414](https://github.com/astral-sh/ruff/pull/22414))\n- Fix handling of `ParamSpec` in overloaded functions ([#22416](https://github.com/astral-sh/ruff/pull/22416))\n- Fix comparisons and arithmetic with `NewType`s of `float` ([#22105](https://github.com/astral-sh/ruff/pull/22105))\n- Fix several issues with unannotated function return types ([#22425](https://github.com/astral-sh/ruff/pull/22425))\n- Fix handling of subclasses in Callables ([#22411](https://github.com/astral-sh/ruff/pull/22411))\n\n### LSP server\n\n- Add support for explicit markdown code fences in docstring rendering ([#22373](https://github.com/astral-sh/ruff/pull/22373), [#22408](https://github.com/astral-sh/ruff/pull/22408))\n- Offer completions for `T` when a value has type `Unknown | T` ([#22436](https://github.com/astral-sh/ruff/pull/22436))\n- Sort keyword argument completions higher ([#22297](https://github.com/astral-sh/ruff/pull/22297))\n\n### Core type checking\n\n- Add support for `@total_ordering` ([#22181](https://github.com/astral-sh/ruff/pull/22181), [#22183](https://github.com/astral-sh/ruff/pull/22183))\n- Better simplification of intersections of tuples ([#22094](https://github.com/astral-sh/ruff/pull/22094))\n- Support comparisons between variable-length tuples ([#21824](https://github.com/astral-sh/ruff/pull/21824))\n- Emit diagnostics for method definitions and other invalid statements in `TypedDict` class bodies ([#22351](https://github.com/astral-sh/ruff/pull/22351))\n- Improve type-narrowing in calls to `len()` ([#22330](https://github.com/astral-sh/ruff/pull/22330))\n\n### CLI\n\n- Add `--add-ignore` CLI option ([#21696](https://github.com/astral-sh/ruff/pull/21696))\n\n### Configuration\n\n- `include = [\"myscript\"]` will now check `myscript` even though it doesn't have a Python extension ([#22243](https://github.com/astral-sh/ruff/pull/22243))\n\n### Performance\n\n- Optimize intersections with a single negated element ([#22344](https://github.com/astral-sh/ruff/pull/22344))\n- Optimize negated types ([#22402](https://github.com/astral-sh/ruff/pull/22402))\n\n### Documentation\n\n- Link to `Callable` `__name__` FAQ directly from `unresolved-attribute` diagnostic ([#22437](https://github.com/astral-sh/ruff/pull/22437))\n\n### Contributors\n\n- [@dhruvmanila](https://github.com/dhruvmanila)\n- [@charliermarsh](https://github.com/charliermarsh)\n- [@oconnor663](https://github.com/oconnor663)\n- [@BurntSushi](https://github.com/BurntSushi)\n- [@RasmusNygren](https://github.com/RasmusNygren)\n- [@carljm](https://github.com/carljm)\n- [@Gankra](https://github.com/Gankra)\n- [@MichaReiser](https://github.com/MichaReiser)\n- [@AlexWaygood](https://github.com/AlexWaygood)\n\n## 0.0.9\n\nReleased on 2026-01-05.\n\n### Bug fixes\n\n- Emit a diagnostic if a class decorator is not a callable accepting a type ([#22375](https://github.com/astral-sh/ruff/pull/22375))\n- Fix exhaustiveness inference for unions that include enums ([#22290](https://github.com/astral-sh/ruff/pull/22290))\n\n### Core type checking\n\n- Support `typing.TypeGuard` ([#20974](https://github.com/astral-sh/ruff/pull/20974))\n- Treat `__setattr__` as fallback-only ([#22014](https://github.com/astral-sh/ruff/pull/22014))\n- Don't expand type aliases via type mappings unless necessary. This means that the displayed signature of a bound methods will no longer eagerly expand type aliases into their aliased types ([#22241](https://github.com/astral-sh/ruff/pull/22241))\n- Narrow `TypedDict` unions with `not in` ([#22349](https://github.com/astral-sh/ruff/pull/22349))\n- Don't including `property` in subclasses properties ([#22088](https://github.com/astral-sh/ruff/pull/22088))\n- Narrow tagged unions of `TypedDict`s in `match` statements ([#22299](https://github.com/astral-sh/ruff/pull/22299))\n- Teach bidirectional inference about subtyping. This allows `x` to be inferred as `list[int]` for `x: Iterable[int] = [42]` ([#21930](https://github.com/astral-sh/ruff/pull/21930))\n- Support narrowing for tagged unions of tuples where one element of the tuple is a `Literal` type ([#22303](https://github.com/astral-sh/ruff/pull/22303))\n\n### LSP server\n\n- Add autocomplete suggestions for keyword arguments in `class` statements ([#22110](https://github.com/astral-sh/ruff/pull/22110))\n- Avoid showing misleading inlay hint for unpacked tuple arguments ([#22286](https://github.com/astral-sh/ruff/pull/22286))\n\n### Other changes\n\n- Sync vendored typeshed stubs ([#22302](https://github.com/astral-sh/ruff/pull/22302), [#22321](https://github.com/astral-sh/ruff/pull/22321), [#22324](https://github.com/astral-sh/ruff/pull/22324)). [Typeshed diff](https://github.com/python/typeshed/compare/3c2dbb1fde8e8d1d59b10161c8bf5fd06c0011cd...d1d5fe58664b30a0c2dde3cd5c3dc8091f0f16ae)\n\n### Contributors\n\n- [@RasmusNygren](https://github.com/RasmusNygren)\n- [@ericmarkmartin](https://github.com/ericmarkmartin)\n- [@AlexWaygood](https://github.com/AlexWaygood)\n- [@ibraheemdev](https://github.com/ibraheemdev)\n- [@charliermarsh](https://github.com/charliermarsh)\n- [@felixscherz](https://github.com/felixscherz)\n- [@MatthewMckee4](https://github.com/MatthewMckee4)\n- [@mtshiba](https://github.com/mtshiba)\n\n## 0.0.8\n\nReleased on 2025-12-29.\n\n### Breaking changes\n\n- Rename `non-subscriptable` rule to `not-subscriptable` ([#22193](https://github.com/astral-sh/ruff/pull/22193))\n\n### Core type checking\n\n- Promote float and complex when promoting literals ([#22215](https://github.com/astral-sh/ruff/pull/22215))\n- Callable type of a type object is not function-like ([#22226](https://github.com/astral-sh/ruff/pull/22226))\n- Fix and simplify callable type materializations ([#22213](https://github.com/astral-sh/ruff/pull/22213))\n\n### LSP server\n\n- Add option to disable syntax errors ([#22217](https://github.com/astral-sh/ruff/pull/22217))\n- Fix completion in decorators with missing declaration ([#22177](https://github.com/astral-sh/ruff/pull/22177))\n- Better completions context detection when typing in decorator positions ([#22224](https://github.com/astral-sh/ruff/pull/22224))\n- Limit the returned completions to reduce lag ([#22240](https://github.com/astral-sh/ruff/pull/22240))\n\n### Diagnostics\n\n- Improve wording of `unsupported-base` sub-diagnostic ([#22194](https://github.com/astral-sh/ruff/pull/22194))\n- Preserve the invalid assignment diagnostic message when implicitly shadowing a definition ([#22219](https://github.com/astral-sh/ruff/pull/22219))\n\n### Other changes\n\n- Update docker image to use alpine 3.23 and trixie ([#2217](https://github.com/astral-sh/ty/pull/2217))\n\n### Contributors\n\n- [@RasmusNygren](https://github.com/RasmusNygren)\n- [@samypr100](https://github.com/samypr100)\n- [@silamon](https://github.com/silamon)\n- [@carljm](https://github.com/carljm)\n- [@MichaReiser](https://github.com/MichaReiser)\n- [@MatthewMckee4](https://github.com/MatthewMckee4)\n\n## 0.0.7\n\nReleased on 2025-12-24.\n\n### Bug fixes\n\n- Fix classification of modules in `import x as y` for semantic syntax highlighting ([#22175](https://github.com/astral-sh/ruff/pull/22175))\n- Fix module resolution on network drives ([#22173](https://github.com/astral-sh/ruff/pull/22173))\n- Render the entire diagnostic message in all output formats ([#22164](https://github.com/astral-sh/ruff/pull/22164))\n\n### Other changes\n\n- Add a dedicated diagnostic for TypedDict deletions ([#22123](https://github.com/astral-sh/ruff/pull/22123))\n- Check `__delitem__` instead of `__getitem__` for `del x[k]` ([#22121](https://github.com/astral-sh/ruff/pull/22121))\n- Fix `@staticmethod` combined with other decorators incorrectly binding `self` ([#22128](https://github.com/astral-sh/ruff/pull/22128))\n- Fix implementation of `Top[Callable[..., object]]` ([#22145](https://github.com/astral-sh/ruff/pull/22145))\n- 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))\n- Improve diagnostic when a user tries to access a function attribute on a `Callable` type ([#22182](https://github.com/astral-sh/ruff/pull/22182))\n- Include the specialization of a generic `TypedDict` as part of its display ([#22174](https://github.com/astral-sh/ruff/pull/22174))\n- Support tuple narrowing based on member checks ([#22167](https://github.com/astral-sh/ruff/pull/22167))\n- Synthesize `__delitem__` for TypedDict to allow deleting non-required keys ([#22122](https://github.com/astral-sh/ruff/pull/22122))\n\n### Contributors\n\n- [@MichaReiser](https://github.com/MichaReiser)\n- [@ntBre](https://github.com/ntBre)\n- [@AlexWaygood](https://github.com/AlexWaygood)\n- [@charliermarsh](https://github.com/charliermarsh)\n\n## 0.0.6\n\nReleased on 2025-12-23.\n\n### Bug fixes\n\n- FIx panic from unexpanded type aliases in implicit tuple aliases ([#22015](https://github.com/astral-sh/ruff/pull/22015))\n- Support `type[T]` where `T` is a type alias to a union of types ([#22115](https://github.com/astral-sh/ruff/pull/22115))\n- Support `==` narrowing for tuples in unions with disjoint types ([#22129](https://github.com/astral-sh/ruff/pull/22129))\n- Respect debug text interpolation in f-strings ([#22151](https://github.com/astral-sh/ruff/pull/22151))\n- Fix panic from unstable union-type ordering in fixed-point iteration ([#22070](https://github.com/astral-sh/ruff/pull/22070))\n\n### LSP server\n\n- Add `ty.configuration` and `ty.configurationFile` options ([#22053](https://github.com/astral-sh/ruff/pull/22053))\n- Add `diagnosticMode: off` to disable diagnostics while retaining Go To Definition, etc. ([#22073](https://github.com/astral-sh/ruff/pull/22073))\n- 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))\n- Use Markdown for completions documentation if the LSP client supports it ([#21752](https://github.com/astral-sh/ruff/pull/21752))\n\n### CLI\n\n- Abort printing diagnostics when pressing `Ctrl+C` ([#22083](https://github.com/astral-sh/ruff/pull/22083))\n\n### Configuration\n\n- Add `respect-type-ignore-comments` configuration option ([#22137](https://github.com/astral-sh/ruff/pull/22137))\n- Support custom builtins via `__builtins__.pyi` ([#22021](https://github.com/astral-sh/ruff/pull/22021))\n\n### Other changes\n\n- Bind self with instance in `__get__` ([#22155](https://github.com/astral-sh/ruff/pull/22155))\n- Support type inference between protocol instances ([#22120](https://github.com/astral-sh/ruff/pull/22120))\n- Synthesize a precise `_fields` attribute for NamedTuples ([#22163](https://github.com/astral-sh/ruff/pull/22163))\n- Synthesize a precise `_replace` method for NamedTuples ([#22153](https://github.com/astral-sh/ruff/pull/22153))\n- Narrow \"tagged unions\" of `TypedDict`s ([#22104](https://github.com/astral-sh/ruff/pull/22104))\n\n### Contributors\n\n- [@mtshiba](https://github.com/mtshiba)\n- [@charliermarsh](https://github.com/charliermarsh)\n- [@Wizzerinus](https://github.com/Wizzerinus)\n- [@oconnor663](https://github.com/oconnor663)\n- [@MichaReiser](https://github.com/MichaReiser)\n- [@ibraheemdev](https://github.com/ibraheemdev)\n- [@MatthewMckee4](https://github.com/MatthewMckee4)\n\n## 0.0.5\n\nReleased on 2025-12-20.\n\n### Bug fixes\n\n- 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))\n\n### LSP server\n\n- Classify docstrings in semantic tokens during syntax highlighting ([#22031](https://github.com/astral-sh/ruff/pull/22031))\n\n### CLI\n\n- Add `--force-exclude` option ([#22076](https://github.com/astral-sh/ruff/pull/22076))\n- Only clear output between two successful checks ([#22078](https://github.com/astral-sh/ruff/pull/22078))\n\n### Other changes\n\n- Add support for `dict(...)` calls in `TypedDict` contexts ([#22113](https://github.com/astral-sh/ruff/pull/22113))\n- Speedup bidirectional type-checking involving large unions by avoiding narrowing on non-generic calls ([#22102](https://github.com/astral-sh/ruff/pull/22102))\n- 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))\n- Improve union builder performance ([#22048](https://github.com/astral-sh/ruff/pull/22048))\n- Only prefer declared types in non-covariant positions ([#22068](https://github.com/astral-sh/ruff/pull/22068))\n- Respect intersections in iterations ([#21965](https://github.com/astral-sh/ruff/pull/21965))\n- Sync vendored typeshed stubs ([#22091](https://github.com/astral-sh/ruff/pull/22091)). [Typeshed diff](https://github.com/python/typeshed/compare/ef2b90c67e5c668b91b3ae121baf00ee5165c30b...3c2dbb1fde8e8d1d59b10161c8bf5fd06c0011cd)\n- 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))\n\n### Contributors\n\n- [@charliermarsh](https://github.com/charliermarsh)\n- [@ibraheemdev](https://github.com/ibraheemdev)\n- [@RasmusNygren](https://github.com/RasmusNygren)\n- [@Hugo-Polloli](https://github.com/Hugo-Polloli)\n- [@carljm](https://github.com/carljm)\n- [@Gankra](https://github.com/Gankra)\n- [@MichaReiser](https://github.com/MichaReiser)\n\n## 0.0.4\n\nReleased on 2025-12-18.\n\n### LSP server\n\n- Add support for attribute docstrings ([#22036](https://github.com/astral-sh/ruff/pull/22036))\n- Correctly encode multiline tokens for clients not supporting multiline tokens ([#22033](https://github.com/astral-sh/ruff/pull/22033))\n- Autocompletions: Don't suggest keyword statements when only expressions are valid ([#22002](https://github.com/astral-sh/ruff/pull/22002))\n- Fix goto-declaration on the right-hand side of `from module import submodule` ([#22042](https://github.com/astral-sh/ruff/pull/22042))\n- Fix some configuration panics in the LSP ([#22040](https://github.com/astral-sh/ruff/pull/22040))\n- Gracefully handle client requests that can't be deserialized ([#22051](https://github.com/astral-sh/ruff/pull/22051))\n\n### Other changes\n\n- Improve performance for large match statements ([#22045](https://github.com/astral-sh/ruff/pull/22045))\n- Disable possibly-missing-imports by default ([#22041](https://github.com/astral-sh/ruff/pull/22041))\n- Implement disjointness for TypedDicts, significantly speeding up checking of code that uses pydantic ([#22044](https://github.com/astral-sh/ruff/pull/22044))\n\n### Contributors\n\n- [@oconnor663](https://github.com/oconnor663)\n- [@MichaReiser](https://github.com/MichaReiser)\n- [@Gankra](https://github.com/Gankra)\n- [@RasmusNygren](https://github.com/RasmusNygren)\n- [@charliermarsh](https://github.com/charliermarsh)\n\n## 0.0.3\n\nReleased on 2025-12-17.\n\n### LSP server\n\n- Improve rendering of signatures in hovers ([#22007](https://github.com/astral-sh/ruff/pull/22007))\n\n### Core type checking\n\n- Apply narrowing to `len` calls based on argument size ([#22026](https://github.com/astral-sh/ruff/pull/22026))\n- Don't add identical lower/upper bounds multiple times when inferring specializations ([#22030](https://github.com/astral-sh/ruff/pull/22030))\n- 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))\n- Improve disambiguation of types in many cases ([#22019](https://github.com/astral-sh/ruff/pull/22019))\n- Respect deferred values in keyword arguments etc. for `.pyi` files ([#22029](https://github.com/astral-sh/ruff/pull/22029))\n- 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))\n\n### Contributors\n\n- [@charliermarsh](https://github.com/charliermarsh)\n- [@sharkdp](https://github.com/sharkdp)\n- [@Gankra](https://github.com/Gankra)\n- [@zanieb](https://github.com/zanieb)\n- [@AlexWaygood](https://github.com/AlexWaygood)\n- [@dcreager](https://github.com/dcreager)\n\n## 0.0.2\n\nReleased on 2025-12-16.\n\nThis is the first Beta release of ty, which we're now ready to recommend to motivated users for\nproduction use. See our [blog post](https://astral.sh/blog/ty) for more details.\n\n### LSP server\n\n- Improve display of completions to show actual insertion text ([#21988](https://github.com/astral-sh/ruff/pull/21988))\n- Improve highlighting of special type syntax in hovers ([#22005](https://github.com/astral-sh/ruff/pull/22005))\n- Improve syntax highlighting of constants ([#22006](https://github.com/astral-sh/ruff/pull/22006))\n\n### Core type checking\n\n- Infer precise types for `isinstance(…)` calls involving type variables ([#21999](https://github.com/astral-sh/ruff/pull/21999))\n- Infer `TypeVar` specializations for `Callable` types ([#21551](https://github.com/astral-sh/ruff/pull/21551))\n- Propagate `classmethod`-ness through decorators returning `Callable`s ([#21958](https://github.com/astral-sh/ruff/pull/21958))\n- Improve rendering of default values for function args ([#22010](https://github.com/astral-sh/ruff/pull/22010))\n- Don't use implicit superclass annotation when converting a class constructor into a `Callable` ([#22011](https://github.com/astral-sh/ruff/pull/22011))\n\n### Other\n\n- Type checking performance improvement ([#22000](https://github.com/astral-sh/ruff/pull/22000))\n\n### Contributors\n\n- [@sharkdp](https://github.com/sharkdp)\n- [@carljm](https://github.com/carljm)\n- [@Gankra](https://github.com/Gankra)\n- [@BurntSushi](https://github.com/BurntSushi)\n- [@dcreager](https://github.com/dcreager)\n- [@MichaReiser](https://github.com/MichaReiser)\n\n## 0.0.1-alpha.35\n\nReleased on 2025-12-16.\n\n### Bug fixes\n\n- Fix panic for stringified comprehensions and boolean expressions in type expression ([#21967](https://github.com/astral-sh/ruff/pull/21967))\n- Avoid stack overflow when determining inferable typevars ([#21971](https://github.com/astral-sh/ruff/pull/21971))\n- Fix false-positive `invalid-method-override` diagnostic on method that uses `Callable` with a `ParamSpec` ([#21934](https://github.com/astral-sh/ruff/pull/21934))\n- Disallow explicit specialization of type variables themselves ([#21938](https://github.com/astral-sh/ruff/pull/21938))\n- Fix hover type on named expression (\"walrus expression\") targets ([#21952](https://github.com/astral-sh/ruff/pull/21952))\n\n### LSP server\n\n- Add *\"qualify ...\"* code fix for undefined references ([#21968](https://github.com/astral-sh/ruff/pull/21968))\n- Add new goto-definition targets on inlay hints ([#21950](https://github.com/astral-sh/ruff/pull/21950))\n- Remove invalid statement-keyword completions in `for`-statements ([#21979](https://github.com/astral-sh/ruff/pull/21979))\n\n### Core type checking\n\n- Add support for `__qualname__` and other implicit class attributes ([#21966](https://github.com/astral-sh/ruff/pull/21966))\n- Emit a diagnostic when a frozen dataclass inherits a non-frozen dataclass and vice versa ([#21962](https://github.com/astral-sh/ruff/pull/21962))\n- 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))\n- Improve diagnostics for unsupported binary operations and unsupported augmented assignments ([#21947](https://github.com/astral-sh/ruff/pull/21947))\n- Improve check enforcing that an overloaded function must have an implementation ([#21978](https://github.com/astral-sh/ruff/pull/21978))\n- Use unqualified names for displays of `TypeAliasType`s and unbound `ParamSpec`s/`TypeVar`s ([#21960](https://github.com/astral-sh/ruff/pull/21960))\n\n### Performance\n\n- Speed up ty on Linux by using jemalloc ([#21975](https://github.com/astral-sh/ruff/pull/21975))\n\n### Contributors\n\n- [@11happy](https://github.com/11happy)\n- [@dhruvmanila](https://github.com/dhruvmanila)\n- [@AlexWaygood](https://github.com/AlexWaygood)\n- [@mtshiba](https://github.com/mtshiba)\n- [@MichaReiser](https://github.com/MichaReiser)\n- [@Gankra](https://github.com/Gankra)\n- [@silamon](https://github.com/silamon)\n- [@dcreager](https://github.com/dcreager)\n- [@charliermarsh](https://github.com/charliermarsh)\n- [@RasmusNygren](https://github.com/RasmusNygren)\n- [@carljm](https://github.com/carljm)\n\n## 0.0.1-alpha.34\n\nReleased on 2025-12-12.\n\n### Bug fixes\n\n- Improve solving of a type variable with an upper bound when that type variable appears as one element in a union type ([#21893](https://github.com/astral-sh/ruff/pull/21893))\n- Accurately emulate runtime semantics for `kw_only=True` dataclasses such that only fields declared in the immediate class body are understood as being keyword-only ([#21820](https://github.com/astral-sh/ruff/pull/21820))\n- Avoid inferring types for invalid binary expressions in string annotations ([#21911](https://github.com/astral-sh/ruff/pull/21911))\n- Fix logic used to determine whether two `@final` instance types are disjoint ([#21769](https://github.com/astral-sh/ruff/pull/21769))\n- Fix logic used to determine whether two `@final` `type[]` types are disjoint ([#21770](https://github.com/astral-sh/ruff/pull/21770))\n- Fix false-positive diagnostics that could arise when analysing cyclic types ([#21910](https://github.com/astral-sh/ruff/pull/21910)), ([#21909](https://github.com/astral-sh/ruff/pull/21909))\n\n### LSP server\n\n- Fix outdated version in publish diagnostics after `didChange` ([#21943](https://github.com/astral-sh/ruff/pull/21943))\n- Fix workspace symbols to return members too ([#21926](https://github.com/astral-sh/ruff/pull/21926))\n- Adjust scope completions to use all reachable symbols ([#21872](https://github.com/astral-sh/ruff/pull/21872))\n- Classify `cls` as class parameter for semantic highlighting ([#21944](https://github.com/astral-sh/ruff/pull/21944))\n- Don't show on-hover tooltips for expressions with no inferred type ([#21924](https://github.com/astral-sh/ruff/pull/21924))\n- Ignore `__all__` for document and workspace symbol requests ([#21928](https://github.com/astral-sh/ruff/pull/21928))\n- Recognize `__all__ += submodule.__all__` in auto-import ([#21918](https://github.com/astral-sh/ruff/pull/21918))\n- Stabilize rename ([#21940](https://github.com/astral-sh/ruff/pull/21940))\n\n### Other changes\n\n- Support checking files without extensions ([#21867](https://github.com/astral-sh/ruff/pull/21867))\n- Improve performance and semantics by deferring inference of all parameter and return-type annotations ([#21906](https://github.com/astral-sh/ruff/pull/21906))\n- Improve resolution of absolute imports in tests ([#21817](https://github.com/astral-sh/ruff/pull/21817))\n- Infer the implicit type of the `cls` parameter in `@classmethod` method bodies ([#21685](https://github.com/astral-sh/ruff/pull/21685))\n- Support the implicit type of the `cls` parameter in signatures of `@classmethod` methods ([#21771](https://github.com/astral-sh/ruff/pull/21771))\n- Uniformly use \"not supported\" in diagnostics ([#21916](https://github.com/astral-sh/ruff/pull/21916))\n- Implement the [equivalence relation](https://typing.python.org/en/latest/spec/glossary.html#term-equivalent) for `TypedDict`s ([#21784](https://github.com/astral-sh/ruff/pull/21784))\n- Ensure that the type of the class object `C` is always considered assignable to `type[C[Unknown]]` if `C` is a generic class ([#21883](https://github.com/astral-sh/ruff/pull/21883))\n- Improve bad specialization results and error messages ([#21840](https://github.com/astral-sh/ruff/pull/21840))\n- Support `NewType`s of `float` and `complex` ([#21886](https://github.com/astral-sh/ruff/pull/21886))\n\n### Contributors\n\n- [@charliermarsh](https://github.com/charliermarsh)\n- [@oconnor663](https://github.com/oconnor663)\n- [@MichaReiser](https://github.com/MichaReiser)\n- [@BurntSushi](https://github.com/BurntSushi)\n- [@lucach](https://github.com/lucach)\n- [@ibraheemdev](https://github.com/ibraheemdev)\n- [@mtshiba](https://github.com/mtshiba)\n- [@dcreager](https://github.com/dcreager)\n- [@sharkdp](https://github.com/sharkdp)\n- [@carljm](https://github.com/carljm)\n- [@Gankra](https://github.com/Gankra)\n\n## 0.0.1-alpha.33\n\nReleased on 2025-12-09.\n\n### Bug fixes\n\n- Fix assignability problem between `tuple[Any, ...]` and `tuple[int, *tuple[int, ...]]` ([#21803](https://github.com/astral-sh/ruff/pull/21803))\n- Avoid diagnostic when `typing_extensions.ParamSpec` uses a `default` parameter ([#21839](https://github.com/astral-sh/ruff/pull/21839))\n- Avoid crash for invalid `Annotated` subscript ([#21837](https://github.com/astral-sh/ruff/pull/21837))\n- Avoid crash for invalid `Final` subscript ([#21828](https://github.com/astral-sh/ruff/pull/21828))\n- Fix overload filtering to prefer more precise match when `*args: Any` is involved ([#21859](https://github.com/astral-sh/ruff/pull/21859))\n- Handle various invalid explicit specializations for `ParamSpec` ([#21821](https://github.com/astral-sh/ruff/pull/21821))\n- Fix stack overflow with recursive generic protocols (depth limit) ([#21858](https://github.com/astral-sh/ruff/pull/21858))\n\n### LSP server\n\n- Add autocomplete suggestions for parameters in function calls ([#21796](https://github.com/astral-sh/ruff/pull/21796))\n- Don't create a related diagnostic for the primary annotation of sub-diagnostics ([#21845](https://github.com/astral-sh/ruff/pull/21845))\n- Stabilize auto-import ([#21851](https://github.com/astral-sh/ruff/pull/21851))\n- Suppress inlay hints when assigning a trivial initializer call ([#21848](https://github.com/astral-sh/ruff/pull/21848))\n- Use concise message for LSP clients not supporting related diagnostic information ([#21850](https://github.com/astral-sh/ruff/pull/21850))\n- Fix add-import action for `reveal_type` ([#21668](https://github.com/astral-sh/ruff/pull/21668))\n\n### Core type checking\n\n- Infer type variables within generic unions ([#21862](https://github.com/astral-sh/ruff/pull/21862))\n- Type inference for `@asynccontextmanager` ([#21876](https://github.com/astral-sh/ruff/pull/21876))\n- Make Python-version subdiagnostics less verbose ([#21849](https://github.com/astral-sh/ruff/pull/21849))\n\n### Contributors\n\n- [@BurntSushi](https://github.com/BurntSushi)\n- [@dhruvmanila](https://github.com/dhruvmanila)\n- [@AlexWaygood](https://github.com/AlexWaygood)\n- [@carljm](https://github.com/carljm)\n- [@Gankra](https://github.com/Gankra)\n- [@charliermarsh](https://github.com/charliermarsh)\n- [@RasmusNygren](https://github.com/RasmusNygren)\n- [@sharkdp](https://github.com/sharkdp)\n- [@MichaReiser](https://github.com/MichaReiser)\n\n## 0.0.1-alpha.32\n\nReleased on 2025-12-05.\n\n### LSP server\n\n- Provide auto-import completion suggestions for modules in more situations ([#21799](https://github.com/astral-sh/ruff/pull/21799))\n- Always register the ty server as a [rename provider](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_rename) if the LSP client doesn't support dynamic registration ([#21789](https://github.com/astral-sh/ruff/pull/21789))\n- Support auto-import of re-exported symbols in completion suggestions ([#21779](https://github.com/astral-sh/ruff/pull/21779))\n- Support renaming import aliases ([#21792](https://github.com/astral-sh/ruff/pull/21792))\n\n### Core type checking\n\n- Support `ParamSpec` ([#21445](https://github.com/astral-sh/ruff/pull/21445))\n- Improve the accuracy of the inferred `Callable` supertype of generic classes ([#21798](https://github.com/astral-sh/ruff/pull/21798))\n- Increase the limit on the number of elements in a non-recursively defined literal union ([#21683](https://github.com/astral-sh/ruff/pull/21683))\n- Fix panics on mutually recursive generic protocols by normalizing the bounds/constraints of cyclic type variables ([#21800](https://github.com/astral-sh/ruff/pull/21800))\n\n### Other changes\n\n- Minor improvements to `assert_type` diagnostics ([#21811](https://github.com/astral-sh/ruff/pull/21811))\n- Fix a panic in recursive + generic type aliases ([#21718](https://github.com/astral-sh/ruff/pull/21718))\n- Fix a panic when instantiating a type variable with invalid constraints ([#21663](https://github.com/astral-sh/ruff/pull/21663))\n\n### Contributors\n\n- [@BurntSushi](https://github.com/BurntSushi)\n- [@dhruvmanila](https://github.com/dhruvmanila)\n- [@MichaReiser](https://github.com/MichaReiser)\n- [@mtshiba](https://github.com/mtshiba)\n- [@dcreager](https://github.com/dcreager)\n- [@carljm](https://github.com/carljm)\n- [@AlexWaygood](https://github.com/AlexWaygood)\n\n## 0.0.1-alpha.31\n\nReleased on 2025-12-04.\n\n### Bug fixes\n\n- Fix incorrect `possibly-missing-attribute` diagnostics for `asyncio` imports on Python 3.14 ([#21776](https://github.com/astral-sh/ruff/pull/21776))\n- Fix panic for recursive type aliases ([#21778](https://github.com/astral-sh/ruff/pull/21778))\n\n### Core type checking\n\n- Try ancestor `pyproject.toml` directories as search-paths if module resolution fails ([#21745](https://github.com/astral-sh/ruff/pull/21745))\n- Sync vendored typeshed stubs ([#21715](https://github.com/astral-sh/ruff/pull/21715)) [Typeshed diff](https://github.com/python/typeshed/compare/f8cdc0bd526301e873cd952eb0d457bdf2554e57...ef2b90c67e5c668b91b3ae121baf00ee5165c30b)\n\n### LSP server\n\n- Don't send publish diagnostics for clients supporting pull diagnostics ([#21772](https://github.com/astral-sh/ruff/pull/21772))\n- Fix crash when hovering over string annotations with unknown symbols ([#21782](https://github.com/astral-sh/ruff/pull/21782))\n\n### Diagnostics\n\n- Add subdiagnostic hint if the user wrote `X = Any` rather than `X: Any` ([#21777](https://github.com/astral-sh/ruff/pull/21777))\n- Improve the display of various special-form types ([#21775](https://github.com/astral-sh/ruff/pull/21775))\n\n### Contributors\n\n- [@sharkdp](https://github.com/sharkdp)\n- [@AlexWaygood](https://github.com/AlexWaygood)\n- [@MichaReiser](https://github.com/MichaReiser)\n- [@Gankra](https://github.com/Gankra)\n\n## 0.0.1-alpha.30\n\nReleased on 2025-12-03.\n\n### Bug fixes\n\n- Fix exhaustiveness checking for `match` statements over unions of generic instance types ([#21726](https://github.com/astral-sh/ruff/pull/21726))\n- Don't introduce invalid syntax when autofixing `override-of-final-method` ([#21699](https://github.com/astral-sh/ruff/pull/21699))\n- Suppress false positives when `dataclasses.dataclass(...)(cls)` is called imperatively ([#21729](https://github.com/astral-sh/ruff/pull/21729))\n- Fix false positives for `class F(Generic[*Ts]): ...` ([#21723](https://github.com/astral-sh/ruff/pull/21723))\n- Don't confuse multiple occurrences of `typing.Self` when binding bound methods ([#21754](https://github.com/astral-sh/ruff/pull/21754))\n- Fix subtyping between `type[T]` and a union type, where `T` is a type variable in scope ([#21740](https://github.com/astral-sh/ruff/pull/21740))\n- Fix subtyping between `type[T]` and `U`, where `T` is a type variable in scope and `U` is a type variable not in scope ([#21766](https://github.com/astral-sh/ruff/pull/21766))\n- Fix false positives for `type[tuple[...]]` ([#21652](https://github.com/astral-sh/ruff/pull/21652))\n\n### Memory usage improvements\n\n- Significantly reduce memory usage (especially when ty is used as an LSP server) by enabling least-recently-used ([LRU](https://en.wikipedia.org/wiki/Page_replacement_algorithm#Least_recently_used)) cache eviction for module ASTs ([#21749](https://github.com/astral-sh/ruff/pull/21749))\n\n### LSP server\n\n- Add code action to ignore diagnostic on the current line ([#21595](https://github.com/astral-sh/ruff/pull/21595))\n- Exclude `typing_extensions` from autocomplete suggestions unless it's really available ([#21731](https://github.com/astral-sh/ruff/pull/21731))\n- Fix auto-import code action to handle pre-existing imports ([#21733](https://github.com/astral-sh/ruff/pull/21733))\n- Fix \"find all references\" for types defined in stub files ([#21732](https://github.com/astral-sh/ruff/pull/21732))\n- Fix \"find all references\" for symbols defined via aliased imports ([#21736](https://github.com/astral-sh/ruff/pull/21736))\n\n### Improvements to handling of type aliases\n\n- Default-specialize generic type aliases when they appear unspecialized in type expressions ([#21765](https://github.com/astral-sh/ruff/pull/21765))\n- Infer a type alias as being a generic type alias if it includes a type variable in its definition, even in cases where the value subscripted with the type variable is inferred as having a dynamic type such as `Any` or `Unknown` ([#21730](https://github.com/astral-sh/ruff/pull/21730))\n\n### New `NamedTuple` diagnostics\n\n- Detect `NamedTuple` classes that have field names starting with underscores, which is banned at runtime ([#21697](https://github.com/astral-sh/ruff/pull/21697))\n- Add a diagnostic detecting overrides of prohibited `NamedTuple` attributes ([#21717](https://github.com/astral-sh/ruff/pull/21717))\n- Detect illegal uses of `super()` in methods of `NamedTuple` classes ([#21700](https://github.com/astral-sh/ruff/pull/21700))\n\n### Improvements to existing diagnostics\n\n- Improve diagnostics for unsupported comparison operations ([#21737](https://github.com/astral-sh/ruff/pull/21737))\n- For `invalid-type-arguments` diagnostics, show the user where the type variable was defined ([#21727](https://github.com/astral-sh/ruff/pull/21727))\n- Extend `invalid-explicit-override` to also cover properties decorated with `@override` that do not override anything ([#21756](https://github.com/astral-sh/ruff/pull/21756))\n- Improve `@override`, `@final` and Liskov checks in cases where there are multiple reachable definitions ([#21767](https://github.com/astral-sh/ruff/pull/21767))\n\n### Contributors\n\n- [@MichaReiser](https://github.com/MichaReiser)\n- [@charliermarsh](https://github.com/charliermarsh)\n- [@dcreager](https://github.com/dcreager)\n- [@carljm](https://github.com/carljm)\n- [@AlexWaygood](https://github.com/AlexWaygood)\n- [@BurntSushi](https://github.com/BurntSushi)\n- [@ibraheemdev](https://github.com/ibraheemdev)\n- [@woodruffw](https://github.com/woodruffw)\n- [@sharkdp](https://github.com/sharkdp)\n\n## 0.0.1-alpha.29\n\nReleased on 2025-11-28.\n\n### Bug Fix\n\n- Fix multiple panics due to recursive type definitions ([#20566](https://github.com/astral-sh/ruff/pull/20566))\n\n### Type inference\n\n- Support `type[T]` where `T` is a type variable ([#21650](https://github.com/astral-sh/ruff/pull/21650))\n- More precise inference for a failed specialization of a generic type ([#21651](https://github.com/astral-sh/ruff/pull/21651))\n- Detect invalid overrides of methods that are marked as `typing.final` ([#21646](https://github.com/astral-sh/ruff/pull/21646))\n- Fix subtyping of `type[Any]` / `type[T]` and protocols ([#21678](https://github.com/astral-sh/ruff/pull/21678))\n- Added generics support for implicit and explicit (`typing.TypeAlias`) type aliases ([#21553](https://github.com/astral-sh/ruff/pull/21553))\n\n### LSP server\n\n- Add `import ...` code action for unresolved references ([#21629](https://github.com/astral-sh/ruff/pull/21629))\n- Include all members on `type` in autocompletion suggestions for `type[]` types ([#21670](https://github.com/astral-sh/ruff/pull/21670))\n- Mark comprehension targets as definitions in semantic highlighting ([#21636](https://github.com/astral-sh/ruff/pull/21636))\n- Add IDE autofixes for two \"Did you mean...?\" suggestions ([#21667](https://github.com/astral-sh/ruff/pull/21667))\n- Prettier rendering of `code:: lang` in docstrings ([#21665](https://github.com/astral-sh/ruff/pull/21665))\n- Support go-to for patterns and typevars ([#21671](https://github.com/astral-sh/ruff/pull/21671))\n\n### Diagnostics\n\n- Add subdiagnostic hint if a variable with type `Never` is used in a type expression ([#21660](https://github.com/astral-sh/ruff/pull/21660))\n- Improve diagnostic messages for invalid type arguments during explicit specialization ([#21635](https://github.com/astral-sh/ruff/pull/21635))\n\n### Contributors\n\n- [@lucach](https://github.com/lucach)\n- [@carljm](https://github.com/carljm)\n- [@ibraheemdev](https://github.com/ibraheemdev)\n- [@Gankra](https://github.com/Gankra)\n- [@AlexWaygood](https://github.com/AlexWaygood)\n- [@mtshiba](https://github.com/mtshiba)\n- [@oconnor663](https://github.com/oconnor663)\n- [@sharkdp](https://github.com/sharkdp)\n\n## 0.0.1-alpha.28\n\nReleased on 2025-11-25.\n\n### Bug fixes\n\n- Fix panic for unclosed string literal in type annotation position ([#21592](https://github.com/astral-sh/ruff/pull/21592))\n\n### Type inference\n\n- Check method definitions on subclasses for Liskov violations ([#21436](https://github.com/astral-sh/ruff/pull/21436))\n- Eagerly evaluate `types.UnionType` elements as type expressions ([#21531](https://github.com/astral-sh/ruff/pull/21531))\n- Extend Liskov checks to also cover classmethods and staticmethods ([#21598](https://github.com/astral-sh/ruff/pull/21598))\n- Implement `typing.override` ([#21627](https://github.com/astral-sh/ruff/pull/21627))\n- Narrow type context during literal promotion in generic class constructors ([#21574](https://github.com/astral-sh/ruff/pull/21574))\n- Retain the function-like-ness of `Callable` types when binding `self` ([#21614](https://github.com/astral-sh/ruff/pull/21614))\n- Substitute for `typing.Self` when checking protocol members ([#21569](https://github.com/astral-sh/ruff/pull/21569))\n- Implement `TypedDict` structural assignment ([#21467](https://github.com/astral-sh/ruff/pull/21467))\n- Make implicit submodule imports re-exported ([#21573](https://github.com/astral-sh/ruff/pull/21573))\n- Support PEP 613 `typing.TypeAlias` type aliases ([#21394](https://github.com/astral-sh/ruff/pull/21394))\n- Support generic aliases in `type[...]`, like `type[C[int]]` ([#21552](https://github.com/astral-sh/ruff/pull/21552))\n- Tighten up handling of subscripts in type expressions ([#21503](https://github.com/astral-sh/ruff/pull/21503))\n\n### LSP server\n\n- Improve go-to-definition and add go-to-definition for inlay hints\n    ([#21545](https://github.com/astral-sh/ruff/pull/21545),\n    [#21546](https://github.com/astral-sh/ruff/pull/21546),\n    [#21544](https://github.com/astral-sh/ruff/pull/21544),\n    [#21616](https://github.com/astral-sh/ruff/pull/21616),\n    [#21548](https://github.com/astral-sh/ruff/pull/21548))\n- Implement go-to-type for inlay type hints ([#21533](https://github.com/astral-sh/ruff/pull/21533))\n- Add \"remove unused ignore comment\" code action ([#21582](https://github.com/astral-sh/ruff/pull/21582))\n- Don't suggest completions that aren't subclasses of `BaseException` after `raise` ([#21571](https://github.com/astral-sh/ruff/pull/21571))\n- Implement double click to insert inlay hint ([#21600](https://github.com/astral-sh/ruff/pull/21600))\n- Fix edge cases for autocomplete suppressions in variable bindings ([#21576](https://github.com/astral-sh/ruff/pull/21576))\n- Implement docstring rendering to markdown ([#21550](https://github.com/astral-sh/ruff/pull/21550))\n- Support string annotations ([#21577](https://github.com/astral-sh/ruff/pull/21577))\n- Improve import detection for completions and support `from ...<CURSOR>` completions ([#21547](https://github.com/astral-sh/ruff/pull/21547))\n- Improve handling of hover/goto on imports ([#21572](https://github.com/astral-sh/ruff/pull/21572))\n- Don't allow edits of some more invalid syntax types in inlay hints ([#21621](https://github.com/astral-sh/ruff/pull/21621))\n- Resolve applicable overloads for hover on an overloaded function call ([#21417](https://github.com/astral-sh/ruff/pull/21417))\n- Consistently add the `DEFINITION` modifier when computing semantic tokens ([#21521](https://github.com/astral-sh/ruff/pull/21521))\n- Suppress autocomplete suggestions during variable binding ([#21549](https://github.com/astral-sh/ruff/pull/21549))\n\n### CLI\n\n- Exit with code `2` if there's any IO error ([#21508](https://github.com/astral-sh/ruff/pull/21508))\n\n### Diagnostics\n\n- Add hint about resolved Python version when a user attempts to import a member added on a newer version ([#21615](https://github.com/astral-sh/ruff/pull/21615))\n- Attach subdiagnostics to `unresolved-import` errors for relative imports as well as absolute imports ([#21554](https://github.com/astral-sh/ruff/pull/21554))\n- Avoid expression re-inference for diagnostics ([#21267](https://github.com/astral-sh/ruff/pull/21267))\n- Improve message rendering of unused suppression diagnostic ([#21580](https://github.com/astral-sh/ruff/pull/21580))\n- Improve concise diagnostics for invalid exceptions when a user catches a tuple of objects ([#21578](https://github.com/astral-sh/ruff/pull/21578))\n- Improve diagnostics when `NotImplemented` is called ([#21523](https://github.com/astral-sh/ruff/pull/21523))\n- Improve diagnostics when a submodule is not available as an attribute on a module-literal type ([#21561](https://github.com/astral-sh/ruff/pull/21561))\n- Improve several \"Did you mean?\" suggestions ([#21597](https://github.com/astral-sh/ruff/pull/21597))\n- Switch the error code from `unresolved-attribute` to `possibly-missing-attribute` for submodules that may not be available ([#21618](https://github.com/astral-sh/ruff/pull/21618))\n\n### Other\n\n- Improve debug messages when imports fail ([#21555](https://github.com/astral-sh/ruff/pull/21555))\n\n### Contributors\n\n- [@Gankra](https://github.com/Gankra)\n- [@MatthewMckee4](https://github.com/MatthewMckee4)\n- [@AlexWaygood](https://github.com/AlexWaygood)\n- [@RasmusNygren](https://github.com/RasmusNygren)\n- [@dcreager](https://github.com/dcreager)\n- [@BurntSushi](https://github.com/BurntSushi)\n- [@carljm](https://github.com/carljm)\n- [@MichaReiser](https://github.com/MichaReiser)\n- [@sharkdp](https://github.com/sharkdp)\n- [@oconnor663](https://github.com/oconnor663)\n- [@lucach](https://github.com/lucach)\n- [@ibraheemdev](https://github.com/ibraheemdev)\n\n## 0.0.1-alpha.27\n\nReleased on 2025-11-18.\n\n### Bug fixes\n\n- Fix panic for cyclic star imports ([#21428](https://github.com/astral-sh/ruff/pull/21428))\n- Fix crashes when using a homebrew Python install ([#21405](https://github.com/astral-sh/ruff/pull/21405))\n- Fix incorrect inference of `enum.auto()` for enums with non-`int` mixins, and imprecise inference of `enum.auto()` for single-member enums ([#20541](https://github.com/astral-sh/ruff/pull/20541))\n- Fix global symbol lookup from eagerly executed scopes such as comprehensions and classes ([#21317](https://github.com/astral-sh/ruff/pull/21317))\n- Fix false positive for instance attributes that are declared as `Final` in the class body but have their value assigned in the class's `__init__` method ([#21158](https://github.com/astral-sh/ruff/pull/21158))\n- Use the return type of `__get__` for descriptor lookups even when `__get__` is called with incorrect arguments ([#21424](https://github.com/astral-sh/ruff/pull/21424))\n- Consider parameters being declared `global` a syntax error ([#21312](https://github.com/astral-sh/ruff/pull/21312))\n\n### Type inference\n\n- Support `typing.NewType` ([#21157](https://github.com/astral-sh/ruff/pull/21157))\n- Support `Callable` in implicit type aliases ([#21496](https://github.com/astral-sh/ruff/pull/21496))\n- Support `typing.Union` in implicit type aliases ([#21363](https://github.com/astral-sh/ruff/pull/21363))\n- Precise inference for generator expressions ([#21437](https://github.com/astral-sh/ruff/pull/21437))\n- Support storing attributes in comprehension scopes ([#20856](https://github.com/astral-sh/ruff/pull/20856))\n- Support `isinstance()` and `issubclass()` narrowing when the second argument is a `typing.py` stdlib alias ([#21391](https://github.com/astral-sh/ruff/pull/21391))\n- Support `type[…]` and `Type[…]` in implicit type aliases ([#21421](https://github.com/astral-sh/ruff/pull/21421))\n- Support attribute-expression `TYPE_CHECKING` conditionals ([#21449](https://github.com/astral-sh/ruff/pull/21449))\n- Support class-arguments for dataclass transformers ([#21457](https://github.com/astral-sh/ruff/pull/21457))\n- Support legacy `typing` special forms in implicit type aliases ([#21433](https://github.com/astral-sh/ruff/pull/21433))\n- Support stringified annotations in value-position `Annotated` instances ([#21447](https://github.com/astral-sh/ruff/pull/21447))\n- Support all parameters of dataclass transforms ([#21474](https://github.com/astral-sh/ruff/pull/21474))\n- Support `__hash__` semantics and `unsafe_hash` for dataclasses ([#21470](https://github.com/astral-sh/ruff/pull/21470))\n- Improve handling of version-specific features of dataclasses ([#21453](https://github.com/astral-sh/ruff/pull/21453))\n- Correctly infer the specialization of a non-invariant PEP-695 generic class that has an annotated `self` parameter in its `__init__` method ([#21325](https://github.com/astral-sh/ruff/pull/21325))\n- Improve use of type context when inferring the result of a generic constructor call ([#20933](https://github.com/astral-sh/ruff/pull/20933), [#21442](https://github.com/astral-sh/ruff/pull/21442))\n- Improve use of type context when inferring the result of a generic call expression ([#21210](https://github.com/astral-sh/ruff/pull/21210))\n- Improve heuristics used to decide when it is appropriate to \"promote\" a `Literal` type such as `Literal[42]` to its instance supertype (in this case, `int`) when solving type variables ([#21439](https://github.com/astral-sh/ruff/pull/21439))\n- Improve use of type context to infer conditional expressions ([#21443](https://github.com/astral-sh/ruff/pull/21443))\n- Make `__getattr__` available for `ModuleType` instances ([#21450](https://github.com/astral-sh/ruff/pull/21450))\n- Introduce implicit local variables for `from` imports of submodules in `__init__.py(i)` ([#21173](https://github.com/astral-sh/ruff/pull/21173))\n- Make implicit submodule locals only occur in global scope of an `__init__.py(i)` ([#21370](https://github.com/astral-sh/ruff/pull/21370))\n- Make implicit submodule locals also occur for absolute `from` imports in `__init__.py(i)` files ([#21372](https://github.com/astral-sh/ruff/pull/21372))\n- Consider `from thispackage import y` a re-export of `y` in `__init__.pyi` ([#21387](https://github.com/astral-sh/ruff/pull/21387))\n- Allow PEP-604 unions in stubs and `TYPE_CHECKING` blocks prior to 3.10 ([#21379](https://github.com/astral-sh/ruff/pull/21379))\n- Ensure annotation/type expressions in stub files are always deferred ([#21401](https://github.com/astral-sh/ruff/pull/21401), [#21456](https://github.com/astral-sh/ruff/pull/21456))\n- Silence false-positive diagnostics when using `typing.Dict` or `typing.Callable` as the second argument to `isinstance()` ([#21386](https://github.com/astral-sh/ruff/pull/21386))\n- Sync vendored typeshed stubs ([#21466](https://github.com/astral-sh/ruff/pull/21466)). [Typeshed diff](https://github.com/python/typeshed/compare/bf7214784877c52638844c065360d4814fae4c65...f8cdc0bd526301e873cd952eb0d457bdf2554e57)\n\n### LSP server\n\n- Support for notebooks in VS Code ([#21175](https://github.com/astral-sh/ruff/pull/21175))\n- Fix goto-definition for `float` and `complex` in type annotation positions ([#21388](https://github.com/astral-sh/ruff/pull/21388))\n- Support goto-definition on call argument inlay hints ([#20349](https://github.com/astral-sh/ruff/pull/20349))\n- Add more keywords to scope-based completions ([#21383](https://github.com/astral-sh/ruff/pull/21383))\n- Add synthetic members to completions on dataclasses ([#21446](https://github.com/astral-sh/ruff/pull/21446))\n- Only suggest the `import` keyword in autocompletions for `from <name> <CURSOR>` statements ([#21291](https://github.com/astral-sh/ruff/pull/21291))\n- Suppress completion suggestions following `as` tokens ([#21460](https://github.com/astral-sh/ruff/pull/21460))\n- Suppress invalid suggestions in `import` statements ([#21484](https://github.com/astral-sh/ruff/pull/21484))\n- Suppress redundant inlay hints for function args ([#21365](https://github.com/astral-sh/ruff/pull/21365))\n- Suppress some trivial expression inlay hints ([#21367](https://github.com/astral-sh/ruff/pull/21367))\n- Suppress inlay hints for `+1` and `-1` ([#21368](https://github.com/astral-sh/ruff/pull/21368))\n- Improve [semantic token](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_semanticTokens) classification for names ([#21399](https://github.com/astral-sh/ruff/pull/21399))\n- Classify parameter declarations as definitions when computing semantic tokens ([#21420](https://github.com/astral-sh/ruff/pull/21420))\n\n### Diagnostics\n\n- Better invalid-assignment diagnostics ([#21476](https://github.com/astral-sh/ruff/pull/21476))\n- Better concise diagnostic messages ([#21498](https://github.com/astral-sh/ruff/pull/21498))\n- Improve subscript assignment diagnostics ([#21411](https://github.com/astral-sh/ruff/pull/21411), [#21452](https://github.com/astral-sh/ruff/pull/21452))\n- Improve diagnostic range for `non-subscriptable` diagnostics ([#21461](https://github.com/astral-sh/ruff/pull/21461))\n- Improve diagnostics for invalid exceptions ([#21475](https://github.com/astral-sh/ruff/pull/21475))\n- Add hyperlinks to rule codes in CLI ([#21502](https://github.com/astral-sh/ruff/pull/21502))\n\n### Performance improvements\n\n- Cache computation of dataclass/NamedTuple/TypedDict fields ([#21512](https://github.com/astral-sh/ruff/pull/21512))\n- Faster subscript assignment checks for (unions of) `TypedDict`s ([#21378](https://github.com/astral-sh/ruff/pull/21378))\n- Reduce memory allocations for string-literal types ([#21497](https://github.com/astral-sh/ruff/pull/21497))\n\n### Contributors\n\n- [@thejchap](https://github.com/thejchap)\n- [@mtshiba](https://github.com/mtshiba)\n- [@ibraheemdev](https://github.com/ibraheemdev)\n- [@Gankra](https://github.com/Gankra)\n- [@charliecloudberry](https://github.com/charliecloudberry)\n- [@lucach](https://github.com/lucach)\n- [@AlexWaygood](https://github.com/AlexWaygood)\n- [@MichaReiser](https://github.com/MichaReiser)\n- [@Glyphack](https://github.com/Glyphack)\n- [@dcreager](https://github.com/dcreager)\n- [@saada](https://github.com/saada)\n- [@11happy](https://github.com/11happy)\n- [@oconnor663](https://github.com/oconnor663)\n- [@MatthewMckee4](https://github.com/MatthewMckee4)\n- [@BurntSushi](https://github.com/BurntSushi)\n- [@RasmusNygren](https://github.com/RasmusNygren)\n- [@sharkdp](https://github.com/sharkdp)\n\n## 0.0.1-alpha.26\n\nReleased on 2025-11-10.\n\n### Bug fixes\n\n- Language server: For [semantic tokens](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_semanticTokens), fix range filtering for tokens starting at the end of the requested range ([#21193](https://github.com/astral-sh/ruff/pull/21193))\n- Fix panic due to simplifying `Divergent` types out of intersections types ([#21253](https://github.com/astral-sh/ruff/pull/21253))\n- Fix merging of `--exclude` CLI flag and `src.exclude` config-file setting ([#21341](https://github.com/astral-sh/ruff/pull/21341))\n\n### Type inference\n\n- Infer type of `self` for decorated methods and properties ([#21123](https://github.com/astral-sh/ruff/pull/21123))\n- Add support for properties that return `Self` ([#21335](https://github.com/astral-sh/ruff/pull/21335))\n- Understand legacy and PEP 695 `ParamSpec` ([#21139](https://github.com/astral-sh/ruff/pull/21139))\n- Type inference for comprehensions ([#20962](https://github.com/astral-sh/ruff/pull/20962))\n- Reachability and narrowing for enum methods ([#21130](https://github.com/astral-sh/ruff/pull/21130))\n- Implicit type aliases: Support for PEP 604 unions, `Literal`s, `Optional`, and `Annotated` ([#21195](https://github.com/astral-sh/ruff/pull/21195), [#21296](https://github.com/astral-sh/ruff/pull/21296), [#21321](https://github.com/astral-sh/ruff/pull/21321))\n- `dict` is not assignable to `TypedDict` ([#21238](https://github.com/astral-sh/ruff/pull/21238))\n- Allow values of type `None` in type expressions ([#21263](https://github.com/astral-sh/ruff/pull/21263))\n- Add narrowing for `isinstance()` and `issubclass()` checks that use PEP-604 unions ([#21334](https://github.com/astral-sh/ruff/pull/21334))\n- Do not promote `Literal` types when solving type variables in contravariant positions ([#21164](https://github.com/astral-sh/ruff/pull/21164), <https://github.com/astral-sh/ruff/pull/21171>))\n- Fix lookup of `__new__` methods on instances ([#21147](https://github.com/astral-sh/ruff/pull/21147))\n- Fix narrowing of generic classes in class patterns for `match` statements ([#21150](https://github.com/astral-sh/ruff/pull/21150))\n- Improve understanding of disjointness for `@final` classes ([#21167](https://github.com/astral-sh/ruff/pull/21167))\n- Fix the inferred signature of the synthesized `__init__` method of a non-dataclass inheriting from a generic dataclass ([#21159](https://github.com/astral-sh/ruff/pull/21159))\n- Improve exhaustiveness analysis for type variables with bounds or constraints ([#21172](https://github.com/astral-sh/ruff/pull/21172))\n- Prefer exact matches when solving constrained type variables ([#21165](https://github.com/astral-sh/ruff/pull/21165))\n- Simplify unions containing multiple type variables during inference ([#21275](https://github.com/astral-sh/ruff/pull/21275))\n- Use the declared attribute type when inferring union attribute assignments ([#21170](https://github.com/astral-sh/ruff/pull/21170))\n- Sync vendored typeshed stubs ([#21178](https://github.com/astral-sh/ruff/pull/21178)). [Typeshed diff](https://github.com/python/typeshed/compare/d6f4a0f7102b1400a21742cf9b7ea93614e2b6ec...bf7214784877c52638844c065360d4814fae4c65)\n- Use declared attribute types as type context when solving type variables ([#21143](https://github.com/astral-sh/ruff/pull/21143))\n- Don't union in the inferred type of a parameter's default value when inferring the type of an annotated parameter ([#21208](https://github.com/astral-sh/ruff/pull/21208))\n- Support subscripting typing.Literal with a type alias ([#21207](https://github.com/astral-sh/ruff/pull/21207))\n\n### LSP server\n\n- Don't provide completions when in a class or function definition ([#21146](https://github.com/astral-sh/ruff/pull/21146))\n- Favor symbols defined in the current file over imported symbols ([#21194](https://github.com/astral-sh/ruff/pull/21194)) and builtin symbols ([#21285](https://github.com/astral-sh/ruff/pull/21285))\n\n### Diagnostics\n\n- Add diagnostics for `isinstance()` and `issubclass()` calls that use invalid PEP-604 unions for their second argument ([#21343](https://github.com/astral-sh/ruff/pull/21343))\n- Don't assume in diagnostic messages that a `TypedDict` key error is about subscript access ([#21166](https://github.com/astral-sh/ruff/pull/21166))\n\n### Other changes\n\n- Consistently wrap tokens in parser diagnostics in `backticks` instead of 'quotes' ([#21163](https://github.com/astral-sh/ruff/pull/21163))\n- Discover the `site-packages` directory from the environment that ty is installed in ([#21286](https://github.com/astral-sh/ruff/pull/21286)), improving the ergonomics of `uvx ty check`\n- Support implicit imports of submodules in `__init__.pyi` ([#20855](https://github.com/astral-sh/ruff/pull/20855))\n- Use \"cannot\" consistently over \"can not\" in diagnostics ([#21255](https://github.com/astral-sh/ruff/pull/21255))\n- Resolve `from foo import bar` to the `foo.bar` submodule rather than using the `__getattr__` function in `foo/__init__.py` (in situations where they both exist)([#21260](https://github.com/astral-sh/ruff/pull/21260))\n\n### Contributors\n\n- [@MatthewMckee4](https://github.com/MatthewMckee4)\n- [@dhruvmanila](https://github.com/dhruvmanila)\n- [@sharkdp](https://github.com/sharkdp)\n- [@Gankra](https://github.com/Gankra)\n- [@saada](https://github.com/saada)\n- [@zanieb](https://github.com/zanieb)\n- [@MichaReiser](https://github.com/MichaReiser)\n- [@ibraheemdev](https://github.com/ibraheemdev)\n- [@AlexWaygood](https://github.com/AlexWaygood)\n- [@lucach](https://github.com/lucach)\n- [@mtshiba](https://github.com/mtshiba)\n- [@carljm](https://github.com/carljm)\n\n## 0.0.1-alpha.25\n\nReleased on 2025-10-29.\n\n### Bug fixes\n\n- Fix bug where ty would think all types had an `__mro__` attribute ([#20995](https://github.com/astral-sh/ruff/pull/20995))\n- Fix rare panic with highly cyclic `TypeVar` definitions ([#21059](https://github.com/astral-sh/ruff/pull/21059))\n- Fix infinite recursion with generic type aliases ([#20969](https://github.com/astral-sh/ruff/pull/20969))\n- Add missing newline before first diagnostic in CLI output ([#21058](https://github.com/astral-sh/ruff/pull/21058))\n- Make the ty server's auto-import feature skip symbols in the current module ([#21100](https://github.com/astral-sh/ruff/pull/21100))\n- Don't provide goto-definition for definitions which are not reexported in builtins ([#21127](https://github.com/astral-sh/ruff/pull/21127))\n- Avoid duplicate diagnostics during multi-inference of standalone expressions ([#21056](https://github.com/astral-sh/ruff/pull/21056))\n\n### Type inference and diagnostics\n\n- Use constructor parameter types as context to inform solving type variables ([#21054](https://github.com/astral-sh/ruff/pull/21054))\n- Consider `__len__` when determining the truthiness of an instance of a tuple class or a `@final` class ([#21049](https://github.com/astral-sh/ruff/pull/21049))\n- Delegate truthiness inference of an enum `Literal` type to its enum-instance supertype ([#21060](https://github.com/astral-sh/ruff/pull/21060))\n- Improve `invalid-argument-type` diagnostics where a union type was provided ([#21044](https://github.com/astral-sh/ruff/pull/21044))\n\n### LSP server\n\n- Suggest `type_check_only` items last in completions ([#20910](https://github.com/astral-sh/ruff/pull/20910))\n- Render `import <...>` in completions when \"label details\" isn't supported ([#21109](https://github.com/astral-sh/ruff/pull/21109))\n- Update workspace diagnostic progress every 50ms ([#21019](https://github.com/astral-sh/ruff/pull/21019))\n\n### CLI\n\n- Add `--no-progress` option to suppress the rendering of a progress bar ([#21063](https://github.com/astral-sh/ruff/pull/21063))\n\n### Contributors\n\n- [@ibraheemdev](https://github.com/ibraheemdev)\n- [@MatthewMckee4](https://github.com/MatthewMckee4)\n- [@BurntSushi](https://github.com/BurntSushi)\n- [@mtshiba](https://github.com/mtshiba)\n- [@AlexWaygood](https://github.com/AlexWaygood)\n- [@MichaReiser](https://github.com/MichaReiser)\n- [@decorator-factory](https://github.com/decorator-factory)\n\n## 0.0.1-alpha.24\n\nReleased on 2025-10-23.\n\n### Breaking changes\n\n- Rename `unknown-rule` lint to `ignore-comment-unknown-rule` ([#20948](https://github.com/astral-sh/ruff/pull/20948))\n\n### Type inference and diagnostics\n\n- Infer a type of `Self` for unannotated `self` parameters in methods ([#20922](https://github.com/astral-sh/ruff/pull/20922))\n- Prefer the declared type over the inferred type for invariant collection literals ([#20927](https://github.com/astral-sh/ruff/pull/20927))\n- Use declared variable types as bidirectional type context for solving type variables ([#20796](https://github.com/astral-sh/ruff/pull/20796))\n- Support `dataclass_transform` for base class models ([#20783](https://github.com/astral-sh/ruff/pull/20783))\n- Support dataclass-transform `field_specifiers` ([#20888](https://github.com/astral-sh/ruff/pull/20888))\n- `dataclass_transform` support for fields with an `alias` ([#20961](https://github.com/astral-sh/ruff/pull/20961))\n- Add support for legacy namespace packages ([#20897](https://github.com/astral-sh/ruff/pull/20897))\n- Add suggestion to \"unknown rule\" diagnostics ([#20948](https://github.com/astral-sh/ruff/pull/20948))\n- Improve error messages for \"unresolved attribute\" diagnostics ([#20963](https://github.com/astral-sh/ruff/pull/20963))\n- Avoid unnecessarily widening generic specializations ([#20875](https://github.com/astral-sh/ruff/pull/20875))\n- Truncate `Literal` type display in some situations ([#20928](https://github.com/astral-sh/ruff/pull/20928))\n\n### Bug fixes\n\n- Fix panic involving cyclic `TypeVar` default ([#20967](https://github.com/astral-sh/ruff/pull/20967))\n- Fix panic involving ever-growing default types ([#20991](https://github.com/astral-sh/ruff/pull/20991))\n- Fix panic involving infinitely expanding implicit attribute types ([#20988](https://github.com/astral-sh/ruff/pull/20988))\n- Fix autocomplete suggestions when the cursor is at the end of a file ([#20993](https://github.com/astral-sh/ruff/pull/20993))\n- Fix inconsistent highlighting of self ([#20986](https://github.com/astral-sh/ruff/pull/20986))\n- Fix out-of-order semantic token for function with regular argument after kwargs ([#21013](https://github.com/astral-sh/ruff/pull/21013))\n- Fix panic on recursive class definitions in a stub that use constrained type variables ([#20955](https://github.com/astral-sh/ruff/pull/20955))\n- Fix panic when attempting to validate the members of a protocol that inherits from a protocol in another module ([#20956](https://github.com/astral-sh/ruff/pull/20956))\n- Fix rare hang relating to multithreading ([#21038](https://github.com/astral-sh/ruff/pull/21038))\n- Fix non-deterministic overload function inference ([#20966](https://github.com/astral-sh/ruff/pull/20966))\n- Fix auto-import edits made by autocompletions for files with an existing `from __future__` import ([#20987](https://github.com/astral-sh/ruff/pull/20987))\n\n### LSP server\n\n- Support goto-definition for binary and unary operators ([#21001](https://github.com/astral-sh/ruff/pull/21001))\n- Support goto-definition on vendored typeshed stubs ([#21020](https://github.com/astral-sh/ruff/pull/21020))\n- Provide completions on `TypeVar`s ([#20943](https://github.com/astral-sh/ruff/pull/20943))\n- Display variance when hovering over type variables ([#20900](https://github.com/astral-sh/ruff/pull/20900))\n- Avoid sending an unnecessary \"clear diagnostics\" message for clients supporting [pull diagnostics](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_pullDiagnostics). ([#20989](https://github.com/astral-sh/ruff/pull/20989))\n\n### Other changes\n\n- Report `continue` and `break` statements outside loops as syntax errors ([#20944](https://github.com/astral-sh/ruff/pull/20944))\n\n### Contributors\n\n- [@TaKO8Ki](https://github.com/TaKO8Ki)\n- [@sharkdp](https://github.com/sharkdp)\n- [@InvalidPathException](https://github.com/InvalidPathException)\n- [@AlexWaygood](https://github.com/AlexWaygood)\n- [@mtshiba](https://github.com/mtshiba)\n- [@ibraheemdev](https://github.com/ibraheemdev)\n- [@Gankra](https://github.com/Gankra)\n- [@MichaReiser](https://github.com/MichaReiser)\n\n## 0.0.1-alpha.23\n\nReleased on 2025-10-16.\n\n### Bug fixes\n\n- Fix handling of dataclass `field()`s without default values ([#20914](https://github.com/astral-sh/ruff/pull/20914))\n- Fix false-positive diagnostics on `super()` calls ([#20814](https://github.com/astral-sh/ruff/pull/20814), [#20843](https://github.com/astral-sh/ruff/pull/20843))\n- Fix `match` pattern value narrowing to use equality semantics ([#20882](https://github.com/astral-sh/ruff/pull/20882))\n- Fix \"missing root\" panic when handling completion requests ([#20917](https://github.com/astral-sh/ruff/pull/20917))\n- Fix overwriting of declared base class attributes through undeclared subclass members ([#20764](https://github.com/astral-sh/ruff/pull/20764))\n- Fix runaway execution time for mutually referential instance attributes ([#20645](https://github.com/astral-sh/ruff/pull/20645))\n\n### CLI\n\n- For `unresolved-import` diagnostics, limit the shown import paths to at most five, unless in verbose mode ([#20912](https://github.com/astral-sh/ruff/pull/20912))\n- Write files that are slow to type check to log output ([#20836](https://github.com/astral-sh/ruff/pull/20836))\n- Remove \"pre-release software\" warning ([#20817](https://github.com/astral-sh/ruff/pull/20817))\n\n### LSP server\n\n- Improve ranking of autocomplete suggestions ([#20807](https://github.com/astral-sh/ruff/pull/20807))\n\n### Type inference and diagnostics\n\n- Use return type annotations as context for bidirectional type inference ([#20528](https://github.com/astral-sh/ruff/pull/20528))\n- Use bidirectional type context for `TypedDict` construction ([#20806](https://github.com/astral-sh/ruff/pull/20806))\n- Add support for unpacking of heterogeneous tuples in unions ([#20377](https://github.com/astral-sh/ruff/pull/20377))\n- Add a new diagnostic for generic classes that reference typevars from an enclosing scope ([#20822](https://github.com/astral-sh/ruff/pull/20822))\n- Add hint when accessing standard library module attributes that are not available on the configured Python version ([#20909](https://github.com/astral-sh/ruff/pull/20909))\n- Treat functions, methods, and dynamic types as function-like `Callable`s ([#20842](https://github.com/astral-sh/ruff/pull/20842))\n- Treat `Callable`s as bound-method descriptors in special cases ([#20802](https://github.com/astral-sh/ruff/pull/20802))\n- Treat `Callable` dunder members as bound method descriptors ([#20860](https://github.com/astral-sh/ruff/pull/20860))\n- Sync vendored typeshed stubs ([#20876](https://github.com/astral-sh/ruff/pull/20876)). [Typeshed diff](https://github.com/python/typeshed/compare/91055c730ffcda6311654cf32d663858ece69bad...d6f4a0f7102b1400a21742cf9b7ea93614e2b6ec)\n\n### Performance improvements\n\n- Improve performance by caching union simplification type relations ([#20477](https://github.com/astral-sh/ruff/pull/20477))\n\n### Contributors\n\n- [@mtshiba](https://github.com/mtshiba)\n- [@AlexWaygood](https://github.com/AlexWaygood)\n- [@ericmarkmartin](https://github.com/ericmarkmartin)\n- [@carljm](https://github.com/carljm)\n- [@ntBre](https://github.com/ntBre)\n- [@sharkdp](https://github.com/sharkdp)\n- [@BurntSushi](https://github.com/BurntSushi)\n- [@Gankra](https://github.com/Gankra)\n- [@MichaReiser](https://github.com/MichaReiser)\n- [@dcreager](https://github.com/dcreager)\n\n## 0.0.1-alpha.22\n\nReleased on 2025-10-10.\n\n### Bug fixes\n\n- Enforce that `typing_extensions` must come from a stdlib search path. This fixes a panic that could occur with a confusing backtrace if the `extra-paths` setting was incorrectly used to point to a virtual environment ([#20715](https://github.com/astral-sh/ruff/pull/20715))\n- Fix server panic when opening a project located at `/` in the file system ([#20684](https://github.com/astral-sh/ruff/pull/20684))\n- Fix panics when using `--output-format=gitlab` in CI environments ([#20550](https://github.com/astral-sh/ruff/pull/20550))\n- Fix stack overflows that could occur when attempting to determine if a recursive `NamedTuple` type was disjoint from another type ([#20538](https://github.com/astral-sh/ruff/pull/20538))\n- Fix panics in type inference when legacy TypeVars had bounds, constraints, or defaults that cyclically referred back to the TypeVar definition (directly or indirectly) ([#20598](https://github.com/astral-sh/ruff/pull/20598))\n- Fix situations where a panic during resolution of type-checker query cycles would manifest in a hang ([#20577](https://github.com/astral-sh/ruff/pull/20577))\n- When analyzing a .py file, do not error if there's also a .pyi for that module ([#20461](https://github.com/astral-sh/ruff/pull/20461))\n- Recognise that the runtime object `typing.Protocol` is an instance of `_ProtocolMeta` ([#20488](https://github.com/astral-sh/ruff/pull/20488))\n- Fix logic that attempted to determine whether a user had explicitly activated a Conda environment, which has implications for the search paths ty uses for module resolution ([#20675](https://github.com/astral-sh/ruff/pull/20675))\n- Fix false negatives when iterables with the wrong type are unpacked into a function with a `*args` variadic parameter ([#20511](https://github.com/astral-sh/ruff/pull/20511))\n\n### Support for Python 3.14\n\n- Use 3.14 as the default version ([#20725](https://github.com/astral-sh/ruff/pull/20725), [#20759](https://github.com/astral-sh/ruff/pull/20759), [#20760](https://github.com/astral-sh/ruff/pull/20760))\n- Annotations are deferred by default for 3.14+ ([#20799](https://github.com/astral-sh/ruff/pull/20799))\n- Fix false positives when accessing `__annotate__` (Py3.14+) or `__warningregistry__` as a module global ([#20154](https://github.com/astral-sh/ruff/pull/20154))\n\n### Improvements to `TypeVar` solving and inference of generic types\n\n- Improve solving of a type variable `T` if it appears in a union with non-`TypeVar`s (`T | None`, `T | str | None`, etc.) ([#20749](https://github.com/astral-sh/ruff/pull/20749))\n- More precise type inference for dictionary literals ([#20523](https://github.com/astral-sh/ruff/pull/20523))\n- When solving type variables, use type context to inform whether `Literal` types should be promoted to instance types ([#20776](https://github.com/astral-sh/ruff/pull/20776))\n- Use annotated parameters as type context when solving type variables ([#20635](https://github.com/astral-sh/ruff/pull/20635))\n- Correctly infer the return type of method calls when the method is annotated as returning `Self` ([#20517](https://github.com/astral-sh/ruff/pull/20517), [#20754](https://github.com/astral-sh/ruff/pull/20754))\n- Use type context for inference of generic function calls ([#20476](https://github.com/astral-sh/ruff/pull/20476))\n- Use `C[T]` instead of `C[Unknown]` for the upper bound of `Self` ([#20479](https://github.com/astral-sh/ruff/pull/20479))\n\n### Improvements to assignability, subtyping, and union simplification\n\n- Fix overly strict assignability implementation for intersections with negated gradual elements ([#20773](https://github.com/astral-sh/ruff/pull/20773))\n- Ensure that `C[Any]` is understood as a subtype of `C[object]` if `C` is a covariant generic class ([#20592](https://github.com/astral-sh/ruff/pull/20592))\n- Ensure that `~T` is never considered to be assignable to `T` where `T` is a type variable ([#20606](https://github.com/astral-sh/ruff/pull/20606))\n- Improve assignability/subtyping between two protocol types ([#20368](https://github.com/astral-sh/ruff/pull/20368))\n- Simplify `Any | (Any & T)` to `Any` ([#20593](https://github.com/astral-sh/ruff/pull/20593))\n- Optimise and generalise union/intersection simplification ([#20602](https://github.com/astral-sh/ruff/pull/20602))\n- Make protocol satisfiability checks more principled when a protocol has a method member that is generic over type variables scoped to the function ([#20568](https://github.com/astral-sh/ruff/pull/20568))\n- Fix subtyping of invariant generics specialized with `Any`, ensuring that (for example) `list[Any]` is not considered a subtype of `list[Any]` ([#20650](https://github.com/astral-sh/ruff/pull/20650))\n\n### Server\n\n- Add LSP debug information command ([#20379](https://github.com/astral-sh/ruff/pull/20379))\n- Add support for inlay hints on attribute assignment ([#20485](https://github.com/astral-sh/ruff/pull/20485))\n\n### Improvements to diagnostics\n\n- Improve diagnostics when a positional-only parameter is passed using a keyword argument ([#20495](https://github.com/astral-sh/ruff/pull/20495))\n- Improve disambiguations of class names in diagnostics ([#20603](https://github.com/astral-sh/ruff/pull/20603), [#20756](https://github.com/astral-sh/ruff/pull/20756))\n- Improve diagnostics for bad `@overload` definitions ([#20745](https://github.com/astral-sh/ruff/pull/20745))\n- Truncate type display for long unions in some situations ([#20730](https://github.com/astral-sh/ruff/pull/20730))\n- Rename \"possibly unbound\" diagnostics to \"possibly missing\" ([#20492](https://github.com/astral-sh/ruff/pull/20492))\n\n### Improvements to enum support\n\n- Allow multiple aliases to point to the same member ([#20669](https://github.com/astral-sh/ruff/pull/20669))\n- implement `auto()` for `StrEnum` ([#20524](https://github.com/astral-sh/ruff/pull/20524))\n\n### Improvements to ty's `@overload` implementation\n\n- Support single-starred argument for overload call ([#20223](https://github.com/astral-sh/ruff/pull/20223))\n- Filter overloads using variadic parameters ([#20547](https://github.com/astral-sh/ruff/pull/20547))\n\n### Other typing semantics and features\n\n- Do not union the inferred type of a module-global symbol with `Unknown` for the symbol's type when accessed from external scopes ([#20664](https://github.com/astral-sh/ruff/pull/20664))\n- Ensure that class objects are understood as callable even if they do not override `object.__new__` or `object.__init__` ([#20521](https://github.com/astral-sh/ruff/pull/20521))\n- Add support for `**kwargs` ([#20430](https://github.com/astral-sh/ruff/pull/20430))\n- Ensure first-party module-resolution search paths always appear in a sensible order ([#20629](https://github.com/astral-sh/ruff/pull/20629))\n- Respect `dataclass_transform` parameters for metaclass-based models ([#20780](https://github.com/astral-sh/ruff/pull/20780))\n- Sync vendored typeshed stubs ([#20658](https://github.com/astral-sh/ruff/pull/20658)). [Typeshed diff](https://github.com/python/typeshed/compare/47dbbd6c914a5190d54bc5bd498d1e6633d97db2...91055c730ffcda6311654cf32d663858ece69bad)\n- Bring ty's `TypeIs` narrowing behaviour closer to ty's narrowing behaviour for `isinstance()` checks. ([#20591](https://github.com/astral-sh/ruff/pull/20591))\n- `dataclass_transform`: Support `frozen_default` and `kw_only_default` ([#20761](https://github.com/astral-sh/ruff/pull/20761))\n- Allow any string `Literal` type expression as a key when constructing a `TypedDict` ([#20792](https://github.com/astral-sh/ruff/pull/20792))\n- Add `--venv` as an alias to `--python` on the command line ([#20718](https://github.com/astral-sh/ruff/pull/20718))\n- Add search paths listed in `PYTHONPATH` to search paths used for ty's module resolution ([#20441](https://github.com/astral-sh/ruff/pull/20441), [#20490](https://github.com/astral-sh/ruff/pull/20490))\n\n### Contributors\n\n- [@thejchap](https://github.com/thejchap)\n- [@mtshiba](https://github.com/mtshiba)\n- [@Danielkonge](https://github.com/Danielkonge)\n- [@dcreager](https://github.com/dcreager)\n- [@MatthewMckee4](https://github.com/MatthewMckee4)\n- [@Gankra](https://github.com/Gankra)\n- [@BurntSushi](https://github.com/BurntSushi)\n- [@carljm](https://github.com/carljm)\n- [@dhruvmanila](https://github.com/dhruvmanila)\n- [@sharkdp](https://github.com/sharkdp)\n- [@mmlb](https://github.com/mmlb)\n- [@fgiacome](https://github.com/fgiacome)\n- [@Guillaume-Fgt](https://github.com/Guillaume-Fgt)\n- [@AlexWaygood](https://github.com/AlexWaygood)\n- [@Renkai](https://github.com/Renkai)\n- [@InvalidPathException](https://github.com/InvalidPathException)\n- [@ibraheemdev](https://github.com/ibraheemdev)\n- [@fatelei](https://github.com/fatelei)\n- [@github-actions](https://github.com/github-actions)\n- [@MichaReiser](https://github.com/MichaReiser)\n- [@ntBre](https://github.com/ntBre)\n- [@danparizher](https://github.com/danparizher)\n\n## 0.0.1-alpha.21\n\n### Bug fixes\n\n- Fix inference of constructor calls to generic classes that have explicitly annotated `self` parameters in their `__init__` methods ([#20325](https://github.com/astral-sh/ruff/pull/20325))\n- Fix a stack overflow when computing completions for recursive types ([#20354](https://github.com/astral-sh/ruff/pull/20354))\n- Fix panic in `BoundMethodType::into_callable_type()` ([#20369](https://github.com/astral-sh/ruff/pull/20369))\n- Fix stack overflows in binary comparison inference ([#20446](https://github.com/astral-sh/ruff/pull/20446))\n- Fix many \"too many cycle iterations\" panics concerning recursive type aliases and/or recursive generics ([#20359](https://github.com/astral-sh/ruff/pull/20359))\n- Fix stack overflow involving subtype checks for recursive type aliases ([#20259](https://github.com/astral-sh/ruff/pull/20259))\n- Fix panic when inferring the type of an infinitely-nested-tuple implicit instance attribute ([#20333](https://github.com/astral-sh/ruff/pull/20333))\n\n### Server\n\n- Add autocomplete suggestions for unimported symbols ([#20207](https://github.com/astral-sh/ruff/pull/20207), [#20439](https://github.com/astral-sh/ruff/pull/20439))\n- Include generated `NamedTuple` methods such as `_make`, `_asdict` and `_replace` in autocomplete suggestions ([#20356](https://github.com/astral-sh/ruff/pull/20356))\n\n### Configuration\n\n- Automatically add `python/` to `environment.root` if a `python/` folder exists in the root of a repository ([#20263](https://github.com/astral-sh/ruff/pull/20263))\n\n### CLI\n\n- Add GitHub output format ([#20358](https://github.com/astral-sh/ruff/pull/20358))\n- Add GitLab output format ([#20155](https://github.com/astral-sh/ruff/pull/20155))\n\n### Typing semantics and features\n\n- Add support for generic [PEP-695 type aliases](https://peps.python.org/pep-0695/#generic-type-alias) ([#20219](https://github.com/astral-sh/ruff/pull/20219))\n- Allow annotation expressions to be `ast::Attribute` nodes ([#20413](https://github.com/astral-sh/ruff/pull/20413))\n- Allow protocols to participate in nominal subtyping as well as structural subtyping ([#20314](https://github.com/astral-sh/ruff/pull/20314))\n- Attribute access on top/bottom materializations ([#20221](https://github.com/astral-sh/ruff/pull/20221))\n- Bind `Self` type variables to the method, not the class ([#20366](https://github.com/astral-sh/ruff/pull/20366))\n- Ensure various special-cased bound methods are understood as assignable to `Callable` ([#20330](https://github.com/astral-sh/ruff/pull/20330))\n- Ensure various special-cased builtin functions are understood as assignable to `Callable` ([#20331](https://github.com/astral-sh/ruff/pull/20331))\n- Fall back to `object` for attribute access on synthesized protocols ([#20286](https://github.com/astral-sh/ruff/pull/20286))\n- Fix signature of `NamedTupleLike._make` ([#20302](https://github.com/astral-sh/ruff/pull/20302))\n- Fix subtyping/assignability of function- and class-literal types to callback protocols ([#20363](https://github.com/astral-sh/ruff/pull/20363))\n- Implement the legacy PEP-484 convention for indicating positional-only parameters ([#20248](https://github.com/astral-sh/ruff/pull/20248))\n- Infer more precise types for collection literals ([#20360](https://github.com/astral-sh/ruff/pull/20360))\n- Make `TypeIs` invariant in its type argument ([#20428](https://github.com/astral-sh/ruff/pull/20428))\n- Narrow specialized generics using `isinstance()` ([#20256](https://github.com/astral-sh/ruff/pull/20256))\n- Proper assignability/subtyping checks for protocols with method members ([#20165](https://github.com/astral-sh/ruff/pull/20165))\n- Reduce false positives for `ParamSpec`s and `TypeVarTuple`s ([#20239](https://github.com/astral-sh/ruff/pull/20239))\n- Overload evaluation: retry parameter matching for argument type expansion ([#20153](https://github.com/astral-sh/ruff/pull/20153))\n- Simplify unions of enum literals and subtypes thereof ([#20324](https://github.com/astral-sh/ruff/pull/20324))\n- Support \"legacy\" `typing.Self` in combination with [PEP-695](https://peps.python.org/pep-0695) generic contexts ([#20304](https://github.com/astral-sh/ruff/pull/20304))\n- Treat `Hashable`, and similar protocols, equivalently to `object` for subtyping/assignability ([#20284](https://github.com/astral-sh/ruff/pull/20284))\n- Treat `__new__` as a static method ([#20212](https://github.com/astral-sh/ruff/pull/20212))\n- `TypedDict`: Add support for `typing.ReadOnly` ([#20241](https://github.com/astral-sh/ruff/pull/20241))\n- Detect syntax errors stemming from `yield from` expressions inside async functions ([#20051](https://github.com/astral-sh/ruff/pull/20051))\n- `\"foo\".startswith` is not an instance of `types.MethodWrapperType` ([#20317](https://github.com/astral-sh/ruff/pull/20317))\n- Eliminate definitely-impossible types from union in equality narrowing ([#20164](https://github.com/astral-sh/ruff/pull/20164))\n- Infer more precise types for the `name` and `value` properties on enum members ([#20311](https://github.com/astral-sh/ruff/pull/20311))\n- Initial support for `slots=True` in dataclasses ([#20278](https://github.com/astral-sh/ruff/pull/20278))\n- Improve type narrowing in situations involving nested functions ([#19932](https://github.com/astral-sh/ruff/pull/19932))\n- Support type aliases in binary comparison inference ([#20445](https://github.com/astral-sh/ruff/pull/20445))\n- Sync vendored typeshed stubs ([#20394](https://github.com/astral-sh/ruff/pull/20394)). [Typeshed diff](https://github.com/python/typeshed/compare/2480d7e7c74493a024eaf254c5d2c6f452c80ee2...47dbbd6c914a5190d54bc5bd498d1e6633d97db2)\n\n### Diagnostics\n\n- Improve specialization-error diagnostics ([#20326](https://github.com/astral-sh/ruff/pull/20326))\n\n### Contributors\n\n- [@thejchap](https://github.com/thejchap)\n- [@AlexWaygood](https://github.com/AlexWaygood)\n- [@mtshiba](https://github.com/mtshiba)\n- [@JelleZijlstra](https://github.com/JelleZijlstra)\n- [@ibraheemdev](https://github.com/ibraheemdev)\n- [@TaKO8Ki](https://github.com/TaKO8Ki)\n- [@Glyphack](https://github.com/Glyphack)\n- [@ericmarkmartin](https://github.com/ericmarkmartin)\n- [@Renkai](https://github.com/Renkai)\n- [@sharkdp](https://github.com/sharkdp)\n- [@11happy](https://github.com/11happy)\n- [@BurntSushi](https://github.com/BurntSushi)\n- [@carljm](https://github.com/carljm)\n- [@dhruvmanila](https://github.com/dhruvmanila)\n- [@github-actions](https://github.com/github-actions)\n- [@ntBre](https://github.com/ntBre)\n\n## 0.0.1-alpha.20\n\n### Bug fixes\n\n- Server: Cancel background tasks when shutdown is requested ([#20039](https://github.com/astral-sh/ruff/pull/20039))\n- Server: Close signature help after `)` ([#20017](https://github.com/astral-sh/ruff/pull/20017))\n- Server: Fix incorrect docstring in call signature completion ([#20021](https://github.com/astral-sh/ruff/pull/20021))\n- Fix 'too many cycle iterations' for unions of literals ([#20137](https://github.com/astral-sh/ruff/pull/20137))\n- Fix namespace packages that behave like partial stubs ([#19994](https://github.com/astral-sh/ruff/pull/19994))\n- Fix server hang (unchanged diagnostics) when changing file on Windows ([#19991](https://github.com/astral-sh/ruff/pull/19991))\n- Apply `KW_ONLY` sentinel only to local fields ([#19986](https://github.com/astral-sh/ruff/pull/19986))\n- Ignore field specifiers when not specified in `@dataclass_transform` ([#20002](https://github.com/astral-sh/ruff/pull/20002))\n\n### Server\n\n- Add completion support for `import` and `from ... import` statements ([#19883](https://github.com/astral-sh/ruff/pull/19883))\n- Add type as detail to completion items ([#20047](https://github.com/astral-sh/ruff/pull/20047))\n- Ask the LSP client to watch all project search paths ([#19975](https://github.com/astral-sh/ruff/pull/19975))\n- Fix incorrect inlay hint type ([#20044](https://github.com/astral-sh/ruff/pull/20044))\n- Update goto definition, goto declaration and hover to consider constructor method (`__init__`) ([#20014](https://github.com/astral-sh/ruff/pull/20014))\n- Add docstrings to completions based on type ([#20008](https://github.com/astral-sh/ruff/pull/20008))\n- Fix goto targets for keyword arguments in nested function calls ([#20013](https://github.com/astral-sh/ruff/pull/20013))\n- Introduce multiline pretty printer to render function signatures across multiple lines ([#19979](https://github.com/astral-sh/ruff/pull/19979))\n\n### Configuration\n\n- Distinguish base conda from child conda ([#19990](https://github.com/astral-sh/ruff/pull/19990))\n\n### Typing semantics and features\n\n- Add support for PEP 750: t-strings ([#20085](https://github.com/astral-sh/ruff/pull/20085))\n- Add support for PEP 800: Disjoint bases ([#20084](https://github.com/astral-sh/ruff/pull/20084))\n- Add precise inference for unpacking a TypeVar if the TypeVar has an upper bound with a precise tuple spec ([#19985](https://github.com/astral-sh/ruff/pull/19985))\n- Add precise iteration and unpacking inference for string literals and bytes literals ([#20023](https://github.com/astral-sh/ruff/pull/20023))\n- Completely ignore typeshed's stub for `Any` ([#20079](https://github.com/astral-sh/ruff/pull/20079))\n- Enforce that an attribute on a class `X` must be callable in order to satisfy a member on a protocol `P` ([#20142](https://github.com/astral-sh/ruff/pull/20142))\n- Evaluate static truthiness of non-definitely-bound symbols to \"ambiguous\" ([#19579](https://github.com/astral-sh/ruff/pull/19579))\n- Fix the inferred interface of specialized generic protocols ([#19866](https://github.com/astral-sh/ruff/pull/19866))\n- Infer slightly more precise types for comprehensions ([#20111](https://github.com/astral-sh/ruff/pull/20111))\n- Disable boundness analysis for implicit instance attributes ([#20128](https://github.com/astral-sh/ruff/pull/20128))\n- Add `Top[]` and `Bottom[]` special forms ([#20054](https://github.com/astral-sh/ruff/pull/20054))\n- Preserve qualifiers when accessing attributes on unions/intersections ([#20114](https://github.com/astral-sh/ruff/pull/20114))\n- Strict validation of protocol members ([#17750](https://github.com/astral-sh/ruff/pull/17750))\n- Support `__init_subclass__` ([#20190](https://github.com/astral-sh/ruff/pull/20190))\n- Unpack variadic argument type in specialization ([#20130](https://github.com/astral-sh/ruff/pull/20130))\n- Use `invalid-assignment` error code for invalid assignments to `ClassVar`s ([#20156](https://github.com/astral-sh/ruff/pull/20156))\n- Use specialized parameter type for overload filter ([#19964](https://github.com/astral-sh/ruff/pull/19964))\n- `__class_getitem__` is a classmethod ([#20192](https://github.com/astral-sh/ruff/pull/20192))\n- Add cycle detection for find_legacy_typevars ([#20124](https://github.com/astral-sh/ruff/pull/20124))\n- Add support for cyclic legacy generic protocols ([#20125](https://github.com/astral-sh/ruff/pull/20125))\n- Don't eagerly unpack aliases in user-authored unions ([#20055](https://github.com/astral-sh/ruff/pull/20055))\n- Don't mark entire type-alias scopes as Deferred ([#20086](https://github.com/astral-sh/ruff/pull/20086))\n- Ensure union normalization really normalizes ([#20147](https://github.com/astral-sh/ruff/pull/20147))\n- Improve cycle-detection coverage for apply_type_mapping ([#20159](https://github.com/astral-sh/ruff/pull/20159))\n- Linear variance inference for PEP-695 type parameters ([#18713](https://github.com/astral-sh/ruff/pull/18713))\n- Minor `TypedDict` fixes ([#20146](https://github.com/astral-sh/ruff/pull/20146))\n- Typecheck dict methods for `TypedDict` ([#19874](https://github.com/astral-sh/ruff/pull/19874))\n- Validate constructor call of `TypedDict` ([#19810](https://github.com/astral-sh/ruff/pull/19810))\n- Sync vendored typeshed stubs ([#20031](https://github.com/astral-sh/ruff/pull/20031), [#20083](https://github.com/astral-sh/ruff/pull/20083), [#20188](https://github.com/astral-sh/ruff/pull/20188)) [Typeshed diff](https://github.com/python/typeshed/compare/893b9a760deb3be64d13c748318e95a752230961...2480d7e7c74493a024eaf254c5d2c6f452c80ee2)\n\n### Diagnostics\n\n- Add search paths info to unresolved import diagnostics ([#20040](https://github.com/astral-sh/ruff/pull/20040))\n- Better error message for attempting to assign to a read-only property ([#20150](https://github.com/astral-sh/ruff/pull/20150))\n- Improve diagnostics for bad calls to functions ([#20022](https://github.com/astral-sh/ruff/pull/20022))\n- Improve disambiguation of types via fully qualified names ([#20141](https://github.com/astral-sh/ruff/pull/20141))\n- Print diagnostics with fully qualified name to disambiguate some cases ([#19850](https://github.com/astral-sh/ruff/pull/19850))\n\n### Performance\n\n- Avoid unnecessary argument type expansion ([#19999](https://github.com/astral-sh/ruff/pull/19999))\n- Limit argument expansion size for overload call evaluation ([#20041](https://github.com/astral-sh/ruff/pull/20041))\n- Optimize TDD atom ordering ([#20098](https://github.com/astral-sh/ruff/pull/20098))\n\n### Contributors\n\n- [@carljm](https://github.com/carljm)\n- [@sharkdp](https://github.com/sharkdp)\n- [@dylwil3](https://github.com/dylwil3)\n- [@dcreager](https://github.com/dcreager)\n- [@MichaReiser](https://github.com/MichaReiser)\n- [@ericmarkmartin](https://github.com/ericmarkmartin)\n- [@Renkai](https://github.com/Renkai)\n- [@JelleZijlstra](https://github.com/JelleZijlstra)\n- [@BurntSushi](https://github.com/BurntSushi)\n- [@AlexWaygood](https://github.com/AlexWaygood)\n- [@github-actions](https://github.com/github-actions)\n- [@PrettyWood](https://github.com/PrettyWood)\n- [@dhruvmanila](https://github.com/dhruvmanila)\n- [@Glyphack](https://github.com/Glyphack)\n- [@Gankra](https://github.com/Gankra)\n- [@MatthewMckee4](https://github.com/MatthewMckee4)\n- [@leandrobbraga](https://github.com/leandrobbraga)\n\n## 0.0.1-alpha.19\n\n### Bug fixes\n\n- Fix false-positive diagnostics if a function parameter is annotated with `type[P]` where `P` is a protocol class ([#19947](https://github.com/astral-sh/ruff/pull/19947))\n- Fix ANSI colors in terminal output on old Windows terminals ([#19984](https://github.com/astral-sh/ruff/pull/19984))\n- Fix protocol interface inference for protocols in stub files with `ClassVar` members and \"subprotocols\" that extend other protocols ([#19950](https://github.com/astral-sh/ruff/pull/19950))\n- Fix inference of equality comparisons between enum members ([#19666](https://github.com/astral-sh/ruff/pull/19666))\n- Remove incorrect type narrowing for `if type(x) is C[int]` ([#19926](https://github.com/astral-sh/ruff/pull/19926))\n- Improve detection of `TypeError`s resulting from protocol classes illegally inheriting from non-protocol classes ([#19941](https://github.com/astral-sh/ruff/pull/19941)). We previously detected this error, but only when the protocol class illegally inherited from a non-generic class or an unspecialized generic class. We now also detect it when the protocol class inherits from a specialized generic class.\n- Fix incorrectly precise type inference in some situations involving nested scopes ([#19908](https://github.com/astral-sh/ruff/pull/19908))\n- Fix unpacking a type alias with a precise tuple spec ([#19981](https://github.com/astral-sh/ruff/pull/19981))\n\n### `NamedTuple` semantics improvements\n\n- Synthesize read-only properties for all declared members on `NamedTuple` classes ([#19899](https://github.com/astral-sh/ruff/pull/19899))\n- Allow any instance of a `NamedTuple` class to be passed to a function parameter annotated with `typing.NamedTuple` ([#19915](https://github.com/astral-sh/ruff/pull/19915))\n- Detect `NamedTuple` classes where fields without default values illegally follow fields with default values ([#19945](https://github.com/astral-sh/ruff/pull/19945)). This causes `TypeError` to be raised at runtime.\n- Detect illegal multiple inheritance with `NamedTuple` ([#19943](https://github.com/astral-sh/ruff/pull/19943)). This causes `TypeError` to be raised at runtime.\n\n### Other typing and semantics improvements\n\n- Add support for stubs packages with `partial` in their `py.typed` files ([#19931](https://github.com/astral-sh/ruff/pull/19931))\n- Look for `site-packages` directories in `<sys.prefix>/lib64/` as well as `<sys.prefix>/lib/` on non-Windows systems ([#19978](https://github.com/astral-sh/ruff/pull/19978)). This change fixes a number of `unresolved-import` false-positive diagnostics reported by Poetry users.\n- Add diagnostics for invalid `await` expressions ([#19711](https://github.com/astral-sh/ruff/pull/19711))\n- Add `else`-branch narrowing for `if type(a) is A` when `A` is `@final` ([#19925](https://github.com/astral-sh/ruff/pull/19925))\n- Improve solving of typevars with defaults, and `typing.Self` ([#19786](https://github.com/astral-sh/ruff/pull/19786))\n- Support the `kw_only` parameter for `dataclasses.dataclass()` and `dataclasses.field()` ([#19677](https://github.com/astral-sh/ruff/pull/19677))\n- Sync vendored typeshed stubs ([#19923](https://github.com/astral-sh/ruff/pull/19923)). [Typeshed diff](https://github.com/python/typeshed/compare/3f08a4ed10b321c378107c236a06a33584869a9b...893b9a760deb3be64d13c748318e95a752230961).\n\n### Server improvements\n\n- Improve goto/hover for definitions ([#19976](https://github.com/astral-sh/ruff/pull/19976))\n\n### Performance improvements\n\n- Short-circuit a server [inlay hints request](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_inlayHint) if all settings under `ty.inlayHints` are disabled ([#19963](https://github.com/astral-sh/ruff/pull/19963))\n- Speedup server tracing checks ([#19965](https://github.com/astral-sh/ruff/pull/19965))\n- Add caching to logic for inferring whether a class is a `NamedTuple`, a dataclass or a `TypedDict` ([#19912](https://github.com/astral-sh/ruff/pull/19912))\n- Speedup project file discovery ([#19913](https://github.com/astral-sh/ruff/pull/19913))\n\n### Contributors\n\n- [@dcreager](https://github.com/dcreager)\n- [@MichaReiser](https://github.com/MichaReiser)\n- [@sharkdp](https://github.com/sharkdp)\n- [@github-actions](https://github.com/github-actions)\n- [@mtshiba](https://github.com/mtshiba)\n- [@theammir](https://github.com/theammir)\n- [@AlexWaygood](https://github.com/AlexWaygood)\n- [@thejchap](https://github.com/thejchap)\n- [@Gankra](https://github.com/Gankra)\n- [@MatthewMckee4](https://github.com/MatthewMckee4)\n- [@carljm](https://github.com/carljm)\n\n## 0.0.1-alpha.18\n\n### Bug fixes\n\n- Fix goto definition on imports ([#19834](https://github.com/astral-sh/ruff/pull/19834))\n- Support non-generic recursive type aliases that use [the `type` statement](https://docs.python.org/3/reference/simple_stmts.html#grammar-token-python-grammar-type_stmt) ([#19805](https://github.com/astral-sh/ruff/pull/19805))\n- Handle cycles when finding implicit attributes ([#19833](https://github.com/astral-sh/ruff/pull/19833))\n\n### Server\n\n- Implement support for \"rename\" language server feature ([#19551](https://github.com/astral-sh/ruff/pull/19551))\n- Add `ty.experimental.rename` server setting ([#19800](https://github.com/astral-sh/ruff/pull/19800))\n- Add `ty.inlayHints.variableTypes` server setting ([#19780](https://github.com/astral-sh/ruff/pull/19780))\n- Add inlay hints for call arguments (configured by `ty.inlayHints.callArgumentNames` server setting) ([#19269](https://github.com/astral-sh/ruff/pull/19269))\n- Enable goto definition to jump to the runtime definition in the standard library for stdlib symbols (rather than the type definition in typeshed's stubs) ([#19529](https://github.com/astral-sh/ruff/pull/19529))\n- Support LSP client settings ([#19614](https://github.com/astral-sh/ruff/pull/19614))\n- Update goto range for attribute access to only target the attribute ([#19848](https://github.com/astral-sh/ruff/pull/19848))\n- Warn users if the server received unknown options ([#19779](https://github.com/astral-sh/ruff/pull/19779))\n- Render docstrings in hover ([#19882](https://github.com/astral-sh/ruff/pull/19882))\n- Resolve docstrings for modules ([#19898](https://github.com/astral-sh/ruff/pull/19898))\n\n### Typing semantics and features\n\n- Add precise inference for indexing, slicing and unpacking `NamedTuple` instances ([#19560](https://github.com/astral-sh/ruff/pull/19560))\n- Disallow `typing.TypedDict` in type expressions ([#19777](https://github.com/astral-sh/ruff/pull/19777))\n- Implement module-level `__getattr__` support ([#19791](https://github.com/astral-sh/ruff/pull/19791))\n- Improve ability to solve TypeVars when they appear in unions ([#19829](https://github.com/astral-sh/ruff/pull/19829))\n- Improve subscript narrowing for `collections.ChainMap`, `collections.Counter`, `collections.deque` and `collections.OrderedDict` ([#19781](https://github.com/astral-sh/ruff/pull/19781))\n- Extend all tuple special casing to tuple subclasses ([#19669](https://github.com/astral-sh/ruff/pull/19669))\n- Use separate Rust types for bound and unbound type variables ([#19796](https://github.com/astral-sh/ruff/pull/19796))\n- Validate writes to `TypedDict` keys ([#19782](https://github.com/astral-sh/ruff/pull/19782))\n- `typing.Self` is bound by the method, not the class ([#19784](https://github.com/astral-sh/ruff/pull/19784))\n- Fix deferred name loading in PEP695 generic classes/functions ([#19888](https://github.com/astral-sh/ruff/pull/19888))\n- Improve handling of symbol-lookup edge cases involving class scopes ([#19795](https://github.com/astral-sh/ruff/pull/19795))\n\n### Performance\n\n- Improve performance around tuple types ([#19840](https://github.com/astral-sh/ruff/pull/19840))\n- Improve performance of subtyping and assignability checks for protocols ([#19824](https://github.com/astral-sh/ruff/pull/19824))\n- Improve multithreaded performance for large codebases ([#19867](https://github.com/astral-sh/ruff/pull/19867))\n\n### Memory usage optimizations\n\n- Reduce memory usage of `TupleSpec` and `TupleType` ([#19872](https://github.com/astral-sh/ruff/pull/19872))\n- Reduce size of member table ([#19572](https://github.com/astral-sh/ruff/pull/19572))\n\n### Contributors\n\n- [@AlexWaygood](https://github.com/AlexWaygood)\n- [@Gankra](https://github.com/Gankra)\n- [@ntbre](https://github.com/ntBre)\n- [@MichaReiser](https://github.com/MichaReiser)\n- [@PrettyWood](https://github.com/PrettyWood)\n- [@dhruvmanila](https://github.com/dhruvmanila)\n- [@carljm](https://github.com/carljm)\n- [@dcreager](https://github.com/dcreager)\n- [@UnboundVariable](https://github.com/UnboundVariable)\n- [@sharkdp](https://github.com/sharkdp)\n- [@oconnor663](https://github.com/oconnor663)\n- [@MatthewMckee4](https://github.com/MatthewMckee4)\n\n## 0.0.1-alpha.17\n\n### Bug fixes\n\n- Always refresh diagnostics after a watched files change ([#19697](https://github.com/astral-sh/ruff/pull/19697))\n- Correctly instantiate generic class that inherits `__init__` from generic base class ([#19693](https://github.com/astral-sh/ruff/pull/19693))\n- Don't panic with argument that doesn't actually implement Iterable ([#19602](https://github.com/astral-sh/ruff/pull/19602))\n- Fix \"peek definition\" in playground ([#19592](https://github.com/astral-sh/ruff/pull/19592))\n- Fix empty spans following a line terminator and unprintable character spans in diagnostics ([#19535](https://github.com/astral-sh/ruff/pull/19535))\n- Fix incorrect diagnostic when calling `__setitem__` ([#19645](https://github.com/astral-sh/ruff/pull/19645))\n- Fix lookup order of class variables before they are defined ([#19743](https://github.com/astral-sh/ruff/pull/19743))\n- Fix more false positives related to `Generic` or `Protocol` being subscripted with a `ParamSpec` or `TypeVarTuple` ([#19764](https://github.com/astral-sh/ruff/pull/19764))\n- Keep track of type qualifiers in stub declarations without right-hand side ([#19756](https://github.com/astral-sh/ruff/pull/19756))\n\n### Server\n\n- Add progress reporting to workspace diagnostics ([#19616](https://github.com/astral-sh/ruff/pull/19616))\n- Add stub mapping support to signature help ([#19570](https://github.com/astral-sh/ruff/pull/19570))\n- Added support for \"document symbols\" and \"workspace symbols\" ([#19521](https://github.com/astral-sh/ruff/pull/19521))\n- Fix server panic in workspace diagnostics request handler when typing ([#19631](https://github.com/astral-sh/ruff/pull/19631))\n- Implement caching for workspace and document diagnostics ([#19605](https://github.com/astral-sh/ruff/pull/19605))\n- Implement long-polling for workspace diagnostics ([#19670](https://github.com/astral-sh/ruff/pull/19670))\n- Implement streaming for workspace diagnostics ([#19657](https://github.com/astral-sh/ruff/pull/19657))\n- Implemented support for \"selection range\" language server feature ([#19567](https://github.com/astral-sh/ruff/pull/19567))\n\n### CLI\n\n- Add progress bar to `--watch` mode ([#19729](https://github.com/astral-sh/ruff/pull/19729))\n- Clear the terminal screen in `--watch` mode ([#19712](https://github.com/astral-sh/ruff/pull/19712))\n- Resolve file symlinks in src walk ([#19674](https://github.com/astral-sh/ruff/pull/19674))\n\n### Typing semantics and features\n\n- Support `async`/`await`, `async with` and `yield from` ([#19595](https://github.com/astral-sh/ruff/pull/19595))\n- Add support for `async for` loops and async iterables ([#19634](https://github.com/astral-sh/ruff/pull/19634))\n- Don't include already-bound legacy typevars in function generic context ([#19558](https://github.com/astral-sh/ruff/pull/19558))\n- Infer types for key-based access on `TypedDict`s ([#19763](https://github.com/astral-sh/ruff/pull/19763))\n- Improve `isinstance()` truthiness analysis for generic types ([#19668](https://github.com/astral-sh/ruff/pull/19668))\n- Infer `type[tuple[int, str]]` as the meta-type of `tuple[int, str]` ([#19741](https://github.com/astral-sh/ruff/pull/19741))\n- Remove false positives when subscripting `Generic` or `Protocol` with a `ParamSpec` or `TypeVarTuple` ([#19749](https://github.com/astral-sh/ruff/pull/19749))\n- Remove special casing for string-literal-in-tuple `__contains__` ([#19642](https://github.com/astral-sh/ruff/pull/19642))\n- Remove special casing for tuple addition ([#19636](https://github.com/astral-sh/ruff/pull/19636))\n- Return `Option<TupleType>` from `infer_tuple_type_expression` ([#19735](https://github.com/astral-sh/ruff/pull/19735))\n- Support `as`-patterns in reachability analysis ([#19728](https://github.com/astral-sh/ruff/pull/19728))\n- Support `__setitem__` and improve `__getitem__` related diagnostics ([#19578](https://github.com/astral-sh/ruff/pull/19578))\n- Synthesize precise `__getitem__` overloads for tuple subclasses ([#19493](https://github.com/astral-sh/ruff/pull/19493))\n- Track different uses of legacy typevars, including context when rendering typevars ([#19604](https://github.com/astral-sh/ruff/pull/19604))\n- Upcast heterogeneous and mixed tuples to homogeneous tuples where it's necessary to solve a `TypeVar` ([#19635](https://github.com/astral-sh/ruff/pull/19635))\n- Fix incorrect lazy scope narrowing ([#19744](https://github.com/astral-sh/ruff/pull/19744))\n- Synthesize `__replace__` for dataclasses ([#19545](https://github.com/astral-sh/ruff/pull/19545))\n\n### Diagnostics\n\n- Add diagnostics for async context managers ([#19704](https://github.com/astral-sh/ruff/pull/19704))\n- Display generic function signature properly ([#19544](https://github.com/astral-sh/ruff/pull/19544))\n- Improve the `Display` for generic `type[]` types ([#19667](https://github.com/astral-sh/ruff/pull/19667))\n- Remap Jupyter notebook cell indices in `ruff_db` ([#19698](https://github.com/astral-sh/ruff/pull/19698))\n\n### Documentation\n\n- Add the `ty` badge ([#897](https://github.com/astral-sh/ty/pull/897))\n\n### Contributors\n\n- [@mtshiba](https://github.com/mtshiba)\n- [@MichaReiser](https://github.com/MichaReiser)\n- [@sharkdp](https://github.com/sharkdp)\n- [@github-actions](https://github.com/github-actions)\n- [@UnboundVariable](https://github.com/UnboundVariable)\n- [@jorenham](https://github.com/jorenham)\n- [@silamon](https://github.com/silamon)\n- [@AlexWaygood](https://github.com/AlexWaygood)\n- [@thejchap](https://github.com/thejchap)\n- [@ngroman](https://github.com/ngroman)\n- [@leandrobbraga](https://github.com/leandrobbraga)\n- [@dcreager](https://github.com/dcreager)\n- [@ntbre](https://github.com/ntBre)\n- [@MatthewMckee4](https://github.com/MatthewMckee4)\n\n## 0.0.1-alpha.16\n\n### Bug fixes\n\n- Fix server panics when hovering over invalid syntax in `Callable` annotations ([#19517](https://github.com/astral-sh/ruff/pull/19517))\n- `match` statements: Fix narrowing and reachability of class patterns with arguments ([#19512](https://github.com/astral-sh/ruff/pull/19512))\n- Fix server panics when hovering over illegal `Literal[…]` annotations with inner subscript expressions ([#19489](https://github.com/astral-sh/ruff/pull/19489))\n- Pass down specialization to generic dataclass bases ([#19472](https://github.com/astral-sh/ruff/pull/19472))\n\n### Server\n\n- Add support for \"go to definition\" for attribute accesses and keyword arguments ([#19417](https://github.com/astral-sh/ruff/pull/19417))\n- Add support for \"go to definition\" for import statements ([#19428](https://github.com/astral-sh/ruff/pull/19428))\n- Add support for \"document highlights\" ([#19515](https://github.com/astral-sh/ruff/pull/19515))\n- Add partial support for \"find references\" ([#19475](https://github.com/astral-sh/ruff/pull/19475))\n- Prefer the runtime definition, not the stub definition, on a go-to-definition request for a class or function. Currently this is only implemented for definitions originating outside of the stdlib. ([#19471](https://github.com/astral-sh/ruff/pull/19471))\n- Add [semantic token](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_semanticTokens) support for more identifiers ([#19473](https://github.com/astral-sh/ruff/pull/19473))\n- Avoid rechecking the entire project when a file in the editor is opened or closed ([#19463](https://github.com/astral-sh/ruff/pull/19463))\n\n### Typing semantics and features\n\n- Handle splatted arguments in function calls ([#18996](https://github.com/astral-sh/ruff/pull/18996))\n- Improve place lookup and narrowing in lazy scopes ([#19321](https://github.com/astral-sh/ruff/pull/19321))\n- Add exhaustiveness checking and reachability analysis for `match` statements ([#19508](https://github.com/astral-sh/ruff/pull/19508))\n- Improve reachability analysis for `isinstance(…)` branches ([#19503](https://github.com/astral-sh/ruff/pull/19503))\n- Make tuple subclass constructors sound ([#19469](https://github.com/astral-sh/ruff/pull/19469))\n- Extend tuple `__len__` and `__bool__` special casing to also cover tuple subclasses ([#19289](https://github.com/astral-sh/ruff/pull/19289))\n- Add support for `dataclasses.field` ([#19553](https://github.com/astral-sh/ruff/pull/19553))\n- Add support for `dataclasses.InitVar` ([#19527](https://github.com/astral-sh/ruff/pull/19527))\n- Add support for `@warnings.deprecated` and `typing_extensions.deprecated` ([#19376](https://github.com/astral-sh/ruff/pull/19376))\n- Do not consider a type `T` to satisfy a method member on a protocol unless the method is available on the meta-type of `T` ([#19187](https://github.com/astral-sh/ruff/pull/19187))\n- Implement expansion of enums into unions of literals ([#19382](https://github.com/astral-sh/ruff/pull/19382))\n- Support iterating over enums ([#19486](https://github.com/astral-sh/ruff/pull/19486))\n- Detect enums if metaclass is a subtype of `EnumType` / `EnumMeta` ([#19481](https://github.com/astral-sh/ruff/pull/19481))\n- Infer single-valuedness for enums deriving from `int` or `str` ([#19510](https://github.com/astral-sh/ruff/pull/19510))\n- Detect illegal non-enum attribute accesses in `Literal` annotations ([#19477](https://github.com/astral-sh/ruff/pull/19477))\n- Disallow assignment to `Final` class attributes ([#19457](https://github.com/astral-sh/ruff/pull/19457))\n- Handle implicit instance attributes declared `Final` ([#19462](https://github.com/astral-sh/ruff/pull/19462))\n- Disallow `Final` in function parameter- and return-type annotations ([#19480](https://github.com/astral-sh/ruff/pull/19480))\n- Disallow illegal uses of `ClassVar` ([#19483](https://github.com/astral-sh/ruff/pull/19483))\n- Make `del x` force a local resolution of `x` in the current scope ([#19389](https://github.com/astral-sh/ruff/pull/19389))\n- Perform type narrowing for places marked `global` ([#19381](https://github.com/astral-sh/ruff/pull/19381))\n- Infer correct types for attribute accesses on intersections with negative parts ([#19524](https://github.com/astral-sh/ruff/pull/19524))\n- Sync vendored typeshed stubs ([typeshed diff](https://github.com/python/typeshed/compare/84e41f2853d7af3d651d620f093031cba849bd1d...08225953c98cfd375d80bc88865e5aae77d2c07f))\n\n### Memory usage optimizations\n\n- Reduce ty's memory usage (for example: [#19409](https://github.com/astral-sh/ruff/pull/19409), [#19435](https://github.com/astral-sh/ruff/pull/19435), [#19414](https://github.com/astral-sh/ruff/pull/19414))\n\n### Contributors\n\n- [@sharkdp](https://github.com/sharkdp)\n- [@BurntSushi](https://github.com/BurntSushi)\n- [@oconnor663](https://github.com/oconnor663)\n- [@Gankra](https://github.com/Gankra)\n- [@carljm](https://github.com/carljm)\n- [@AlexWaygood](https://github.com/AlexWaygood)\n- [@MichaReiser](https://github.com/MichaReiser)\n- [@dcreager](https://github.com/dcreager)\n- [@mtshiba](https://github.com/mtshiba)\n- [@UnboundVariable](https://github.com/UnboundVariable)\n\n## 0.0.1-alpha.15\n\n### Bug fixes\n\n- Avoid stale diagnostics for open-files diagnostic mode ([#19273](https://github.com/astral-sh/ruff/pull/19273))\n- Fix inconsistent semantic syntax highlighting for parameters ([#19418](https://github.com/astral-sh/ruff/pull/19418))\n- Fix checking of virtual files after re-opening from an unsaved edit ([#19277](https://github.com/astral-sh/ruff/pull/19277))\n- Show the correct ty version in the LSP server ([#19284](https://github.com/astral-sh/ruff/pull/19284))\n- Do not surface settings errors in unrelated Python files ([#19206](https://github.com/astral-sh/ruff/pull/19206))\n- Do not ignore conditionally defined dataclass fields ([#19197](https://github.com/astral-sh/ruff/pull/19197))\n- Fix panic for attribute expressions with empty value ([#19069](https://github.com/astral-sh/ruff/pull/19069))\n- Fix assignabiliy of dataclasses to `Callable` types ([#19192](https://github.com/astral-sh/ruff/pull/19192))\n- Fix `__setattr__` call check precedence during attribute assignment ([#18347](https://github.com/astral-sh/ruff/pull/18347))\n\n### Server\n\n- Add definition and declaration providers (go-to-definition, go-to-declaration) ([#19371](https://github.com/astral-sh/ruff/pull/19371))\n- Add signature help provider (show signature and docstring when writing a call expression) ([#19194](https://github.com/astral-sh/ruff/pull/19194))\n- Add \"kind\" to completion suggestions ([#19216](https://github.com/astral-sh/ruff/pull/19216))\n- Add completions for submodules that aren't attributes of their parent ([#19266](https://github.com/astral-sh/ruff/pull/19266))\n- Filter out private type aliases from stub files when offering autocomplete suggestions ([#19282](https://github.com/astral-sh/ruff/pull/19282))\n- Handle configuration errors in the LSP more gracefully ([#19262](https://github.com/astral-sh/ruff/pull/19262))\n- Use Python version and path from VSCode Python extension ([#19012](https://github.com/astral-sh/ruff/pull/19012))\n- Publish errors in settings as LSP diagnostics ([#19335](https://github.com/astral-sh/ruff/pull/19335))\n\n### Typing semantics and features\n\n- Add support for `nonlocal` statements ([#19112](https://github.com/astral-sh/ruff/pull/19112))\n- Support empty function bodies in `if TYPE_CHECKING` blocks ([#19372](https://github.com/astral-sh/ruff/pull/19372))\n- Emit a diagnostic when attempting to modify a `typing.Final`-qualified symbol ([#19178](https://github.com/astral-sh/ruff/pull/19178))\n- Infer enum literal types when accessing enum members ([#19328](https://github.com/astral-sh/ruff/pull/19328))\n- Synthesize `__setattr__` for frozen dataclasses ([#19307](https://github.com/astral-sh/ruff/pull/19307))\n- Improve equivalence for module-literal types ([#19243](https://github.com/astral-sh/ruff/pull/19243))\n- Reduce false positives for `TypedDict` types ([#19354](https://github.com/astral-sh/ruff/pull/19354))\n- Emit an error for `global` uses if there is no explicit definition in the global scope ([#19344](https://github.com/astral-sh/ruff/pull/19344))\n- Sync vendored typeshed stubs ([typeshed diff](https://github.com/python/typeshed/compare/f64707592dd3c32f756ddeebd012acb2b072aa0d...84e41f2853d7af3d651d620f093031cba849bd1d))\n\n### CLI\n\n- Add a `-q`/`--quiet` mode, `-qq` for silent output mode ([#19233](https://github.com/astral-sh/ruff/pull/19233))\n\n### Contributors\n\n- [@AlexWaygood](https://github.com/AlexWaygood)\n- [@github-actions](https://github.com/github-actions)\n- [@dhruvmanila](https://github.com/dhruvmanila)\n- [@sharkdp](https://github.com/sharkdp)\n- [@renovate](https://github.com/renovate)\n- [@MatthewMckee4](https://github.com/MatthewMckee4)\n- [@UnboundVariable](https://github.com/UnboundVariable)\n- [@oconnor663](https://github.com/oconnor663)\n- [@zanieb](https://github.com/zanieb)\n- [@MichaReiser](https://github.com/MichaReiser)\n- [@charliermarsh](https://github.com/charliermarsh)\n- [@Gankra](https://github.com/Gankra)\n- [@thejchap](https://github.com/thejchap)\n- [@BurntSushi](https://github.com/BurntSushi)\n- [@mdqst](https://github.com/mdqst)\n\n## 0.0.1-alpha.14\n\n### Bug fixes\n\n- Add cycle detection to ty's implementation of disjointness between types, fixing a possible source of stack overflows when analysing recursive types ([#19139](https://github.com/astral-sh/ruff/pull/19139))\n- Don't allow first-party code to shadow the stdlib `types` module ([#19128](https://github.com/astral-sh/ruff/pull/19128)).\n    This fixes another possible source of stack overflows.\n- Fix descriptor lookups for most types that overlap with `None` ([#19120](https://github.com/astral-sh/ruff/pull/19120)).\n    This means that e.g. `object().__str__()` now correctly binds the `self` argument of the `__str__`\n    method, as the `object` type overlaps with `None`.\n\n### Server\n\n- Filter a symbol from a stub file in autocomplete suggestions if it is an implementation detail of the stub ([#19121](https://github.com/astral-sh/ruff/pull/19121))\n- Add initial support for [semantic tokens](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_semanticTokens) ([#19108](https://github.com/astral-sh/ruff/pull/19108)).\n    This feature allows editors to apply more advanced syntax highlighting. Currently, the supported tokens are: `Namespace`, `Class`, `Parameter`, `SelfParameter`,`ClsParameter`, `Variable`, `Property`, `Function`, `Method`, `Keyword`, `String`, `Number`, `Decorator`, `BuiltinConstant` and `TypeParameter`.\n- Initial support for [workspace diagnostics](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#workspace_diagnostic) ([#18939](https://github.com/astral-sh/ruff/pull/18939)).\n    Enable this feature by setting the `ty.diagnosticMode` configuration setting to `\"workspace\"`.\n- Use Python syntax highlighting in on-hover content ([#19082](https://github.com/astral-sh/ruff/pull/19082))\n\n### Typing semantics and features\n\n- Understand that calls to functions returning `Never` / `NoReturn` are terminal with respect to control flow ([#18333](https://github.com/astral-sh/ruff/pull/18333))\n- Add subtyping between `type[]` types and `Callable` types ([#19026](https://github.com/astral-sh/ruff/pull/19026))\n- Support bare `ClassVar` annotations ([#15768](https://github.com/astral-sh/ruff/pull/15768))\n- Understand that two protocols with equivalent method members are equivalent ([#18659](https://github.com/astral-sh/ruff/pull/18659))\n- Support declared-only instance attributes such as `self.x: int` ([#19048](https://github.com/astral-sh/ruff/pull/19048))\n- Sync vendored typeshed stubs ([#19174](https://github.com/astral-sh/ruff/pull/19174)): [typeshed diff](https://github.com/python/typeshed/compare/3f727b0cd6620b7fca45318dd34542b1e1c7dbfb...f64707592dd3c32f756ddeebd012acb2b072aa0d)\n- Use the inferred type as the declared type for bare `Final` symbols ([#19142](https://github.com/astral-sh/ruff/pull/19142))\n\n### Contributors\n\n- [@iyakushev](https://github.com/iyakushev)\n- [@MatthewMckee4](https://github.com/MatthewMckee4)\n- [@zanieb](https://github.com/zanieb)\n- [@sharkdp](https://github.com/sharkdp)\n- [@UnboundVariable](https://github.com/UnboundVariable)\n- [@abhijeetbodas2001](https://github.com/abhijeetbodas2001)\n- [@github-actions](https://github.com/github-actions)\n- [@dhruvmanila](https://github.com/dhruvmanila)\n- [@AlexWaygood](https://github.com/AlexWaygood)\n- [@carljm](https://github.com/carljm)\n- [@CodeMan62](https://github.com/CodeMan62)\n\n## 0.0.1-alpha.13\n\n### Bug fixes\n\n- Fix stack overflows related to mutually recursive protocols ([#19003](https://github.com/astral-sh/ruff/pull/19003))\n- Don't add incorrect subdiagnostic for `unresolved-reference` in `staticmethod`s and `classmethod`s ([#18487](https://github.com/astral-sh/ruff/pull/18487))\n- Fix rendering of long lines in diagnostic messages that are indented with tabs ([#18962](https://github.com/astral-sh/ruff/pull/18962))\n- Fix reachability of star import definitions for nonlocal lookups ([#19066](https://github.com/astral-sh/ruff/pull/19066))\n\n### Typing semantics and features\n\n- Support variable-length tuples in unpacking assignments ([#18948](https://github.com/astral-sh/ruff/pull/18948))\n- Allow declared-only class-level attributes to be accessed on the class ([#19071](https://github.com/astral-sh/ruff/pull/19071))\n- Infer nonlocal types as unions of all reachable bindings ([#18750](https://github.com/astral-sh/ruff/pull/18750))\n- Use all reachable bindings for instance attributes and deferred lookups ([#18955](https://github.com/astral-sh/ruff/pull/18955))\n- Improve protocol member type checking and relation handling ([#18847](https://github.com/astral-sh/ruff/pull/18847))\n- Rework disjointness of protocol instances vs types with possibly unbound attributes, preventing some false instances of `Never` in `hasattr` narrowing ([#19043](https://github.com/astral-sh/ruff/pull/19043))\n- Make tuple instantiations sound ([#18987](https://github.com/astral-sh/ruff/pull/18987))\n- Add subdiagnostic about empty bodies in more cases ([#18942](https://github.com/astral-sh/ruff/pull/18942))\n- Improve type-inference for `__import__(name)` and `importlib.import_module(name)` ([#19008](https://github.com/astral-sh/ruff/pull/19008))\n- Eagerly evaluate certain constraints when analyzing control flow ([#18998](https://github.com/astral-sh/ruff/pull/18998), [#19044](https://github.com/astral-sh/ruff/pull/19044), [#19068](https://github.com/astral-sh/ruff/pull/19068))\n- Update typeshed stubs ([#19060](https://github.com/astral-sh/ruff/pull/19060)): [typeshed diff](https://github.com/python/typeshed/compare/ecd5141cc036366cc9e3ca371096d6a14b0ccd13...3f727b0cd6620b7fca45318dd34542b1e1c7dbfb)\n\n### Server\n\n- Add `builtins` to completions ([#18982](https://github.com/astral-sh/ruff/pull/18982))\n- Support LSP go-to with vendored typeshed stubs ([#19057](https://github.com/astral-sh/ruff/pull/19057))\n\n### Documentation\n\n- The ty documentation is now available at [docs.astral.sh/ty](https://docs.astral.sh/ty) ([#744](https://github.com/astral-sh/ty/pull/744))\n\n### Performance\n\n- Remove `ScopedExpressionId` ([#19019](https://github.com/astral-sh/ruff/pull/19019))\n\n### Contributors\n\n- [@InSyncWithFoo](https://github.com/InSyncWithFoo)\n- [@MatthewMckee4](https://github.com/MatthewMckee4)\n- [@dcreager](https://github.com/dcreager)\n- [@mtshiba](https://github.com/mtshiba)\n- [@BurntSushi](https://github.com/BurntSushi)\n- [@sharkdp](https://github.com/sharkdp)\n- [@ibraheemdev](https://github.com/ibraheemdev)\n- [@github-actions](https://github.com/github-actions)\n- [@carljm](https://github.com/carljm)\n- [@AlexWaygood](https://github.com/AlexWaygood)\n- [@MichaReiser](https://github.com/MichaReiser)\n- [@zanieb](https://github.com/zanieb)\n\n## 0.0.1-alpha.12\n\n### Bug fixes\n\n- Avoid duplicate diagnostic when reporting errors in unpacked assignments ([#18897](https://github.com/astral-sh/ruff/pull/18897))\n- Fix panics when \"pulling types\" for `ClassVar` or `Final` parameterized with >1 argument ([#18824](https://github.com/astral-sh/ruff/pull/18824)). These could cause issues when hovering over symbols in an IDE.\n\n### Improved modeling of Python runtime semantics\n\n- Add support for `@staticmethod`s ([#18809](https://github.com/astral-sh/ruff/pull/18809))\n- Discover implicit class attribute assignments in `@classmethod`-decorated methods. Recognize that assignments in the body of a `@staticmethod`-decorated method are never instance attributes ([#18587](https://github.com/astral-sh/ruff/pull/18587))\n- Report when a dataclass contains more than one `KW_ONLY` field ([#18731](https://github.com/astral-sh/ruff/pull/18731))\n\n### Type narrowing improvements\n\n- Ty will now perform `isinstance()` and `issubclass()` narrowing when the second argument is a union type, intersection type or `TypeVar` type ([#18900](https://github.com/astral-sh/ruff/pull/18900))\n- Ty now narrows types in comprehensions and generator expressions ([#18934](https://github.com/astral-sh/ruff/pull/18934))\n- Understand two `NominalInstanceType`s as disjoint types if attempting to use multiple inheritance with their underlying classes would result in an instance memory layout conflict ([#18864](https://github.com/astral-sh/ruff/pull/18864))\n\n### Other typing semantics features\n\n- Support \"mixed\" tuples such as `tuple[int, *tuple[str, ...]]` ([#18600](https://github.com/astral-sh/ruff/pull/18600), [#18901](https://github.com/astral-sh/ruff/pull/18901))\n- Support type inference for subscript expressions on union types ([#18846](https://github.com/astral-sh/ruff/pull/18846))\n- Introduce a new subtyping framework in which gradual types can participate, allowing for more advanced union type simplification ([#18799](https://github.com/astral-sh/ruff/pull/18799))\n- Surface the matched overload directly when reporting a diagnostic for an invalid call to an overloaded function ([#18452](https://github.com/astral-sh/ruff/pull/18452))\n\n### Improvements to server autocompletions\n\n- Add completions for `from module import <CURSOR>` ([#18830](https://github.com/astral-sh/ruff/pull/18830))\n- Enforce sort order of completions ([#18917](https://github.com/astral-sh/ruff/pull/18917))\n- Include imported sub-modules as attributes on modules for completions ([#18898](https://github.com/astral-sh/ruff/pull/18898))\n\n### Configuration\n\n- Anchor all `src.exclude` patterns, for consistency with `src.include` patterns ([#18685](https://github.com/astral-sh/ruff/pull/18685))\n- Change `environment.root` to accept multiple paths ([#18913](https://github.com/astral-sh/ruff/pull/18913))\n- Rename `src.root` setting to `environment.root` ([#18760](https://github.com/astral-sh/ruff/pull/18760))\n- Support `--python=<symlink to executable>` ([#18827](https://github.com/astral-sh/ruff/pull/18827))\n\n### Contributors\n\n- [@BurntSushi](https://github.com/BurntSushi)\n- [@InSyncWithFoo](https://github.com/InSyncWithFoo)\n- [@suneettipirneni](https://github.com/suneettipirneni)\n- [@AlexWaygood](https://github.com/AlexWaygood)\n- [@dhruvmanila](https://github.com/dhruvmanila)\n- [@sharkdp](https://github.com/sharkdp)\n- [@MichaReiser](https://github.com/MichaReiser)\n- [@med1844](https://github.com/med1844)\n- [@dcreager](https://github.com/dcreager)\n- [@carljm](https://github.com/carljm)\n\n## 0.0.1-alpha.11\n\n### Breaking changes\n\n- Stabilize auto-complete; remove the opt-in experimental setting ([#18650](https://github.com/astral-sh/ruff/pull/18650))\n\n### Bug fixes\n\n- Fix binary expression inference between Boolean literals and `bool` instances ([#18663](https://github.com/astral-sh/ruff/pull/18663))\n- Fix panic that could occur when printing a class's \"header\" in diagnostic messages ([#18670](https://github.com/astral-sh/ruff/pull/18670))\n- Fix panic when attempting to provide autocompletions for an instance of a class that assigns attributes to `self[0]` ([#18707](https://github.com/astral-sh/ruff/pull/18707))\n- Fix panics when \"pulling types\" for various special forms that have the wrong number of parameters. These could cause issues when hovering over symbols in an IDE. ([#18642](https://github.com/astral-sh/ruff/pull/18642))\n\n### Typing semantics and features\n\n- Support type narrowing for attribute and subscript expressions ([#17643](https://github.com/astral-sh/ruff/pull/17643))\n- Add partial support for `TypeIs` ([#18589](https://github.com/astral-sh/ruff/pull/18589))\n- Support `dataclasses.KW_ONLY` ([#18677](https://github.com/astral-sh/ruff/pull/18677))\n- Filter overloads based on `Any` / `Unknown` ([#18607](https://github.com/astral-sh/ruff/pull/18607))\n- Improve reachability analysis ([#18621](https://github.com/astral-sh/ruff/pull/18621))\n- Model `T: Never` as a subtype of `Never` ([#18687](https://github.com/astral-sh/ruff/pull/18687))\n- Update typeshed stubs ([#18679](https://github.com/astral-sh/ruff/pull/18679)): [typeshed diff](https://github.com/python/typeshed/compare/5a3c495d2f6fa9b68cd99f39feba4426e4d17ea9...ecd5141cc036366cc9e3ca371096d6a14b0ccd13)\n\n### Configuration\n\n- Allow overriding rules for specific files ([#18648](https://github.com/astral-sh/ruff/pull/18648))\n\n### Server\n\n- Add `python.ty.disableLanguageServices` config ([#18230](https://github.com/astral-sh/ruff/pull/18230))\n\n### Contributors\n\n- [@dhruvmanila](https://github.com/dhruvmanila)\n- [@felixscherz](https://github.com/felixscherz)\n- [@MichaReiser](https://github.com/MichaReiser)\n- [@alpaylan](https://github.com/alpaylan)\n- [@mtshiba](https://github.com/mtshiba)\n- [@github-actions](https://github.com/github-actions)\n- [@BurntSushi](https://github.com/BurntSushi)\n- [@InSyncWithFoo](https://github.com/InSyncWithFoo)\n- [@AlexWaygood](https://github.com/AlexWaygood)\n- [@abhijeetbodas2001](https://github.com/abhijeetbodas2001)\n- [@sharkdp](https://github.com/sharkdp)\n- [@ibraheemdev](https://github.com/ibraheemdev)\n\n## 0.0.1-alpha.10\n\n### Server\n\n- Improve support for `object.<CURSOR>` completions ([#18629](https://github.com/astral-sh/ruff/pull/18629))\n\n### Configuration\n\n- Add file inclusion and exclusion ([#18498](https://github.com/astral-sh/ruff/pull/18498))\n- Infer the Python version from `--python=<system installation>` on Unix ([#18550](https://github.com/astral-sh/ruff/pull/18550))\n\n### Bug fixes\n\n- Delay computation of 'unbound' visibility for implicit instance attributes ([#18669](https://github.com/astral-sh/ruff/pull/18669)).\n    This fixes a significant performance regression in version 0.0.1-alpha.9.\n\n### Typing semantics and features\n\n- Support the `del` statement; model implicit deletion of except handler names ([#18593](https://github.com/astral-sh/ruff/pull/18593))\n\n### Release\n\n- Include ruff/ directory in release source tarballs ([#617](https://github.com/astral-sh/ty/pull/617))\n\n### Contributors\n\n- [@AlexWaygood](https://github.com/AlexWaygood)\n- [@BurntSushi](https://github.com/BurntSushi)\n- [@Gankra](https://github.com/Gankra)\n- [@mtshiba](https://github.com/mtshiba)\n- [@sharkdp](https://github.com/sharkdp)\n- [@dhruvmanila](https://github.com/dhruvmanila)\n- [@MichaReiser](https://github.com/MichaReiser)\n\n## 0.0.1-alpha.9\n\n### Typing semantics and features\n\n- Add generic inference for dataclasses ([#18443](https://github.com/astral-sh/ruff/pull/18443))\n- Add support for global `__debug__` constant ([#18540](https://github.com/astral-sh/ruff/pull/18540))\n- Argument type expansion for overload call evaluation ([#18382](https://github.com/astral-sh/ruff/pull/18382))\n- Exclude members starting with `_abc_` from a protocol interface ([#18467](https://github.com/astral-sh/ruff/pull/18467))\n- Infer `list[T]` for starred target in unpacking ([#18401](https://github.com/astral-sh/ruff/pull/18401))\n- Infer `list[T]` when unpacking non-tuple type ([#18438](https://github.com/astral-sh/ruff/pull/18438))\n- Support type annotation for legacy typing aliases for generic classes ([#18404](https://github.com/astral-sh/ruff/pull/18404))\n- Allow using `dataclasses.dataclass` as a function ([#18440](https://github.com/astral-sh/ruff/pull/18440))\n- Type narrowing for attribute/subscript assignments ([#18041](https://github.com/astral-sh/ruff/pull/18041))\n\n### Diagnostics\n\n- Add hints to `invalid-type-form` for common mistakes ([#18543](https://github.com/astral-sh/ruff/pull/18543))\n- Add subdiagnostic suggestion to `unresolved-reference` diagnostic when variable exists on `self` ([#18444](https://github.com/astral-sh/ruff/pull/18444))\n- Track the origin of the `environment.python` setting for better error messages ([#18483](https://github.com/astral-sh/ruff/pull/18483))\n\n### CLI\n\n- Fix `--python` argument for Windows, and improve error messages for bad `--python` arguments ([#18457](https://github.com/astral-sh/ruff/pull/18457))\n\n### Bug fixes\n\n- Meta-type of type variables should be `type[..]` ([#18439](https://github.com/astral-sh/ruff/pull/18439))\n- Only consider a type `T` a subtype of a protocol `P` if all of `P`'s members are fully bound on `T` ([#18466](https://github.com/astral-sh/ruff/pull/18466))\n- Fix false positives for legacy `ParamSpec`s inside `Callable` type expressions ([#18426](https://github.com/astral-sh/ruff/pull/18426))\n- Fix panic when pulling types for `UnaryOp` expressions inside `Literal` slices ([#18536](https://github.com/astral-sh/ruff/pull/18536))\n- Fix panic when trying to pull types for attribute expressions inside `Literal` type expressions ([#18535](https://github.com/astral-sh/ruff/pull/18535))\n- Fix panic when trying to pull types for subscript expressions inside `Callable` type expressions ([#18534](https://github.com/astral-sh/ruff/pull/18534))\n- Treat lambda functions as instances of `types.FunctionType` ([#18431](https://github.com/astral-sh/ruff/pull/18431))\n- Implement disjointness between `Callable` and `SpecialForm` ([#18503](https://github.com/astral-sh/ruff/pull/18503))\n\n### Server\n\n- Fix stale diagnostics in documents on Windows ([#18544](https://github.com/astral-sh/ruff/pull/18544))\n- Add support for `object.<CURSOR>` completions ([#18468](https://github.com/astral-sh/ruff/pull/18468))\n- Only provide declarations and bindings as completions ([#18456](https://github.com/astral-sh/ruff/pull/18456))\n\n### Documentation\n\n- Add `CONDA_PREFIX` to `--python` documentation ([#18574](https://github.com/astral-sh/ruff/pull/18574))\n- Update list of referenced environment variables ([#612](https://github.com/astral-sh/ty/pull/612))\n- Document how the default value for `python-version` is determined ([#18549](https://github.com/astral-sh/ruff/pull/18549))\n- Document the `\"all\"` option for `python-platform` ([#18548](https://github.com/astral-sh/ruff/pull/18548))\n\n### Contributors\n\n- [@AlexWaygood](https://github.com/AlexWaygood)\n- [@charliermarsh](https://github.com/charliermarsh)\n- [@mtshiba](https://github.com/mtshiba)\n- [@benbaror](https://github.com/benbaror)\n- [@sharkdp](https://github.com/sharkdp)\n- [@carljm](https://github.com/carljm)\n- [@MichaReiser](https://github.com/MichaReiser)\n- [@lipefree](https://github.com/lipefree)\n- [@BurntSushi](https://github.com/BurntSushi)\n- [@DetachHead](https://github.com/DetachHead)\n- [@MatthewMckee4](https://github.com/MatthewMckee4)\n- [@suneettipirneni](https://github.com/suneettipirneni)\n- [@abhijeetbodas2001](https://github.com/abhijeetbodas2001)\n- [@ibraheemdev](https://github.com/ibraheemdev)\n- [@dhruvmanila](https://github.com/dhruvmanila)\n\n## 0.0.1-alpha.8\n\n### Typing semantics and features\n\n- Add subtyping between Callable types and class literals with `__init__` ([#17638](https://github.com/astral-sh/ruff/pull/17638))\n- Implement implicit inheritance from `Generic[]` for PEP-695 generic classes ([#18283](https://github.com/astral-sh/ruff/pull/18283))\n- Infer the Python version from the environment if feasible ([#18057](https://github.com/astral-sh/ruff/pull/18057))\n- Support ephemeral uv virtual environments ([#18335](https://github.com/astral-sh/ruff/pull/18335))\n- Model that some `Callable` types should have all `FunctionType` attributes available ([#18242](https://github.com/astral-sh/ruff/pull/18242))\n\n### Diagnostics\n\n- Add diagnostic hints for a function that has a non-`None` return-type annotation but no return statements ([#18359](https://github.com/astral-sh/ruff/pull/18359))\n- Add hint if async context manager is used in non-async with statement ([#18299](https://github.com/astral-sh/ruff/pull/18299))\n- Improve diagnostics if the user attempts to import a stdlib module that does not exist on their configured Python version ([#18403](https://github.com/astral-sh/ruff/pull/18403))\n- Tell the user why we inferred a certain Python version when reporting version-specific syntax errors ([#18295](https://github.com/astral-sh/ruff/pull/18295))\n\n### Bug fixes\n\n- Fix multithreading related hangs and panics ([#18238](https://github.com/astral-sh/ruff/pull/18238))\n- Ensure `Literal` types are considered assignable to anything their `Instance` supertypes are assignable to ([#18351](https://github.com/astral-sh/ruff/pull/18351))\n- Callable types are disjoint from non-callable `@final` nominal instance types ([#18368](https://github.com/astral-sh/ruff/pull/18368))\n- Support callability of bound/constrained typevars ([#18389](https://github.com/astral-sh/ruff/pull/18389))\n\n### Server\n\n- Fix server hang after shutdown request ([#18414](https://github.com/astral-sh/ruff/pull/18414))\n- Improve completions by leveraging scopes ([#18281](https://github.com/astral-sh/ruff/pull/18281))\n- Support cancellation and retry in the server ([#18273](https://github.com/astral-sh/ruff/pull/18273))\n- Support publishing diagnostics in the server ([#18309](https://github.com/astral-sh/ruff/pull/18309))\n\n### CLI\n\n- Add `--config-file` CLI arg ([#18083](https://github.com/astral-sh/ruff/pull/18083))\n\n### Contributors\n\n- [@AlexWaygood](https://github.com/AlexWaygood)\n- [@BurntSushi](https://github.com/BurntSushi)\n- [@lipefree](https://github.com/lipefree)\n- [@MatthewMckee4](https://github.com/MatthewMckee4)\n- [@dhruvmanila](https://github.com/dhruvmanila)\n- [@zanieb](https://github.com/zanieb)\n- [@carljm](https://github.com/carljm)\n- [@thejchap](https://github.com/thejchap)\n- [@sharkdp](https://github.com/sharkdp)\n- [@InSyncWithFoo](https://github.com/InSyncWithFoo)\n- [@MichaReiser](https://github.com/MichaReiser)\n\n## 0.0.1-alpha.7\n\n### Bug fixes\n\n- Implement Python's floor-division semantics for `Literal` `int`s ([#18249](https://github.com/astral-sh/ruff/pull/18249))\n- Don't warn about a `yield` expression not being in a function if the `yield` expression is in a function ([#18008](https://github.com/astral-sh/ruff/pull/18008))\n- Fix inference of attribute writes to unions/intersections that including module-literal types ([#18313](https://github.com/astral-sh/ruff/pull/18313))\n- Fix false-positive diagnostics in binary comparison inference logic for intersection types ([#18266](https://github.com/astral-sh/ruff/pull/18266))\n- Fix instance vs callable subtyping/assignability ([#18260](https://github.com/astral-sh/ruff/pull/18260))\n- Ignore `ClassVar` declarations when resolving instance members ([#18241](https://github.com/astral-sh/ruff/pull/18241))\n- Fix crash when hovering over a `ty_extensions.Intersection[A, B]` expression in an IDE context ([#18321](https://github.com/astral-sh/ruff/pull/18321))\n- Respect `MRO_NO_OBJECT_FALLBACK` policy when looking up symbols on `type` instances ([#18312](https://github.com/astral-sh/ruff/pull/18312))\n- `get_protocol_members` returns a frozenset, not a tuple ([#18284](https://github.com/astral-sh/ruff/pull/18284))\n\n### Typing semantics and features\n\n- Support `import <namespace>` and `from <namespace> import module` ([#18137](https://github.com/astral-sh/ruff/pull/18137))\n- Support frozen dataclasses ([#17974](https://github.com/astral-sh/ruff/pull/17974))\n- Understand that the presence of a `__getattribute__` method indicates arbitrary members can exist on a type ([#18280](https://github.com/astral-sh/ruff/pull/18280))\n- Add a subdiagnostic if `invalid-return-type` is emitted on a method with an empty body on a non-protocol subclass of a protocol class ([#18243](https://github.com/astral-sh/ruff/pull/18243))\n- Improve `invalid-type-form` diagnostic where a module-literal type is used in a type expression and the module has a member which would be valid in a type expression ([#18244](https://github.com/astral-sh/ruff/pull/18244))\n- Split `invalid-base` error code into two error codes ([#18245](https://github.com/astral-sh/ruff/pull/18245))\n- Rename `call-possibly-unbound-method` to `possibly-unbound-implicit-call` ([#18017](https://github.com/astral-sh/ruff/pull/18017))\n\n### Configuration\n\n- Add `tests` to `src.root` by default if a `tests/` directory exists and is not a package ([#18286](https://github.com/astral-sh/ruff/pull/18286))\n- Tell the user why we inferred the Python version we inferred ([#18082](https://github.com/astral-sh/ruff/pull/18082))\n- Add support for detecting activated Conda and Pixi environments ([#18267](https://github.com/astral-sh/ruff/pull/18267))\n- Move `respect-ignore-files` configuration setting under `src` section ([#18322](https://github.com/astral-sh/ruff/pull/18322))\n\n### Server\n\n- Fix server panic when calling `system_mut` ([#18252](https://github.com/astral-sh/ruff/pull/18252))\n- Abort process if worker thread panics ([#18211](https://github.com/astral-sh/ruff/pull/18211))\n- Gracefully handle salsa cancellations and panics in background request handlers ([#18254](https://github.com/astral-sh/ruff/pull/18254))\n\n### Contributors\n\n- [@felixscherz](https://github.com/felixscherz)\n- [@carljm](https://github.com/carljm)\n- [@j178](https://github.com/j178)\n- [@thejchap](https://github.com/thejchap)\n- [@brainwane](https://github.com/brainwane)\n- [@AlexWaygood](https://github.com/AlexWaygood)\n- [@lipefree](https://github.com/lipefree)\n- [@InSyncWithFoo](https://github.com/InSyncWithFoo)\n- [@brandtbucher](https://github.com/brandtbucher)\n- [@MichaReiser](https://github.com/MichaReiser)\n- [@maxmynter](https://github.com/maxmynter)\n- [@fabridamicelli](https://github.com/fabridamicelli)\n- [@sharkdp](https://github.com/sharkdp)\n\n## 0.0.1-alpha.6\n\n### Server\n\n- Add rule link to server diagnostics ([#18128](https://github.com/astral-sh/ruff/pull/18128))\n- Avoid panicking when there are multiple workspaces ([#18151](https://github.com/astral-sh/ruff/pull/18151))\n- Show related information in diagnostic ([#17359](https://github.com/astral-sh/ruff/pull/17359))\n\n### Configuration\n\n- Default `src.root` setting to `['.', '<project_name>']` if an `src/` directory does not exist but a `<project-name>/<project-name>` directory does exist ([#18141](https://github.com/astral-sh/ruff/pull/18141))\n\n### Typing semantics and features\n\n- Consider a class with a dynamic element in its MRO assignable to any subtype of `type` ([#18205](https://github.com/astral-sh/ruff/pull/18205))\n- Ensure that a function-literal type is always considered equivalent to itself ([#18227](https://github.com/astral-sh/ruff/pull/18227))\n- Promote literals when inferring class specializations from constructors ([#18102](https://github.com/astral-sh/ruff/pull/18102))\n- Support `typing.TypeAliasType` ([#18156](https://github.com/astral-sh/ruff/pull/18156))\n- Infer function-call type variables in both directions ([#18155](https://github.com/astral-sh/ruff/pull/18155))\n\n### Improvements to modeling of runtime semantics\n\n- Integer indexing into `bytes` returns `int` ([#18218](https://github.com/astral-sh/ruff/pull/18218))\n- Emit `invalid-exception-caught` diagnostics even when the caught exception is not bound to a variable ([#18202](https://github.com/astral-sh/ruff/pull/18202))\n\n### Usability improvements\n\n- Add hint to some diagnostics that [PEP 604](https://peps.python.org/pep-0604/) union syntax is only available on Python 3.10+ ([#18192](https://github.com/astral-sh/ruff/pull/18192))\n- Add note to `unresolved-import` diagnostic hinting to users to configure their Python environment ([#18207](https://github.com/astral-sh/ruff/pull/18207))\n- Make `division-by-zero` an opt-in diagnostic rather than opt-out ([#18220](https://github.com/astral-sh/ruff/pull/18220))\n\n### Import resolution improvements\n\n- Add support for PyPy virtual environments ([#18203](https://github.com/astral-sh/ruff/pull/18203))\n\n### Contributors\n\n- [@dhruvmanila](https://github.com/dhruvmanila)\n- [@InSyncWithFoo](https://github.com/InSyncWithFoo)\n- [@AlexWaygood](https://github.com/AlexWaygood)\n- [@MichaReiser](https://github.com/MichaReiser)\n- [@BradonZhang](https://github.com/BradonZhang)\n- [@dcreager](https://github.com/dcreager)\n- [@danielhollas](https://github.com/danielhollas)\n- [@esadek](https://github.com/esadek)\n- [@kiran-4444](https://github.com/kiran-4444)\n- [@Mathemmagician](https://github.com/Mathemmagician)\n- [@sharkdp](https://github.com/sharkdp)\n- [@felixscherz](https://github.com/felixscherz)\n- [@adamaaronson](https://github.com/adamaaronson)\n- [@carljm](https://github.com/carljm)\n\n## 0.0.1-alpha.5\n\n### Bug fixes\n\n- Fix assignability checks for invariant generics parameterized by gradual types ([#18138](https://github.com/astral-sh/ruff/pull/18138))\n- Revert boolean expression control flow change which caused a performance regression ([#18150](https://github.com/astral-sh/ruff/pull/18150))\n- Remove pyvenv.cfg validation check for lines with multiple `=` ([#18144](https://github.com/astral-sh/ruff/pull/18144))\n\n### Contributors\n\n- [@MatthewMckee4](https://github.com/MatthewMckee4)\n- [@AlexWaygood](https://github.com/AlexWaygood)\n\n## 0.0.1-alpha.4\n\n### Enhancements\n\n- Allow unions including `Any`/`Unknown` as bases ([#18094](https://github.com/astral-sh/ruff/pull/18094))\n- Better control flow for boolean expressions that are inside if ([#18010](https://github.com/astral-sh/ruff/pull/18010))\n- Improve invalid method calls for unmatched overloads ([#18122](https://github.com/astral-sh/ruff/pull/18122))\n- Add support for `NamedTuple` 'fallback' attributes ([#18127](https://github.com/astral-sh/ruff/pull/18127))\n- `type[…]` is always assignable to `type` ([#18121](https://github.com/astral-sh/ruff/pull/18121))\n- Support accessing `__builtins__` global ([#18118](https://github.com/astral-sh/ruff/pull/18118))\n\n### Bug fixes\n\n- Fix relative imports in stub packages ([#18132](https://github.com/astral-sh/ruff/pull/18132))\n\n### Contributors\n\n- [@MatthewMckee4](https://github.com/MatthewMckee4)\n- [@felixscherz](https://github.com/felixscherz)\n- [@BurntSushi](https://github.com/BurntSushi)\n- [@maxmynter](https://github.com/maxmynter)\n- [@sharkdp](https://github.com/sharkdp)\n- [@TomerBin](https://github.com/TomerBin)\n- [@MichaReiser](https://github.com/MichaReiser)\n\n## 0.0.1-alpha.3\n\n### Enhancements\n\n- Include synthesized arguments in displayed counts for `too-many-positional-arguments` ([#18098](https://github.com/astral-sh/ruff/pull/18098))\n\n### Bug fixes\n\n- Fix `redundant-cast` false positives when casting to `Unknown` ([#18111](https://github.com/astral-sh/ruff/pull/18111))\n- Fix normalization of unions containing instances parameterized with unions ([#18112](https://github.com/astral-sh/ruff/pull/18112))\n- Make dataclass instances adhere to DataclassInstance ([#18115](https://github.com/astral-sh/ruff/pull/18115))\n\n### CLI\n\n- Change layout of extra verbose output and respect `--color` for verbose output ([#18089](https://github.com/astral-sh/ruff/pull/18089))\n\n### Documentation\n\n- Use Cargo-style versions in the changelog ([#397](https://github.com/astral-sh/ty/pull/397))\n\n### Contributors\n\n- [@zanieb](https://github.com/zanieb)\n- [@sharkdp](https://github.com/sharkdp)\n- [@AlexWaygood](https://github.com/AlexWaygood)\n- [@InSyncWithFoo](https://github.com/InSyncWithFoo)\n- [@MichaReiser](https://github.com/MichaReiser)\n\n## 0.0.1-alpha.2\n\n### Enhancements\n\n- Improve diagnostics for failure to call overloaded function ([#18073](https://github.com/astral-sh/ruff/pull/18073))\n- Fix inconsistent casing in `invalid-return-type` diagnostic ([#18084](https://github.com/astral-sh/ruff/pull/18084))\n- Add type-expression syntax link to `invalid-type-expression` diagnostics ([#18104](https://github.com/astral-sh/ruff/pull/18104))\n\n### Bug fixes\n\n- Add cycle handling for unpacking targets ([#18078](https://github.com/astral-sh/ruff/pull/18078))\n- Do not look up `__init__` on instances ([#18092](https://github.com/astral-sh/ruff/pull/18092))\n\n### Typing\n\n- Infer parameter specializations of explicitly implemented generic protocols ([#18054](https://github.com/astral-sh/ruff/pull/18054))\n- Check assignments to implicit global symbols are assignable to the types declared on `types.ModuleType` ([#18077](https://github.com/astral-sh/ruff/pull/18077))\n- Fix various generics-related TODOs ([#18062](https://github.com/astral-sh/ruff/pull/18062))\n\n### Documentation\n\n- Fix rule link in the configuration description ([#381](https://github.com/astral-sh/ty/pull/381))\n- Use `https://ty.dev/rules` when linking to the rules table ([#18072](https://github.com/astral-sh/ruff/pull/18072))\n- Use `ty server` instead of `ty lsp` ([#360](https://github.com/astral-sh/ty/pull/360))\n- Fix missing `>` in HTML anchor tags in CLI reference ([#18096](https://github.com/astral-sh/ruff/pull/18096))\n- Fix link to rules docs ([#378](https://github.com/astral-sh/ty/pull/378))\n- Fix repository in README transform script ([#361](https://github.com/astral-sh/ty/pull/361))\n\n### Contributors\n\n- [@dhruvmanila](https://github.com/dhruvmanila)\n- [@Usul-Dev](https://github.com/Usul-Dev)\n- [@dcreager](https://github.com/dcreager)\n- [@AlexWaygood](https://github.com/AlexWaygood)\n- [@BurntSushi](https://github.com/BurntSushi)\n- [@MichaReiser](https://github.com/MichaReiser)\n- [@frgfm](https://github.com/frgfm)\n- [@kiran-4444](https://github.com/kiran-4444)\n- [@sharkdp](https://github.com/sharkdp)\n- [@eruditmorina](https://github.com/eruditmorina)\n\n## 0.0.1-alpha.1\n\n### Enhancements\n\n- Add basic support for non-virtual Python environments ([#17991](https://github.com/astral-sh/ruff/pull/17991))\n- Do not allow invalid virtual environments from discovered `.venv` or `VIRTUAL_ENV` ([#18003](https://github.com/astral-sh/ruff/pull/18003))\n- Refine message for why a rule is enabled ([#18038](https://github.com/astral-sh/ruff/pull/18038))\n- Update `--python` to accept paths to executables in environments ([#17954](https://github.com/astral-sh/ruff/pull/17954))\n- Improve diagnostics for `assert_type` and `assert_never` ([#18050](https://github.com/astral-sh/ruff/pull/18050))\n- Add a note to the diagnostic if a new builtin is used on an old Python version ([#18068](https://github.com/astral-sh/ruff/pull/18068))\n\n### Bug fixes\n\n- Fix infinite recursion bug in `is_disjoint_from` ([#18043](https://github.com/astral-sh/ruff/pull/18043))\n- Recognize submodules in self-referential imports ([#18005](https://github.com/astral-sh/ruff/pull/18005))\n\n### Typing\n\n- Allow a class to inherit from an intersection if the intersection contains a dynamic type and the intersection is not disjoint from `type` ([#18055](https://github.com/astral-sh/ruff/pull/18055))\n- Allow classes to inherit from `type[Any]` or `type[Unknown]` ([#18060](https://github.com/astral-sh/ruff/pull/18060))\n- Apply function specialization to all overloads ([#18020](https://github.com/astral-sh/ruff/pull/18020))\n- Implement `DataClassInstance` protocol for dataclasses ([#18018](https://github.com/astral-sh/ruff/pull/18018))\n- Induct into instances and subclasses when finding and applying generics ([#18052](https://github.com/astral-sh/ruff/pull/18052))\n- Infer parameter specializations of generic aliases ([#18021](https://github.com/astral-sh/ruff/pull/18021))\n- Narrowing for `hasattr()` ([#18053](https://github.com/astral-sh/ruff/pull/18053))\n- Silence false positives for PEP-695 ParamSpec annotations ([#18001](https://github.com/astral-sh/ruff/pull/18001))\n- Understand homogeneous tuple annotations ([#17998](https://github.com/astral-sh/ruff/pull/17998))\n- `__file__` is always a string inside a Python module ([#18071](https://github.com/astral-sh/ruff/pull/18071))\n\n### CLI\n\n- Avoid initializing progress bars early ([#18049](https://github.com/astral-sh/ruff/pull/18049))\n\n### Contributors\n\n- [@soof-golan](https://github.com/soof-golan)\n- [@ibraheemdev](https://github.com/ibraheemdev)\n- [@dhruvmanila](https://github.com/dhruvmanila)\n- [@charliermarsh](https://github.com/charliermarsh)\n- [@MichaReiser](https://github.com/MichaReiser)\n- [@carljm](https://github.com/carljm)\n- [@abhijeetbodas2001](https://github.com/abhijeetbodas2001)\n- [@zanieb](https://github.com/zanieb)\n- [@AlexWaygood](https://github.com/AlexWaygood)\n- [@dcreager](https://github.com/dcreager)\n- [@mtshiba](https://github.com/mtshiba)\n- [@sharkdp](https://github.com/sharkdp)\n\n## 0.0.0-alpha.8\n\n### Changes\n\n- Add `--config` CLI arg ([#17697](https://github.com/astral-sh/ruff/pull/17697))\n- Add CLI documentation and update README ([#284](https://github.com/astral-sh/ty/pull/284))\n- Add a warning about pre-release status to the CLI ([#17983](https://github.com/astral-sh/ruff/pull/17983))\n- Add missing bitwise-operator branches for boolean and integer arithmetic ([#17949](https://github.com/astral-sh/ruff/pull/17949))\n- Add progress bar for `ty check` ([#17965](https://github.com/astral-sh/ruff/pull/17965))\n- Add CLI reference ([#17978](https://github.com/astral-sh/ruff/pull/17978))\n- Change default severity for `unbound-reference` to `error` ([#17936](https://github.com/astral-sh/ruff/pull/17936))\n- Change range of `revealed-type` diagnostic to be the range of the argument passed in, not the whole call ([#17980](https://github.com/astral-sh/ruff/pull/17980))\n- Default to latest supported Python version ([#17938](https://github.com/astral-sh/ruff/pull/17938))\n- Display \"All checks passed!\" message in green ([#17982](https://github.com/astral-sh/ruff/pull/17982))\n- Document configuration schema ([#17950](https://github.com/astral-sh/ruff/pull/17950))\n- Generate and add rules table ([#17953](https://github.com/astral-sh/ruff/pull/17953))\n- Handle type variables that have other type variables as a default ([#17956](https://github.com/astral-sh/ruff/pull/17956))\n- Ignore `possibly-unresolved-reference` by default ([#17934](https://github.com/astral-sh/ruff/pull/17934))\n- Implement `global` handling and `load-before-global-declaration` syntax error ([#17637](https://github.com/astral-sh/ruff/pull/17637))\n- Make `unused-ignore-comment` disabled by default for now ([#17955](https://github.com/astral-sh/ruff/pull/17955))\n- Recognise functions containing `yield from` expressions as being generator functions ([#17930](https://github.com/astral-sh/ruff/pull/17930))\n- Fix stack overflow on recursive protocols ([#17929](https://github.com/astral-sh/ruff/pull/17929))\n- Report duplicate `Protocol` or `Generic` base classes with `[duplicate-base]`, not `[inconsistent-mro]` ([#17971](https://github.com/astral-sh/ruff/pull/17971))\n- Respect the gradual guarantee when reporting errors in resolving MROs ([#17962](https://github.com/astral-sh/ruff/pull/17962))\n- Support `typing.Self` in methods ([#17689](https://github.com/astral-sh/ruff/pull/17689))\n- Support extending `__all__` from an imported module even when the module is not an `ExprName` node ([#17947](https://github.com/astral-sh/ruff/pull/17947))\n- Support extending `__all__` with a literal tuple or set as well as a literal list ([#17948](https://github.com/astral-sh/ruff/pull/17948))\n- Understand classes that inherit from subscripted `Protocol[]` as generic ([#17832](https://github.com/astral-sh/ruff/pull/17832))\n- Update ty metadata ([#17943](https://github.com/astral-sh/ruff/pull/17943))\n- Add `py.typed` ([#276](https://github.com/astral-sh/ty/pull/276))\n- Bottom-up improvement of diagnostic messages for union type function calls ([#17984](https://github.com/astral-sh/ruff/pull/17984))\n- Fix more ecosystem/fuzzer panics with fixpoint ([#17758](https://github.com/astral-sh/ruff/pull/17758))\n- Remove `lint:` prefix from top-level diagnostic preamble ([#17987](https://github.com/astral-sh/ruff/pull/17987))\n\n### Contributors\n\n- [@Glyphack](https://github.com/Glyphack)\n- [@BurntSushi](https://github.com/BurntSushi)\n- [@paul-nameless](https://github.com/paul-nameless)\n- [@MichaReiser](https://github.com/MichaReiser)\n- [@ntbre](https://github.com/ntBre)\n- [@ibraheemdev](https://github.com/ibraheemdev)\n- [@sharkdp](https://github.com/sharkdp)\n- [@thejchap](https://github.com/thejchap)\n- [@carljm](https://github.com/carljm)\n- [@jorenham](https://github.com/jorenham)\n- [@AlexWaygood](https://github.com/AlexWaygood)\n- [@dcreager](https://github.com/dcreager)\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing\n\n> [!IMPORTANT]\n> If you want to contribute changes to ty's core, please check out the\n> [dedicated `ty` contributing guide](https://github.com/astral-sh/ruff/blob/main/crates/ty/CONTRIBUTING.md).\n> Keep reading if you want to contribute to ty's documentation or release process instead.\n\n## Repository structure\n\nThis repository contains ty's documentation and release infrastructure. The core of ty's Rust codebase is\nlocated in the [Ruff](https://github.com/astral-sh/ruff) repository. While the relationship between these\ntwo projects will evolve over time, they currently share foundational crates and it's easiest to use a single\nrepository for the Rust development.\n\nty's command-line help text, and part of `docs/reference/`, are auto-generated from Rust code in the Ruff\nrepository, using generation scripts that live in\n[`crates/ruff_dev/src/`](https://github.com/astral-sh/ruff/blob/main/crates/ruff_dev/src/):\n\n- [Configuration options](https://docs.astral.sh/ty/reference/configuration/), from\n    [ruff/crates/ty_project/src/metadata/options.rs](https://github.com/astral-sh/ruff/blob/main/crates/ty_project/src/metadata/options.rs)\n- [Rules](https://docs.astral.sh/ty/reference/rules/), from\n    [ruff/crates/ty_python_semantic/src/](https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/src/)\n- [Command-line interface reference](https://docs.astral.sh/ty/reference/cli/), from\n    [ruff/crates/ty/src/args.rs](https://github.com/astral-sh/ruff/blob/main/crates/ty/src/args.rs)\n\nThe Ruff repository is included as a submodule inside this repository to allow ty's release tags to reflect\nan exact snapshot of the Ruff project. The submodule is only updated on release. To see the latest development\ncode, check out the `main` branch of the Ruff repository.\n\n## Getting started with the ty repository\n\nClone the repository:\n\n```shell\ngit clone https://github.com/astral-sh/ty.git\n```\n\nThen, ensure the submodule is initialized:\n\n```shell\ngit submodule update --init --recursive\n```\n\n### Prerequisites\n\nYou'll need [uv](https://docs.astral.sh/uv/getting-started/installation/) (or `pipx` and `pip`) to\nrun Python utility commands.\n\nYou can optionally install prek hooks to automatically run the validation checks\nwhen making a commit:\n\n```shell\nuv tool install prek\nprek install\n```\n\n## Building the Python package\n\nThe Python package can be built with any Python build frontend (Maturin is used as a backend), e.g.:\n\n```shell\nuv build\n```\n\n## Updating the Ruff commit\n\nTo update the Ruff submodule to the latest commit:\n\n```shell\ngit -C ruff pull origin main\n```\n\nOr, to update the Ruff submodule to a specific commit:\n\n```shell\ngit -C ruff checkout <commit>\n```\n\nTo commit the changes:\n\n```shell\ncommit=$(git -C ruff rev-parse --short HEAD)\ngit switch -c \"sync/ruff-${commit}\"\ngit add ruff\ngit commit -m \"Update ruff submodule to https://github.com/astral-sh/ruff/commit/${commit}\"\n```\n\nTo restore the Ruff submodule to a clean-state, reset, then update the submodule:\n\n```shell\ngit -C ruff reset --hard\ngit submodule update\n```\n\nTo restore the Ruff submodule to the commit from `main`:\n\n```shell\ngit -C ruff reset --hard $(git ls-tree main -- ruff | awk '{print $3}')\ngit add ruff\n```\n\n## Documentation\n\nTo preview any changes to the documentation locally run the development server with:\n\n```shell\nuvx --with-requirements docs/requirements.txt -- mkdocs serve -f mkdocs.yml\n```\n\nThe documentation should then be available locally at\n[http://127.0.0.1:8000/ty/](http://127.0.0.1:8000/ty/).\n\nTo update the documentation dependencies, edit `docs/requirements.in`, then run:\n\n```shell\nuv pip compile docs/requirements.in -o docs/requirements.txt --universal -p 3.12\n```\n\nDocumentation is deployed automatically on release by publishing to the\n[Astral documentation](https://github.com/astral-sh/docs) repository, which itself deploys via\nCloudflare Pages.\n\nAfter making changes to the documentation, format the markdown files with:\n\n```shell\nnpx prettier --prose-wrap always --write \"**/*.md\"\n```\n\n## Releasing ty\n\nReleases can only be performed by Astral team members.\n\nPreparation for the release is automated.\n\n1. Install the prek hooks as described above, if you haven't already.\n\n1. Checkout the `main` branch and run `git pull origin main --recurse-submodules --tags`.\n\n1. Create and checkout a new branch for the release.\n\n1. Run `./scripts/release.sh`.\n\n    The release script will:\n\n    - Update the Ruff submodule to the latest commit on `main` upstream\n    - Generate changelog entries based on pull requests here, and in Ruff\n    - Bump the versions in the `pyproject.toml` and `dist-workspace.toml`\n    - Update the generated reference documentation in `docs/reference`\n\n1. Editorialize the `CHANGELOG.md` file to ensure entries are consistently styled.\n\n    This usually involves simple edits, like consistent capitalization and leading verbs like\n    \"Add ...\".\n\n1. Create a pull request with the changelog and version changes\n\n    The pull requests are usually titled as: `Bump version to <version>`.\n\n    Binary builds will automatically be tested for the release.\n\n1. Merge the pull request.\n\n1. Run the [release workflow](https://github.com/astral-sh/ty/actions/workflows/release.yml) with\n    the version tag.\n\n    **Do not include a leading `v`**.\n\n    When running the release workflow for pre-release versions, use the Cargo version format (not PEP\n    440), e.g. `0.0.1-alpha.5` (not `0.0.1a5`). For stable releases, these formats are identical.\n\n    The release will automatically be created on GitHub after the distributions are published.\n\n1. Run `uv run --no-project ./scripts/update_schemastore.py`\n\n    This script will prepare a branch to update the `ty.json` schema in the `schemastore`\n    repository.\n\n    Follow the link in the script's output to submit the pull request.\n\n    The script is a no-op if there are no schema changes.\n\n1. Update and release `ty-vscode`.\n\n    The instructions are [in the `ty-vscode`\n    repository](https://github.com/astral-sh/ty-vscode/blob/main/CONTRIBUTING.md#release).\n\n## Updating ty's conformance results upstream\n\nOne way in which type checkers can be evaluated is by how well they do on the [typing conformance test suite](https://github.com/python/typing/tree/main/conformance),\nwhich contains a number of assertions to test whether type checkers adhere to the rules laid out in\nthe typing spec. ty's results are uploaded to the upstream `python/typing` repo so that users can\ncompare ty's conformance score with other type checkers. Updating these results is partially, but\nnot fully, automated.\n\nTo update ty's conformance results upstream after a release:\n\n1. Clone <https://github.com/python/typing> and checkout a new branch\n1. Run `cd conformance`\n1. Run `uv sync --update-package=ty`\n1. Run `uv run python src/main.py`. This step may update generated fields in TOML files (see below) and/or the `results.html` file.\n1. Check to see if any manual changes are required and apply them as necessary (see below for details).\n1. If you had to make any manual changes as part of the previous step, run `uv run python src/main.py` again. This second run should not update any further TOML files, but is necessary for regenerating `results.html`.\n1. Make a PR to the upstream repo.\n\n### Manual changes that may be required to `.toml` files\n\nThe TOML files that contain the results for each type checker are partially generated.\n\nThe `conformance_automated`, `output` and `errors_diff` fields are all generated; these should never be altered:\n\n- `output` is the raw output of the type checker on that file.\n- `errors_diff` provides one line of output for every Python line where a diagnostic was expected from ty but didn't occur, and one line of output for every Python line where a diagnostic was not expected from ty but did occur.\n- `conformance_automated`: this will always either be \"Pass\" (if `errors_diff` is an empty string) or \"Fail\" (if it is a non-empty string).\n\nThe other fields are manually entered and may need to be updated if any of the generated fields in a TOML file are altered by running `uv run python src/main.py`:\n\n- `conformant`: This should be one of three values:\n    - \"Unsupported\": none of the major features in the Python file are supported by ty\n    - \"Partial\": some, but not all, of the features and assertions in the Python file are supported by ty. If this is given as the current status, a non-empty `notes` field should be provided that describes which features are currently supported and which are not.\n    - \"Pass\": this should generally only be used if ty passes all assertions in the Python file and the generated `errors_diff` field is an empty string. In some rare occasions, it *may* be appropriate to label ty as conformant even if there is a non-empty `errors_diff` field, but you will generally need to provide a non-empty `ignore_errors` field if so.\n- `notes`: if the score is given as \"Partial\" in the `conformant` field, this field should describe which assertions fail and which features are currently unsupported.\n- `ignore_errors`: this is only required if the generated `errors_diff` field is nonempty but the score is nonetheless given as \"Conformant\". It should be a list of strings. Each string should be an error message that appears in the `errors_diff` field but should nonetheless be ignored when considering whether ty is conformant or not. If ty's score is given as \"Conformant\" with a non-empty `errors_diff` field, a verification check in CI in the `python/typing` repository will fail unless each error message listed in `errors_diff` is listed in that TOML file's `ignore_errors` field.\n"
  },
  {
    "path": "Dockerfile",
    "content": "FROM --platform=$BUILDPLATFORM ubuntu AS build\nENV HOME=\"/root\"\nWORKDIR $HOME\n\nRUN apt update && apt install -y build-essential curl python3-venv\n\n# Setup zig as cross compiling linker\nRUN python3 -m venv $HOME/.venv\nRUN .venv/bin/pip install cargo-zigbuild\nENV PATH=\"$HOME/.venv/bin:$PATH\"\n\n# Change to the ruff directory, which is the root for our build\nWORKDIR $HOME/ruff\n\n# Install rust\nARG TARGETPLATFORM\nRUN case \"$TARGETPLATFORM\" in \\\n    \"linux/arm64\") echo \"aarch64-unknown-linux-musl\" > rust_target.txt ;; \\\n    \"linux/amd64\") echo \"x86_64-unknown-linux-musl\" > rust_target.txt ;; \\\n    *) exit 1 ;; \\\n    esac\n# Update rustup whenever we bump the rust version\nCOPY ruff/rust-toolchain.toml rust-toolchain.toml\nRUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --target $(cat rust_target.txt) --profile minimal --default-toolchain none\nENV PATH=\"$HOME/.cargo/bin:$PATH\"\n# Installs the correct toolchain version from rust-toolchain.toml and then the musl target\nRUN rustup target add $(cat rust_target.txt)\n\n# Build\nCOPY ruff/crates crates\nCOPY ruff/Cargo.toml Cargo.toml\nCOPY ruff/Cargo.lock Cargo.lock\nCOPY dist-workspace.toml ../dist-workspace.toml\nRUN cargo zigbuild --bin ty --target $(cat rust_target.txt) --release\nRUN cp target/$(cat rust_target.txt)/release/ty /ty\n# TODO: Optimize binary size, with a version that also works when cross compiling\n# RUN strip --strip-all /ty\n\nFROM scratch\nCOPY --from=build /ty /ty\nWORKDIR /io\nENTRYPOINT [\"/ty\"]\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2025 Astral Software Inc.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# ty\n\n[![ty](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ty/main/assets/badge/v0.json)](https://github.com/astral-sh/ty)\n[![PyPI](https://img.shields.io/pypi/v/ty.svg)](https://pypi.python.org/pypi/ty)\n[![Discord](https://img.shields.io/badge/Discord-%235865F2.svg?logo=discord&logoColor=white)](https://discord.com/invite/astral-sh)\n\nAn extremely fast Python type checker and language server, written in Rust.\n\n<br />\n\n<p align=\"center\">\n  <img alt=\"Shows a bar chart with benchmark results.\" width=\"500px\" src=\"https://raw.githubusercontent.com/astral-sh/ty/main/docs/assets/ty-benchmark-cli.svg\">\n</p>\n\n<p align=\"center\">\n  <i>Type checking the <a href=\"https://github.com/home-assistant/core\">home-assistant</a> project without caching.</i>\n</p>\n\n<br />\n\nty is backed by [Astral](https://astral.sh), the creators of\n[uv](https://github.com/astral-sh/uv) and [Ruff](https://github.com/astral-sh/ruff).\n\nty is currently in [beta](#version-policy).\n\n## Highlights\n\n- 10x - 100x faster than mypy and Pyright\n- Comprehensive [diagnostics](https://docs.astral.sh/ty/features/diagnostics/) with rich contextual information\n- 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\n- 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)\n- [Language server](https://docs.astral.sh/ty/features/language-server/) with code navigation, completions, code actions, auto-import, inlay hints, on-hover help, etc.\n- 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\n- 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\n- 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\n    [sophisticated reachability analysis](https://docs.astral.sh/ty/features/type-system/#reachability-based-on-types)\n\n## Getting started\n\nRun ty with [uvx](https://docs.astral.sh/uv/guides/tools/#running-tools) to get started quickly:\n\n```shell\nuvx ty check\n```\n\nOr, check out the [ty playground](https://play.ty.dev) to try it out in your browser.\n\nTo learn more about using ty, see the [documentation](https://docs.astral.sh/ty/).\n\n## Installation\n\nTo install ty, see the [installation](https://docs.astral.sh/ty/installation/) documentation.\n\nTo add the ty language server to your editor, see the [editor integration](https://docs.astral.sh/ty/editors/) guide.\n\n## Getting help\n\nIf you have questions or want to report a bug, please open an\n[issue](https://github.com/astral-sh/ty/issues) in this repository.\n\nYou may also join our [Discord server](https://discord.com/invite/astral-sh).\n\n## Contributing\n\nDevelopment of this project takes place in the [Ruff](https://github.com/astral-sh/ruff) repository\nat this time. Please [open pull requests](https://github.com/astral-sh/ruff/pulls) there for changes\nto anything in the `ruff` submodule (which includes all of the Rust source code).\n\nSee the\n[contributing guide](./CONTRIBUTING.md) for more details.\n\n## Version policy\n\nty uses `0.0.x` versioning. ty does not yet have a stable API; breaking changes, including changes\nto diagnostics, may occur between any two versions. See the [type system support](https://github.com/astral-sh/ty/issues/1889)\ntracking issue for a detailed overview of currently supported features.\n\n## FAQ\n\n<!-- We intentionally use smaller headings for the FAQ items -->\n\n<!-- markdownlint-disable MD001 -->\n\n#### Why is ty doing \\_\\_\\_\\_\\_?\n\nSee our [typing FAQ](https://docs.astral.sh/ty/reference/typing-faq).\n\n#### How do you pronounce ty?\n\nIt's pronounced as \"tee - why\" ([`/tiː waɪ/`](https://en.wikipedia.org/wiki/Help:IPA/English#Key))\n\n#### How should I stylize ty?\n\nJust \"ty\", please.\n\n<!-- markdownlint-enable MD001 -->\n\n## License\n\nty is licensed under the MIT license ([LICENSE](LICENSE) or\n<https://opensource.org/licenses/MIT>).\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in ty\nby you, as defined in the MIT license, shall be licensed as above, without any additional terms or\nconditions.\n\n<div align=\"center\">\n  <a target=\"_blank\" href=\"https://astral.sh\" style=\"background:none\">\n    <img src=\"https://raw.githubusercontent.com/astral-sh/uv/main/assets/svg/Astral.svg\" alt=\"Made by Astral\">\n  </a>\n</div>\n"
  },
  {
    "path": "SECURITY.md",
    "content": "# Security policy\n\n## Reporting a vulnerability\n\nIf you have found a possible vulnerability, please email `security at astral dot sh`.\n\n## Bug bounties\n\nWhile we sincerely appreciate and encourage reports of suspected security problems, please note that\nAstral does not currently run any bug bounty programs.\n\n## Vulnerability disclosures\n\nCritical vulnerabilities will be disclosed via GitHub's\n[security advisory](https://github.com/astral-sh/ty/security) system.\n"
  },
  {
    "path": "_typos.toml",
    "content": "[files]\nextend-exclude = []\n\n[default.extend-words]\n\n[default]\nextend-ignore-re = [\n    # Line ignore with trailing \"spellchecker:disable-line\"\n    \"(?Rm)^.*#\\\\s*spellchecker:disable-line$\",\n    \"LICENSEs\",\n    \"ntBre\"\n]\n"
  },
  {
    "path": "assets/badge/v0.json",
    "content": "{\n  \"label\": \"\",\n  \"message\": \"ty\",\n  \"logoSvg\": \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"48\\\" height=\\\"48\\\"><path d=\\\"M48 7.7H27.8V0h-24v7.7H0v18.2h3.8v14.3c0 4.3 3.5 7.8 7.8 7.8H48V29.8H27.8v-3.9h12.4c4.3 0 7.8-3.5 7.8-7.8V7.7Z\\\" fill=\\\"#46ebe1\\\"/></svg>\",\n  \"logoWidth\": 10,\n  \"labelColor\": \"grey\",\n  \"color\": \"#261230\"\n}\n"
  },
  {
    "path": "dist-workspace.toml",
    "content": "[workspace]\nmembers = [\"cargo:./ruff\"]\npackages = [\"ty\"]\nversion = \"0.0.24\"\n\n# Config for 'dist'\n[dist]\n# The preferred dist version to use in CI (Cargo.toml SemVer syntax)\ncargo-dist-version = \"0.31.0\"\n# Whether to consider the binaries in a package for distribution (defaults true)\ndist = false\n# CI backends to support\nci = \"github\"\n# The installers to generate for each app\ninstallers = [\"shell\", \"powershell\"]\n# The archive format to use for windows builds (defaults .zip)\nwindows-archive = \".zip\"\n# The archive format to use for non-windows builds (defaults .tar.xz)\nunix-archive = \".tar.gz\"\n# Target platforms to build apps for (Rust target-triple syntax)\ntargets = [\n    \"aarch64-apple-darwin\",\n    \"aarch64-unknown-linux-gnu\",\n    \"aarch64-unknown-linux-musl\",\n    \"aarch64-pc-windows-msvc\",\n    \"arm-unknown-linux-musleabihf\",\n    \"armv7-unknown-linux-gnueabihf\",\n    \"armv7-unknown-linux-musleabihf\",\n    \"x86_64-apple-darwin\",\n    \"powerpc64-unknown-linux-gnu\",\n    \"powerpc64le-unknown-linux-gnu\",\n    \"s390x-unknown-linux-gnu\",\n    \"x86_64-unknown-linux-gnu\",\n    \"x86_64-unknown-linux-musl\",\n    \"x86_64-pc-windows-msvc\",\n    \"i686-unknown-linux-gnu\",\n    \"i686-unknown-linux-musl\",\n    \"i686-pc-windows-msvc\",\n]\n# Whether to auto-include files like READMEs, LICENSEs, and CHANGELOGs (default true)\nauto-includes = false\n# Whether dist should create a Github Release or use an existing draft\ncreate-release = true\n# Which actions to run on pull requests\npr-run-mode = \"plan\"\n# Whether to publish prereleases to package managers\npublish-prereleases = true\n# Whether CI should trigger releases with dispatches instead of tag pushes\ndispatch-releases = true\n# Which phase dist should use to create the GitHub release\ngithub-release = \"announce\"\n# Whether to enable GitHub Attestations\ngithub-attestations = true\n# When to generate GitHub Attestations\ngithub-attestations-phase = \"announce\"\n# Patterns to attest when creating attestations for release artifacts\ngithub-attestations-filters = [\"*.json\", \"*.sh\", \"*.ps1\", \"*.zip\", \"*.tar.gz\"]\n# Whether CI should include auto-generated code to build local artifacts\nbuild-local-artifacts = false\n# Local artifacts jobs to run in CI\nlocal-artifacts-jobs = [\"./build-binaries\", \"./build-docker\"]\n# Publish jobs to run in CI\npublish-jobs = [\"./publish-pypi\"]\n# Post-announce jobs to run in CI\npost-announce-jobs = [\"./publish-docs\", \"./publish-mirror\"]\n# Custom permissions for GitHub Jobs\ngithub-custom-job-permissions = { \"build-docker\" = { packages = \"write\", contents = \"read\", id-token = \"write\", attestations = \"write\" }, \"publish-mirror\" = { contents = \"read\" } }\n# Whether to install an updater program\ninstall-updater = false\n# Path that installers should place binaries in\ninstall-path = [\"$XDG_BIN_HOME/\", \"$XDG_DATA_HOME/../bin\", \"~/.local/bin\"]\n# Whether source tarballs should include submodules\nrecursive-tarball = true\n# Prefer simple hosting for downloads, falling back to GitHub releases\nhosting = [\"simple\", \"github\"]\nsimple-download-url = \"https://releases.astral.sh/github/ty/releases/download/{tag}\"\n\n[dist.github-custom-runners]\nglobal = \"depot-ubuntu-latest-4\"\n\n[dist.github-action-commits]\n\"actions/checkout\" = \"0c366fd6a839edf440554fa01a7085ccba70ac98\"                # v6.0.2\n\"actions/upload-artifact\" = \"bbbca2ddaa5d8feaa63e36b76fdaad77386f024f\"         # v7.0.0\n\"actions/download-artifact\" = \"70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3\"       # v8.0.0\n\"actions/attest-build-provenance\" = \"00014ed6ed5efc5b1ab7f7f34a39eb55d41aa4f8\" # v3.1.0\n"
  },
  {
    "path": "docs/.overrides/main.html",
    "content": "{% extends \"base.html\" %}\n\n{% block htmltitle %}\n{% if page.meta and page.meta.title %}\n<title>{{ page.meta.title }} | {{ config.site_name }}</title>\n{% elif page.title and not page.is_homepage %}\n<title>{{ page.title | striptags }} | {{ config.site_name }}</title>\n{% else %}\n<title>{{ config.site_name }}</title>\n{% endif %}\n{% endblock %}\n\n{% block extrahead %}\n<link rel=\"apple-touch-icon\" sizes=\"180x180\" href=\"https://docs.astral.sh/static/apple-touch-icon.png\"/>\n<link rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"https://docs.astral.sh/static/favicon-32x32.png\"/>\n<link rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"https://docs.astral.sh/static/favicon-16x16.png\"/>\n<link rel=\"manifest\" href=\"https://docs.astral.sh/static/site.webmanifest\"/>\n<link rel=\"mask-icon\" href=\"https://docs.astral.sh/static/safari-pinned-tab.svg\" color=\"#2e183d\"/>\n<meta name=\"msapplication-TileColor\" content=\"#d7ff64\"/>\n<meta name=\"theme-color\" content=\"#ffffff\"/>\n<meta name=\"robots\" content=\"index,follow\"/>\n<script type=\"application/ld+json\">\n    {\n        {% if page and page.meta.git_revision_date_localized_raw_iso_datetime %}\n        \"datePublished\": \"{{ page.meta.git_revision_date_localized_raw_iso_datetime }}Z\",\n        \"dateModified\": \"{{ page.meta.git_revision_date_localized_raw_iso_datetime  }}Z\",\n        {% endif %}\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"WebSite\",\n        \"name\": \"Astral Docs\",\n        \"url\": \"https://docs.astral.sh\"\n    }\n</script>\n{% endblock %}\n"
  },
  {
    "path": "docs/.overrides/partials/integrations/analytics/fathom.html",
    "content": "<script src=\"https://cdn.usefathom.com/script.js\" data-site=\"ASBGCSTT\" defer></script>\n"
  },
  {
    "path": "docs/configuration.md",
    "content": "# Configuration\n\n## Configuration files\n\nty supports persistent configuration files at both the project- and user-level.\n\nSpecifically, ty will search for a `pyproject.toml` or `ty.toml` file in the current directory, or in the nearest parent directory.\n\nIf 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`:\n\n```toml title=\"pyproject.toml\"\n[tool.ty.rules]\nindex-out-of-bounds = \"ignore\"\n```\n\n!!! note\n\n    If there is no `tool.ty` table, the `pyproject.toml` file will be ignored, and ty will continue\n    searching in the directory hierarchy.\n\nty will also search for `ty.toml` files, which follow an identical structure, but omit the `[tool.ty]` prefix. For example:\n\n```toml title=\"ty.toml\"\n[rules]\nindex-out-of-bounds = \"ignore\"\n```\n\n!!! important\n\n    `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.\n\nty 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.\n\nIf project- and user-level configuration files are found, the settings will be merged, with project-level configuration taking precedence over the user-level configuration.\n\nFor 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.\n\nSettings provided via command line take precedence over persistent configuration.\n\nSee the [configuration](./reference/configuration.md) reference for an enumeration of the available settings.\n"
  },
  {
    "path": "docs/editors.md",
    "content": "# Editor integration\n\nty can be integrated with various editors to provide a seamless development experience.\n\nLearn more about ty's editor features in the [language server](./features/language-server.md)\ndocumentation.\n\n## VS Code\n\nThe Astral team maintains an official VS Code extension.\n\nInstall the [ty extension](https://marketplace.visualstudio.com/items?itemName=astral-sh.ty) from the VS Code Marketplace.\n\nThe extension automatically disables the language server from the [Python\nextension](https://marketplace.visualstudio.com/items?itemName=ms-python.python)\nto avoid running two Python language servers. This is done by setting\n[`python.languageServer`](https://code.visualstudio.com/docs/python/settings-reference#_intellisense-engine-settings)\nto `\"None\"` as a default configuration.\n\nIf you prefer to use ty only for type checking and want to use another language\nserver for capabilities like hover, auto-completions, etc., you can override\nthis by explicitly setting [`python.languageServer`](https://code.visualstudio.com/docs/python/settings-reference#_intellisense-engine-settings) and\n[`ty.disableLanguageServices`](./reference/editor-settings.md#disablelanguageservices)\nin your [`settings.json`](https://code.visualstudio.com/docs/configure/settings#_settings-json-file):\n\n```jsonc\n{\n  \"python.languageServer\": \"Pylance\",\n  \"ty.disableLanguageServices\": true,\n}\n```\n\n## Neovim\n\nThe [nvim-lspconfig](https://github.com/neovim/nvim-lspconfig) extension is the\nrecommended way of using ty with Neovim (if you prefer not to install the extension,\nyou can copy [the ty configuration](https://github.com/neovim/nvim-lspconfig/blob/master/lsp/ty.lua)\nmanually instead). After installing the nvim-lspconfig extension, you need to enable\nthe language server (and can optionally configure additional settings). For Neovim >=0.11,\nyou can add the following snippet to your config file:\n\n```lua\n-- Optional: Only required if you need to update the language server settings\nvim.lsp.config('ty', {\n  settings = {\n    ty = {\n      -- ty language server settings go here\n    }\n  }\n})\n\n-- Required: Enable the language server\nvim.lsp.enable('ty')\n```\n\nFor Neovim \\<0.11, you would use the configuration below instead (note that [you might need\nto install an older version of nvim-lspconfig](https://github.com/neovim/nvim-lspconfig?tab=readme-ov-file#important-%EF%B8%8F)):\n\n```lua\nrequire('lspconfig').ty.setup({\n  settings = {\n    ty = {\n      -- ty language server settings go here\n    }\n  }\n})\n```\n\n## Zed\n\nty is included with Zed out of the box (no extension required), although the default primary LSP for Python is basedpyright.\n\nYou can enable ty and disable basedpyright by adding this to your `settings.json` file:\n\n```json\n{\n  \"languages\": {\n    \"Python\": {\n      \"language_servers\": [\n        // Enable ty and ruff,\n        // Other built-in servers (basedpyright, pyright, pylsp)\n        // are disabled by being omitted from this list.\n        \"ty\",\n        \"ruff\"\n      ]\n    }\n  }\n}\n```\n\nYou can override the `ty` executable Zed uses by setting `lsp.ty.binary`:\n\n```json\n{\n  \"lsp\": {\n    \"ty\": {\n      \"binary\": {\n        \"path\": \"/home/user/.local/bin/ty\",\n        \"arguments\": [\"server\"]\n      }\n    }\n  }\n}\n```\n\nMore information in [Zed's documentation](https://zed.dev/docs/languages/python#configure-python-language-servers-in-zed).\n\n## PyCharm\n\nStarting with version 2025.3, PyCharm users can enable native ty support in the settings:\n\n1. Go to **Python | Tools | ty** in the Settings dialog.\n\n1. Select the **Enable** checkbox.\n\n1. In the Execution mode setting, select how PyCharm should search for the executable:\n\n    **Interpreter** mode: PyCharm searches for an executable installed in your interpreter. To install the ty package for the selected interpreter, click _Install ty_.\n\n    **Path** mode: PyCharm searches for an executable in `$PATH`. If the executable is not found, you can specify the path by clicking the Browse... icon.\n\n1. Select which options should be enabled.\n\nFor more information, refer to [PyCharm documentation](https://www.jetbrains.com/help/pycharm/lsp-tools.html#ty).\n\n## Other editors\n\nty can be used with any editor that supports the [language server\nprotocol](https://microsoft.github.io/language-server-protocol/).\n\nTo start the language server, use the `server` subcommand:\n\n```shell\nty server\n```\n\nRefer to your editor's documentation to learn how to connect to an LSP server.\n\n## Settings\n\nSee the [editor settings reference](./reference/editor-settings.md) for more details on configuring the language\nserver.\n"
  },
  {
    "path": "docs/exclusions.md",
    "content": "# Excluding files\n\nty automatically discovers all Python files in your project. You can customize where ty searches by using the [`src.include`](./reference/configuration.md#include) and [`src.exclude`](./reference/configuration.md#exclude) settings.\n\nFor example, with the following configuration, ty checks all Python files in the `src` and `tests` directories except those in the `src/generated` directory:\n\n```toml title=\"pyproject.toml\"\n[tool.ty.src]\ninclude = [\"src\", \"tests\"]\nexclude = [\"src/generated\"]\n```\n\n## Default exclusions\n\nBy 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 `!`:\n\n```toml title=\"pyproject.toml\"\n[tool.ty.src]\n# Remove `build` from the excluded directories.\nexclude = [\"!**/build/\"]\n```\n\nBy 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`.\n\n## Explicit targets\n\nYou may explicitly pass the paths that ty should check, e.g.:\n\n```shell\nty check src scripts/benchmark.py\n```\n\nPaths that are passed as positional arguments to `ty check` are included even if they would otherwise be ignored through `exclude` filters or an ignore-file.\n\n## Include and exclude syntax\n\nBoth `include` and `exclude` support gitignore like glob patterns:\n\n- `src/` matches a directory (including its contents) named `src`.\n- `src` matches a file or directory (including its contents) named `src`.\n- `*` matches any (possibly empty) sequence of characters (except `/`).\n- `**` matches zero or more path components.\n    This sequence **must** form a single path component, so both `./**a` and `./b**/` are invalid and will result in an error.\n    A sequence of more than two consecutive `*` characters is also invalid.\n- `?` matches any single character except `/`\n- `[abc]` matches any character inside the brackets. Character sequences can also specify ranges of characters, as ordered by Unicode,\n    so e.g. `[0-9]` specifies any character between `0` and `9` inclusive. An unclosed bracket is invalid.\n\nAll 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`.\n\n!!! warning\n\n    A prefix include pattern like `**/src` can notably slow down the Python file discovery.\n\nAll 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.\n\n## Excluding files from virtual environments\n\nIn Python 3.13+, the `venv` module will add a `.gitignore` file to the virtual environment root and\nty will not emit diagnostics for the contained files. However, when using an older version of\nPython, ty may include diagnostics for files in the virtual environment.\n\nYou can resolve this by adding a `.gitignore` to the environment, e.g., for a virtual environment\nnamed `.venv`:\n\n```shell\necho \"*\" > .venv/.gitignore\n```\n\nOr by adding your virtual environment to your `.gitignore` or `.ignore` file.\n"
  },
  {
    "path": "docs/features/diagnostics.md",
    "content": "# Diagnostics\n\nty provides diagnostics that include snippets of your source code, annotations and helpful\nexplanations. It will sometimes also provide suggestions on how to fix the reported issues.\n\n## Example: Typed dictionaries\n\nIn this first example, ty detected an invalid assignment to a `TypedDict` key. Notice how the\ndiagnostic includes both the context around the line with the error, as well as the reference to the\n`age` item in the `TypedDict` definition:\n\n![TypedDict invalid-assignment diagnostic](screenshots/diagnostics1.dark.png#only-dark)\n![TypedDict invalid-assignment diagnostic](screenshots/diagnostics1.light.png#only-light)\n\nWhen a `TypedDict` key is misspelled, ty will suggest the correct spelling. If you are using an\neditor with language server support, you can also apply this suggestion as a quick fix:\n\n![TypedDict misspelled-key diagnostic](screenshots/diagnostics2.dark.png#only-dark)\n![TypedDict misspelled-key diagnostic](screenshots/diagnostics2.light.png#only-light)\n\n## Example: Invalid arguments\n\nHere, a file has been opened for writing in text mode, but we are trying to write bytes to it.\nThe diagnostic points out the type mismatch and also includes the corresponding parameter in the\nfunction definition for `write`:\n\n![Invalid arguments diagnostic](screenshots/diagnostics3.dark.png#only-dark)\n![Invalid arguments diagnostic](screenshots/diagnostics3.light.png#only-light)\n\n## Example: Backwards compatibility\n\nInstead of just telling you that `tomllib` can not be found, ty will tell you *why* it is not\navailable for your project. In this case, your project is targeting Python 3.10, but `tomllib` was\nonly added in Python 3.11:\n\n![Missing import diagnostic](screenshots/diagnostics4.dark.png#only-dark)\n![Missing import diagnostic](screenshots/diagnostics4.light.png#only-light)\n"
  },
  {
    "path": "docs/features/language-server.md",
    "content": "<!-- Note for maintainers: the screenshots referenced in this document were taken using\n     the \"Atom One Light\" theme in VS Code. -->\n\n# Language server\n\nYou can generally expect ty to be a fully-featured [language server] for Python.\nThis page describes some of the key features provided by ty's IDE integration and includes\na reference table of supported LSP features at the end.\nSee the [editor integration](../editors.md) guide for instructions on how to set up ty\nwith your editor.\n\n## Diagnostics\n\n<figure markdown=\"span\">\n  ![](screenshots/inline-diagnostics.png)\n  <figcaption>Example of an inline diagnostic with code-span annotations</figcaption>\n</figure>\n\nty reports type errors and other [diagnostics](./diagnostics.md) directly in your editor. Diagnostics\nare updated as you type. You can use the\n[`diagnosticMode`](../reference/editor-settings.md#diagnosticmode) setting to control if you want to\nsee diagnostics for open files only, or for your entire workspace.\n\n!!! info\n\n    ty supports both the \"pull\" and \"push\" diagnostic models. Most modern editors will use the \"pull\" model\n    for better performance, where diagnostics are fetched on demand rather than pushed after every\n    change.\n\n## Code navigation\n\n<figure markdown=\"span\">\n  ![](screenshots/find-references.png)\n  <figcaption>\"Find references\" shows usages across the entire workspace</figcaption>\n</figure>\n\nty powers several language server features that allow you to navigate a Python codebase:\n\n- **Go to Definition**: Jump to where a symbol is defined. ty resolves imports, function calls,\n    class references, and more.\n- **Go to Declaration**: Navigate to the declaration site of a symbol, which can differ from its\n    definition (could be in a stub file).\n- **Go to Type Definition**: Navigate to the type of a symbol. For example, this takes you to the class `Person`\n    when invoked on a variable `user: Person`.\n- **Find all references**: Find every usage of a function, class, or variable across your entire workspace.\n- **Document and workspace symbols**: See an outline of symbols in the current file, or search through symbols across your entire workspace.\n\n## Code completions\n\n<figure markdown=\"span\">\n  ![Code completion example](screenshots/code-completion.png){ width=\"500\" }\n  <figcaption>Accepting this completion will automatically add a <code>subprocess</code> import at the top of the file.</figcaption>\n</figure>\n\nty provides intelligent code completions as you type, offering suggestions for variables, functions, classes, and modules that are in scope.\nFor symbols that are not yet imported, ty suggests auto-import actions to add the necessary `import` statements.\n\n## Code actions and refactorings\n\n<figure markdown=\"span\">\n  ![Code action example](screenshots/quick-fix.png){ width=\"700\" }\n  <figcaption>ty offers to remove the unused suppression comment</figcaption>\n</figure>\n\nty offers quick fixes and other code actions to help you resolve issues:\n\n- **Add import**: Automatically add missing import statements\n- **Quick fixes**: Some diagnostics come with quick fix suggestions to resolve the issue\n- **Rename symbol**: Safely rename symbols across your entire codebase\n- **Selection range**: Expand or shrink the text selection in your editor based on ty's understanding of Python syntax\n\n## Contextual information\n\n<figure markdown=\"span\">\n  ![Inlay hints](screenshots/inlay-hints.png)\n  <figcaption>Gray inlay hints and on-hover information (signature, docstring)</figcaption>\n</figure>\n\nty surfaces useful contextual information as you code:\n\n- **Hover**: Hover over any symbol to see its type, documentation, function signatures, and other\n    useful information like the variance of type parameters.\n- **Inlay hints**: Display inline type hints for variables and parameters without explicit\n    annotations, as well as parameter names at call sites. These hints can also be double-clicked\n    to insert the type annotations into your source code. You can also click on parts of the inlay\n    hints for go-to-definition navigation.\n- **Signature help**: When calling a function, ty displays the function's parameters and their\n    types. This appears automatically when you type `(` and updates as you navigate between arguments.\n- **Document highlight**: When the cursor is on a symbol, ty highlights all occurrences of that\n    symbol in the current file.\n- **Semantic highlighting**: Syntax highlighting based on the underlying semantics and types.\n\n## Code folding\n\nty provides Python specific code folding ranges to LSP clients upon request. This includes tagging\ndocstrings as comments, which supports editor actions like \"fold all comment blocks.\"\n\n## Notebook support\n\nty supports Jupyter notebooks (`.ipynb` files) with language server features. Each cell is\nanalyzed in context, with diagnostics, completions, and other features working across cells.\n\n## Fine-grained incrementality\n\nty's architecture is designed for low-latency updates of diagnostics and other language server features.\nWhen you make a change in your editor, ty incrementally updates only the affected parts of the\ncodebase, rather than re-analyzing everything from scratch. This happens at a fine-grained level,\ndown to individual definitions. This incrementality means that you get instant feedback as you type, i.e.,\nwithin a few milliseconds, even on large projects.\n\n!!! info\n\n    Fine-grained dependencies also allow ty to skip large parts of 3rd-party dependencies when they are not relevant\n    to your codebase.\n\n## Feature reference\n\n<!-- markdownlint-disable MD060 -->\n\n| Feature                                               | Status           | Notes                                                         |\n| ----------------------------------------------------- | ---------------- | ------------------------------------------------------------- |\n| [`callHierarchy/*`][callhierarchy]                    | ❌ Not supported | [#1976]                                                       |\n| [`notebookDocument/*`][notebookdocument]              | ✅ Supported     |                                                               |\n| [`textDocument/codeAction`][codeaction]               | ✅ Supported     | Quick fixes                                                   |\n| [`textDocument/codeLens`][codelens]                   | ❌ Not supported |                                                               |\n| [`textDocument/completion`][completion]               | ✅ Supported     |                                                               |\n| [`textDocument/declaration`][declaration]             | ✅ Supported     |                                                               |\n| [`textDocument/definition`][definition]               | ✅ Supported     |                                                               |\n| [`textDocument/diagnostic`][diagnostic]               | ✅ Supported     |                                                               |\n| [`textDocument/documentColor`][documentcolor]         | ❌ Not supported |                                                               |\n| [`textDocument/documentHighlight`][documenthighlight] | ✅ Supported     |                                                               |\n| [`textDocument/documentLink`][documentlink]           | ❌ Not supported |                                                               |\n| [`textDocument/documentSymbol`][documentsymbol]       | ✅ Supported     |                                                               |\n| [`textDocument/foldingRange`][foldingrange]           | ✅ Supported     |                                                               |\n| [`textDocument/formatting`][formatting]               | —                | Use [Ruff] for formatting                                     |\n| [`textDocument/hover`][hover]                         | ✅ Supported     |                                                               |\n| [`textDocument/implementation`][implementation]       | ❌ Not supported |                                                               |\n| [`textDocument/inlayHint`][inlayhint]                 | ✅ Supported     |                                                               |\n| [`textDocument/onTypeFormatting`][ontypeformatting]   | —                | [Ruff #16829](https://github.com/astral-sh/ruff/issues/16829) |\n| [`textDocument/prepareRename`][preparerename]         | ✅ Supported     |                                                               |\n| [`textDocument/rangeFormatting`][rangeformatting]     | —                | Use [Ruff] for formatting                                     |\n| [`textDocument/references`][references]               | ✅ Supported     |                                                               |\n| [`textDocument/rename`][rename]                       | ✅ Supported     |                                                               |\n| [`textDocument/selectionRange`][selectionrange]       | ✅ Supported     |                                                               |\n| [`textDocument/semanticTokens`][semantictokens]       | ✅ Supported     |                                                               |\n| [`textDocument/signatureHelp`][signaturehelp]         | ✅ Supported     |                                                               |\n| [`textDocument/typeDefinition`][typedefinition]       | ✅ Supported     |                                                               |\n| [`typeHierarchy/*`][typehierarchy]                    | ❌ Not supported | [#534]                                                        |\n| [`workspace/diagnostic`][workspacediagnostic]         | ✅ Supported     |                                                               |\n| [`workspace/symbol`][workspacesymbol]                 | ✅ Supported     |                                                               |\n| [`workspace/willRenameFiles`][willrenamefiles]        | ❌ Not supported | [#1560]                                                       |\n\n[#1560]: https://github.com/astral-sh/ty/issues/1560\n[#1976]: https://github.com/astral-sh/ty/issues/1976\n[#534]: https://github.com/astral-sh/ty/issues/534\n[callhierarchy]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#callHierarchy_incomingCalls\n[codeaction]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_codeAction\n[codelens]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_codeLens\n[completion]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_completion\n[declaration]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_declaration\n[definition]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_definition\n[diagnostic]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_diagnostic\n[documentcolor]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_documentColor\n[documenthighlight]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_documentHighlight\n[documentlink]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_documentLink\n[documentsymbol]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_documentSymbol\n[foldingrange]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_foldingRange\n[formatting]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_formatting\n[hover]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_hover\n[implementation]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_implementation\n[inlayhint]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_inlayHint\n[language server]: https://microsoft.github.io/language-server-protocol/\n[notebookdocument]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#notebookDocument_synchronization\n[ontypeformatting]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_onTypeFormatting\n[preparerename]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_prepareRename\n[rangeformatting]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_rangeFormatting\n[references]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_references\n[rename]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_rename\n[ruff]: https://docs.astral.sh/ruff/\n[selectionrange]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_selectionRange\n[semantictokens]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_semanticTokens\n[signaturehelp]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_signatureHelp\n[typedefinition]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_typeDefinition\n[typehierarchy]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#typeHierarchy_supertypes\n[willrenamefiles]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#workspace_willRenameFiles\n[workspacediagnostic]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#workspace_diagnostic\n[workspacesymbol]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#workspace_symbol\n"
  },
  {
    "path": "docs/features/type-system.md",
    "content": "# Type system\n\nYou can generally expect ty to support all typing features that are described and specified in the\n[Python typing documentation] (for a detailed overview, please refer to the\n[type system features tracking issue](https://github.com/astral-sh/ty/issues/1889)). This page\nhighlights some of the unique features that ty's type system provides.\n\n## Redeclarations\n\nty allows you to reuse the same symbol with a different type. The following example shows how the\n`paths` parameter is redeclared as a list of strings:\n\n```py\ndef split_paths(paths: str) -> list[Path]:\n    paths: list[str] = paths.split(\":\")\n    return [Path(p) for p in paths]\n```\n\n(Full example in the [playground](https://play.ty.dev/80a74c95-a43e-4a3d-8c26-f88e879d7dcb))\n\n## Intersection types\n\nty has first-class support for intersection types. In contrast to a union type `A | B`, which means\n\"*either* A *or* B\", an intersection type `A & B` means \"*both* A *and* B\". Type narrowing in ty is\nbased on intersections. For example, notice how we can call `obj.serialize_json()` *and* access the\n`.version` property in the following function:\n\n```py\ndef output_as_json(obj: Serializable) -> str:\n    if isinstance(obj, Versioned):\n        reveal_type(obj)  # reveals: Serializable & Versioned\n\n        return str({\n            \"data\": obj.serialize_json(),\n            \"version\": obj.version\n        })\n    else:\n        return obj.serialize_json()\n```\n\n(Full example in the [playground](https://play.ty.dev/39241435-5e78-4ce9-817f-ce65be73a6ed))\n\nIntersections can also be built using gradual types like `Any` or its implicit counterpart\n`Unknown`. For example, imagine you call into untyped (third party) code that returns an object of\ntype `Unknown`. Narrowing the type of that object using `isinstance` will result in an intersection\ntype `Unknown & Iterable`. This type allows you to use `obj` as an iterable. But more importantly,\nit still gives you access to attributes defined on the original unknown type (`.description`, in this\nexample):\n\n```py\ndef print_content(data: bytes):\n    obj = untyped_library.deserialize(data)\n\n    if isinstance(obj, Iterable):\n        print(obj.description)\n        for part in obj:\n            print(\"*\", part.description)\n    else:\n        print(obj.description)\n```\n\n(Full example in the [playground](https://play.ty.dev/8f98820e-7306-4d69-b572-56d69a92b90f))\n\nIntersection types are also used in `hasattr` narrowing. Take a look at the following example where\nwe narrow a type of `Person | Animal | None` using `hasattr(…, \"name\")`. `Person` is preserved in\nthe narrowed union type because it has a `name` attribute. `Animal` is intersected with a synthetic\nprotocol, accounting for the possibility of subclasses of `Animal` that add a `name` member.\n`None` is excluded completely since it is a final type that has no `name` attribute:\n\n```py\nclass Person:\n    name: str\n\nclass Animal:\n    species: str\n\ndef greet(being: Person | Animal | None):\n    if hasattr(being, \"name\"):\n        # `being` is now of type `Person | (Animal & <Protocol with members 'name'>)`\n\n        print(f\"Hello, {being.name}!\")\n    else:\n        print(\"Hello there!\")\n```\n\n(Full example in the [playground](https://play.ty.dev/31f2c718-516a-4a85-80e0-2a4682b818f1))\n\n!!! info\n\n    If you run into a situation like this and would like `Animal` to be excluded from the narrowed\n    type as well, you can make `Animal` a `@final` class. This also allows ty to infer a more precise\n    type for `being.name` (`str` instead of `object`).\n\nIf ty is the only type checker you use, you can also make direct use of intersection types in\nannotations by importing `Intersection` from the special `ty_extensions` module that is (currently)\nonly available at type-checking time:\n\n```py\nfrom typing import TYPE_CHECKING\n\nif TYPE_CHECKING:\n    from ty_extensions import Intersection\n\n    type SerializableVersioned = Intersection[Serializable, Versioned]\n\ndef output_as_json(obj: SerializableVersioned) -> str:\n    ...\n```\n\n(Full example in the [playground](https://play.ty.dev/f003e901-0e45-4f45-9759-d6db9d5e5f66))\n\n## Top and bottom materializations\n\nGradual types generally have two special [materializations]. The top materialization represents the\n\"largest\" type that a gradual type can materialize to: the union of all possible materializations.\nFor example, the top materialization of `Any` is `object`, and the top materialization of\n`Any & int` is `int`. For invariant generic classes, the top materialization cannot be expressed in\nPython's type system, but it is a useful type that ty intersects with when `isinstance` checks\ninvolve generic classes. For example, when checking `isinstance(…, list)`, ty intersects with the\ntop materialization of `list[Unknown]`:\n\n```py\n@final\nclass Item: ...\n\ndef process(items: Item | list[Item]):\n    if isinstance(items, list):\n        # reveals: list[Item]\n        reveal_type(items)\n```\n\n(Full example in the [playground](https://play.ty.dev/f1306120-0b8d-4ed5-b832-1f2d379eae2b))\n\n!!! info\n\n    You might wonder why `Item` is declared `@final` here. If we remove the `@final` decorator, the\n    inferred type in the `if` branch becomes `(Item & Top[list[Unknown]]) | list[Item]` instead.\n    This accounts for the possibility of classes that inherit from both `Item` *and* `list`! If\n    you run into this situation and want to rule out this case, you can also perform the `isinstance`\n    check against `Item` instead. The `else` branch will then have a narrowed type of\n    `list[Item] & ~Item`, which effectively acts like `list[Item]`.\n\n## Reachability based on types\n\nReachability analysis in ty is based on type inference. This allows ty to detect unreachable\nbranches in many more situations compared to approaches which match on a few known patterns (e.g.\n`sys.version_info >= (3, 10)` checks). This has useful practical applications. Consider a case\nwhere you are writing code that needs to be compatible with two major versions of a dependency.\nThe following code can be successfully type-checked with either pydantic 1.x installed, or pydantic\n2.x installed. In both cases, ty will only consider the corresponding branch to be reachable, and\nwill not emit any type errors for the other branch. This works because\n`pydantic.__version__.startswith(\"2.\")` can be evaluated to `True` or `False` at type-checking time:\n\n```py\nimport pydantic\nfrom pydantic import BaseModel\n\nPYDANTIC_V2 = pydantic.__version__.startswith(\"2.\")\n\nclass Person(BaseModel):\n    name: str\n\ndef to_json(person: Person):\n    if PYDANTIC_V2:\n        return person.model_dump_json()  # no error here when checking with 1.x\n    else:\n        return person.json()\n```\n\n(Full example in the [playground](https://play.ty.dev/34a227bb-93d5-405e-86c3-72f57ec5642e))\n\n## Gradual guarantee\n\nty generally tries to avoid emitting false positive type errors in untyped code. The following\nsnippet does not produce any type errors when checked with ty (whereas other type checkers make the\nassumption that `max_retries` is of type `None`, leading to an error in the attribute assignment):\n\n```py\nclass RetryPolicy:\n    max_retries = None\n\npolicy = RetryPolicy()\npolicy.max_retries = 1\n```\n\n(Full example in the [playground](https://play.ty.dev/a5286db1-cdfd-45e7-af54-29649ba5c423))\n\nThis is achieved by treating `max_retries` as being of type `Unknown | None`, which means that the\ntype of the attribute is not fully known, but `None` is definitely a possible value.\n\nUsers can always opt into stricter checking by adding type annotations (`int | None`, in this case).\n\n!!! info\n\n    We are also planning to add a mode for users that prefer to have stricter types inferred by default\n    in these situations. You can follow [this issue](https://github.com/astral-sh/ty/issues/1240) for\n    updates.\n\n## Fixpoint iteration\n\nIn a situation where a symbol's type cyclically depends on itself, ty uses a mechanism called fixpoint iteration to\nbe able to infer a type for that symbol. In the `tick` method below, note how the type of `self.value` depends on\n`self.value` itself. ty starts by assuming that `self.value` is just `Unknown | Literal[0]` (the type inferred\nfrom the `__init__` method), and then iterates until the type converges to `Unknown | Literal[0, 1, 2, 3, 4]`.\nWithout the modulo operation, the union would grow indefinitely. In that case, we fall back to `int` after a certain\nnumber of iterations.\n\n```py\nclass LoopingCounter:\n    def __init__(self):\n        self.value = 0\n\n    def tick(self):\n        self.value = (self.value + 1) % 5\n\n# reveals: Unknown | Literal[0, 1, 2, 3, 4]\nreveal_type(LoopingCounter().value)\n```\n\n(Full example in the [playground](https://play.ty.dev/64400d96-ee1b-48f3-8361-b583dddddf82))\n\n[materializations]: https://typing.python.org/en/latest/spec/concepts.html#materialization\n[python typing documentation]: https://typing.python.org/en/latest/spec/index.html\n"
  },
  {
    "path": "docs/index.md",
    "content": "# ty\n\nAn extremely fast Python type checker and language server, written in Rust.\n\n<p align=\"center\">\n  <img alt=\"Shows a bar chart with benchmark results.\" width=\"500px\" src=\"./assets/ty-benchmark-cli-light.svg#only-light\">\n</p>\n\n<p align=\"center\">\n  <img alt=\"Shows a bar chart with benchmark results.\" width=\"500px\" src=\"./assets/ty-benchmark-cli.svg#only-dark\">\n</p>\n\n<p align=\"center\">\n  <i>Type checking the <a href=\"https://github.com/home-assistant/core\">home-assistant</a> project without caching.</i>\n</p>\n\nty is backed by [Astral](https://astral.sh), the creators of\n[uv](https://github.com/astral-sh/uv) and [Ruff](https://github.com/astral-sh/ruff).\n\n## Highlights\n\n- 10x - 100x faster than mypy and Pyright\n- Comprehensive [diagnostics](./features/diagnostics.md) with rich contextual information\n- Configurable [rule levels](./rules.md), [per-file overrides](./reference/configuration.md#overrides), [suppression comments](./suppression.md), and first-class project support\n- Designed for adoption, with support for [redeclarations](./features/type-system.md#redeclarations) and [partially typed code](./features/type-system.md#gradual-guarantee)\n- [Language server](./features/language-server.md) with code navigation, completions, code actions, auto-import, inlay hints, on-hover help, etc.\n- Fine-grained [incremental analysis](./features/language-server.md#fine-grained-incrementality) designed for fast updates when editing files in an IDE\n- Editor integrations for [VS Code](./editors.md#vs-code), [PyCharm](./editors.md#pycharm), [Neovim](./editors.md#neovim) and more\n- 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\n    [sophisticated reachability analysis](./features/type-system.md#reachability-based-on-types)\n\n## Getting started\n\nRun ty with [uvx](https://docs.astral.sh/uv/guides/tools/#running-tools) to get started quickly:\n\n```shell\nuvx ty check\n```\n\nty will check all Python files in the working directory or project by default.\n\nSee the [type checking](./type-checking.md) documentation for more details.\n\n## Installation\n\nTo install ty, see the [installation](./installation.md) documentation.\n\nTo add the ty language server to your editor, see the [editor integration](./editors.md) guide.\n\n## Playground\n\nty has an [online playground](https://play.ty.dev) you can use to try it out on snippets or small\nprojects.\n\n!!! tip\n\n    The playground is a great way to share snippets with other people, e.g., when sharing a bug\n    report.\n"
  },
  {
    "path": "docs/installation.md",
    "content": "# Installing ty\n\n## Running ty without installation\n\nUse [uvx](https://docs.astral.sh/uv/guides/tools/) to quickly get started with ty:\n\n```shell\nuvx ty\n```\n\n## Installation methods\n\n### Adding ty to your project\n\n!!! tip\n\n    Adding ty as a dependency ensures that all developers on the project are using the same version\n    of ty.\n\nUse [uv](https://github.com/astral-sh/uv) (or your project manager of choice) to add ty as a\ndevelopment dependency:\n\n```shell\nuv add --dev ty\n```\n\nThen, use `uv run` to invoke ty:\n\n```shell\nuv run ty\n```\n\nTo update ty, use `--upgrade-package`:\n\n```shell\nuv lock --upgrade-package ty\n```\n\n### Installing globally with uv\n\nInstall ty globally with uv:\n\n```shell\nuv tool install ty@latest\n```\n\nTo update ty, use `uv tool upgrade`:\n\n```shell\nuv tool upgrade ty\n```\n\n### Installing with the standalone installer\n\nty includes a standalone installer.\n\n=== \"macOS and Linux\"\n\n    Use `curl` to download the script and execute it with `sh`:\n\n    ```console\n    $ curl -LsSf https://astral.sh/ty/install.sh | sh\n    ```\n\n    If your system doesn't have `curl`, you can use `wget`:\n\n    ```console\n    $ wget -qO- https://astral.sh/ty/install.sh | sh\n    ```\n\n    Request a specific version by including it in the URL:\n\n    ```console\n    $ curl -LsSf https://astral.sh/ty/0.0.24/install.sh | sh\n    ```\n\n=== \"Windows\"\n\n    Use `irm` to download the script and execute it with `iex`:\n\n    ```pwsh-session\n    PS> powershell -ExecutionPolicy ByPass -c \"irm https://astral.sh/ty/install.ps1 | iex\"\n    ```\n\n    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.\n\n    Request a specific version by including it in the URL:\n\n    ```pwsh-session\n    PS> powershell -ExecutionPolicy ByPass -c \"irm https://astral.sh/ty/0.0.24/install.ps1 | iex\"\n    ```\n\n!!! tip\n\n    The installation script may be inspected before use:\n\n    === \"macOS and Linux\"\n\n        ```console\n        $ curl -LsSf https://astral.sh/ty/install.sh | less\n        ```\n\n    === \"Windows\"\n\n        ```pwsh-session\n        PS> powershell -c \"irm https://astral.sh/ty/install.ps1 | more\"\n        ```\n\n    Alternatively, the installer or binaries can be downloaded directly from [GitHub](#installing-from-github-releases).\n\n### Installing from GitHub Releases\n\nty release artifacts can be downloaded directly from\n[GitHub Releases](https://github.com/astral-sh/ty/releases).\n\nEach release page includes binaries for all supported platforms as well as instructions for using\nthe standalone installer via `github.com` instead of `astral.sh`.\n\n### Installing globally with pipx\n\nInstall ty globally with pipx:\n\n```shell\npipx install ty\n```\n\nTo update ty, use `pipx upgrade`:\n\n```shell\npipx upgrade ty\n```\n\n### Installing with pip\n\nInstall ty into your current Python environment with pip:\n\n```shell\npip install ty\n```\n\n### Installing globally with mise\n\nInstall ty globally with with [mise](https://github.com/jdx/mise):\n\n```shell\nmise install ty\n```\n\nTo set it globally:\n\n```shell\nmise use --global ty\n```\n\n### Installing in Docker\n\nInstall ty in Docker by copying the binary from the official image:\n\n```dockerfile title=\"Dockerfile\"\nCOPY --from=ghcr.io/astral-sh/ty:latest /ty /bin/\n```\n\nThe following tags are available:\n\n- `ghcr.io/astral-sh/ty:latest`\n- `ghcr.io/astral-sh/ty:{major}.{minor}.{patch}`, e.g., `ghcr.io/astral-sh/ty:0.0.24`\n- `ghcr.io/astral-sh/ty:{major}.{minor}`, e.g., `ghcr.io/astral-sh/ty:0.0` (the latest patch\n    version)\n\n### Using ty with Bazel\n\n[`aspect_rules_lint`](https://registry.bazel.build/docs/aspect_rules_lint#function-lint_ty_aspect)\nprovides a Bazel lint aspect that runs ty. See its documentation for setup instructions.\n\n## Adding ty to your editor\n\nSee the [editor integration](./editors.md) guide to add ty to your editor.\n\n## Shell autocompletion\n\n!!! tip\n\n    You can run `echo $SHELL` to help you determine your shell.\n\nTo enable shell autocompletion for ty commands, run one of the following:\n\n=== \"Bash\"\n\n    ```bash\n    echo 'eval \"$(ty generate-shell-completion bash)\"' >> ~/.bashrc\n    ```\n\n=== \"Zsh\"\n\n    ```bash\n    echo 'eval \"$(ty generate-shell-completion zsh)\"' >> ~/.zshrc\n    ```\n\n=== \"fish\"\n\n    ```bash\n    echo 'ty generate-shell-completion fish | source' > ~/.config/fish/completions/ty.fish\n    ```\n\n=== \"Elvish\"\n\n    ```bash\n    echo 'eval (ty generate-shell-completion elvish | slurp)' >> ~/.elvish/rc.elv\n    ```\n\n=== \"PowerShell / pwsh\"\n\n    ```powershell\n    if (!(Test-Path -Path $PROFILE)) {\n      New-Item -ItemType File -Path $PROFILE -Force\n    }\n    Add-Content -Path $PROFILE -Value '(& ty generate-shell-completion powershell) | Out-String | Invoke-Expression'\n    ```\n\nThen restart the shell or source the shell config file.\n"
  },
  {
    "path": "docs/js/extra.js",
    "content": "function cleanupClipboardText(targetSelector) {\n  const targetElement = document.querySelector(targetSelector);\n\n  // exclude \"Generic Prompt\" and \"Generic Output\" spans from copy\n  const excludedClasses = [\"gp\", \"go\"];\n\n  const clipboardText = Array.from(targetElement.childNodes)\n    .filter(\n      (node) =>\n        !excludedClasses.some((className) =>\n          node?.classList?.contains(className)\n        )\n    )\n    .map((node) => node.textContent)\n    .filter((s) => s != \"\");\n  return clipboardText.join(\"\").trim();\n}\n\n// Sets copy text to attributes lazily using an Intersection Observer.\nfunction setCopyText() {\n  // The `data-clipboard-text` attribute allows for customized content in the copy\n  // See: https://www.npmjs.com/package/clipboard#copy-text-from-attribute\n  const attr = \"clipboardText\";\n  // all \"copy\" buttons whose target selector is a <code> element\n  const elements = document.querySelectorAll(\n    'button[data-clipboard-target$=\"code\"]'\n  );\n  const observer = new IntersectionObserver((entries) => {\n    entries.forEach((entry) => {\n      // target in the viewport that have not been patched\n      if (\n        entry.intersectionRatio > 0 &&\n        entry.target.dataset[attr] === undefined\n      ) {\n        entry.target.dataset[attr] = cleanupClipboardText(\n          entry.target.dataset.clipboardTarget\n        );\n      }\n    });\n  });\n\n  elements.forEach((elt) => {\n    observer.observe(elt);\n  });\n}\n\n// Using the document$ observable is particularly important if you are using instant loading since\n// it will not result in a page refresh in the browser\n// See `How to integrate with third-party JavaScript libraries` guideline:\n// https://squidfunk.github.io/mkdocs-material/customization/?h=javascript#additional-javascript\ndocument$.subscribe(function () {\n  setCopyText();\n});\n\n// Use client-side redirects for anchors that have moved.\n// Other redirects should use `redirect_maps` in the `mkdocs.yml` file instead.\n(function () {\n  // (there are no redirects yet)\n  let redirect_maps = {};\n\n  // The prefix for the site, see `site_dir` in `mkdocs.yml`\n  let site_dir = \"ty\";\n\n  function get_path() {\n    var path = window.location.pathname;\n\n    // Trim the site prefix\n    if (path.startsWith(\"/\" + site_dir + \"/\")) {\n      path = path.slice(site_dir.length + 2);\n    }\n\n    // Always include a trailing `/`\n    if (!path.endsWith(\"/\")) {\n      path = path + \"/\";\n    }\n\n    // Check for an anchor\n    var anchor = window.location.hash.substring(1);\n    if (!anchor) {\n      return path;\n    }\n\n    return path + \"#\" + anchor;\n  }\n\n  let path = get_path();\n  if (path && redirect_maps.hasOwnProperty(path)) {\n    window.location.replace(\"/\" + site_dir + \"/\" + redirect_maps[path]);\n  }\n})();\n"
  },
  {
    "path": "docs/modules.md",
    "content": "# Module discovery\n\n## First-party modules\n\nFirst-party modules are Python files that are part of your project source code.\n\nBy default, ty searches for first-party modules in the project's root directory or the `src`\ndirectory, if present.\n\nIf your project uses a different layout, configure the project's\n[`environment.root`](./reference/configuration.md#root) in your `pyproject.toml` or `ty.toml`. For example,\nif your project's code is in an `app/` directory:\n\n```text\nexample-pkg\n├── README.md\n├── pyproject.toml\n└── app\n    └── example_pkg\n        └── __init__.py\n```\n\nthen set [`environment.root`](./reference/configuration.md#root) in your `pyproject.toml` to `[\"./app\"]`:\n\n```toml title=\"pyproject.toml\"\n[tool.ty.environment]\nroot = [\"./app\"]\n```\n\nNote that a `./python` folder is automatically added to the project `root` if it exists,\nand is not itself a package (i.e. does not contain an `__init__.py` file or an\n`__init__.pyi` file).\n\n## Third-party modules\n\nThird-party modules are Python packages that are not part of your project or the standard library.\nThese are usually declared as dependencies in a `pyproject.toml` or `requirements.txt` file\nand installed using a package manager like uv or pip. Examples of popular third-party\nmodules are `requests`, `numpy` and `django`.\n\nty searches for third-party modules in the configured [Python environment](#python-environment).\n\n## Python environment\n\nThe Python environment is used for discovery of third-party modules.\n\nBy default, ty will attempt to discover a virtual environment.\n\nFirst, ty checks for an active virtual environment using the `VIRTUAL_ENV` environment variable. If\nnot set, ty will search for a `.venv` directory in the project root or working directory. ty only\nsupports discovery of virtual environments at this time.\n\n!!! note\n\n    When using project management tools, such as uv or Poetry, the `run` command usually automatically\n    activates the virtual environment and will be detected by ty.\n\nThe Python environment may be explicitly configured using the\n[`environment.python`](./reference/configuration.md#python) setting or\n[`--python`](./reference/cli.md#ty-check--python) flag.\n\nWhen setting the environment explicitly, non-virtual environments can be provided.\n"
  },
  {
    "path": "docs/python-version.md",
    "content": "# Python version\n\nThe Python version affects allowed syntax, type definitions of the standard library, and type\ndefinitions of first- and third-party modules that are conditional on the Python version.\n\nFor example, Python 3.10 introduced support for `match` statements and added the\n`sys.stdlib_module_names` symbol to the standard library. Syntactic features always\nneed to be available in the lowest supported Python version, but symbols may be used\nin a `sys.version_info` conditional branch:\n\n```python\nimport sys\n\n# `invalid-syntax` error if `python-version` is set to 3.9 or lower:\nmatch \"echo hello\".split():\n    case [\"echo\", message]:\n        print(message)\n    case _:\n        print(\"unknown command\")\n\n# `unresolved-attribute` error if `python-version` is set to 3.9 or lower:\nprint(sys.stdlib_module_names)\n\nif sys.version_info >= (3, 10):\n    # ok, because the usage is guarded by a version check:\n    print(sys.stdlib_module_names)\n```\n\nBy default, the lower bound of the project's [`requires-python`](https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#python-requires) field (from the `pyproject.toml`) is\nused as the target Python version, ensuring that features and symbols only available in newer Python\nversions are not used.\n\nIf the `requires-python` field is not available but a virtual environment *has* been\nconfigured or detected, ty will try to infer the Python version being used from the virtual\nenvironment's metadata.\n\nIf no virtual environment is present or inferring the Python version from the metadata fails,\nty will fall back to the latest stable Python version supported by ty (currently 3.14).\n\nThe Python version may also be explicitly specified using the\n[`python-version`](./reference/configuration.md#python-version) setting or the\n[`--python-version`](./reference/cli.md#ty-check--python-version) flag.\n"
  },
  {
    "path": "docs/reference/cli.md",
    "content": "<!-- WARNING: This file is auto-generated (cargo dev generate-all). Edit the doc comments in 'crates/ty/src/args.rs' if you want to change anything here. -->\n\n# CLI Reference\n\n## ty\n\nAn extremely fast Python type checker.\n\n<h3 class=\"cli-reference\">Usage</h3>\n\n```\nty <COMMAND>\n```\n\n<h3 class=\"cli-reference\">Commands</h3>\n\n<dl class=\"cli-reference\"><dt><a href=\"#ty-check\"><code>ty check</code></a></dt><dd><p>Check a project for type errors</p></dd>\n<dt><a href=\"#ty-server\"><code>ty server</code></a></dt><dd><p>Start the language server</p></dd>\n<dt><a href=\"#ty-version\"><code>ty version</code></a></dt><dd><p>Display ty's version</p></dd>\n<dt><a href=\"#ty-explain\"><code>ty explain</code></a></dt><dd><p>Explain rules and other parts of ty</p></dd>\n<dt><a href=\"#ty-help\"><code>ty help</code></a></dt><dd><p>Print this message or the help of the given subcommand(s)</p></dd>\n</dl>\n\n## ty check\n\nCheck a project for type errors\n\n<h3 class=\"cli-reference\">Usage</h3>\n\n```\nty check [OPTIONS] [PATH]...\n```\n\n<h3 class=\"cli-reference\">Arguments</h3>\n\n<dl class=\"cli-reference\"><dt id=\"ty-check--paths\"><a href=\"#ty-check--paths\"><code>PATHS</code></a></dt><dd><p>List of files or directories to check [default: the project root]</p>\n</dd></dl>\n\n<h3 class=\"cli-reference\">Options</h3>\n\n<dl class=\"cli-reference\"><dt id=\"ty-check--add-ignore\"><a href=\"#ty-check--add-ignore\"><code>--add-ignore</code></a></dt><dd><p>Adds <code>ty: ignore</code> comments to suppress all rule diagnostics</p>\n</dd><dt id=\"ty-check--color\"><a href=\"#ty-check--color\"><code>--color</code></a> <i>when</i></dt><dd><p>Control when colored output is used</p>\n<p>Possible values:</p>\n<ul>\n<li><code>auto</code>:  Display colors if the output goes to an interactive terminal</li>\n<li><code>always</code>:  Always display colors</li>\n<li><code>never</code>:  Never display colors</li>\n</ul></dd><dt id=\"ty-check--config\"><a href=\"#ty-check--config\"><code>--config</code></a>, <code>-c</code> <i>config-option</i></dt><dd><p>A TOML <code>&lt;KEY&gt; = &lt;VALUE&gt;</code> pair (such as you might find in a <code>ty.toml</code> configuration file)\noverriding a specific configuration option.</p>\n<p>Overrides of individual settings using this option always take precedence\nover all configuration files.</p>\n</dd><dt id=\"ty-check--config-file\"><a href=\"#ty-check--config-file\"><code>--config-file</code></a> <i>path</i></dt><dd><p>The path to a <code>ty.toml</code> file to use for configuration.</p>\n<p>While ty configuration can be included in a <code>pyproject.toml</code> file, it is not allowed in this context.</p>\n<p>May also be set with the <code>TY_CONFIG_FILE</code> environment variable.</p></dd><dt id=\"ty-check--error\"><a href=\"#ty-check--error\"><code>--error</code></a> <i>rule</i></dt><dd><p>Treat the given rule as having severity 'error'. Can be specified multiple times. Use 'all' to apply to all rules.</p>\n</dd><dt id=\"ty-check--error-on-warning\"><a href=\"#ty-check--error-on-warning\"><code>--error-on-warning</code></a></dt><dd><p>Use exit code 1 if there are any warning-level diagnostics</p>\n</dd><dt id=\"ty-check--exclude\"><a href=\"#ty-check--exclude\"><code>--exclude</code></a> <i>exclude</i></dt><dd><p>Glob patterns for files to exclude from type checking.</p>\n<p>Uses gitignore-style syntax to exclude files and directories from type checking. Supports patterns like <code>tests/</code>, <code>*.tmp</code>, <code>**/__pycache__/**</code>.</p>\n</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>\n</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>\n<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>\n</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>\n</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>\n</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. Use 'all' to apply to all rules.</p>\n</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>\n<p>For example, spinners or progress bars.</p>\n</dd><dt id=\"ty-check--output-format\"><a href=\"#ty-check--output-format\"><code>--output-format</code></a> <i>output-format</i></dt><dd><p>The format to use for printing diagnostic messages</p>\n<p>May also be set with the <code>TY_OUTPUT_FORMAT</code> environment variable.</p><p>Possible values:</p>\n<ul>\n<li><code>full</code>:  Print diagnostics verbosely, with context and helpful hints (default)</li>\n<li><code>concise</code>:  Print diagnostics concisely, one per line</li>\n<li><code>gitlab</code>:  Print diagnostics in the JSON format expected by GitLab Code Quality reports</li>\n<li><code>github</code>:  Print diagnostics in the format used by GitHub Actions workflow error annotations</li>\n<li><code>junit</code>:  Print diagnostics as a JUnit-style XML report</li>\n</ul></dd><dt id=\"ty-check--project\"><a href=\"#ty-check--project\"><code>--project</code></a> <i>project</i></dt><dd><p>Run the command within the given project directory.</p>\n<p>All <code>pyproject.toml</code> files will be discovered by walking up the directory tree from the given project directory, as will the project's virtual environment (<code>.venv</code>) unless the <code>venv-path</code> option is set.</p>\n<p>Other command-line arguments (such as relative paths) will be resolved relative to the current working directory.</p>\n</dd><dt id=\"ty-check--python\"><a href=\"#ty-check--python\"><code>--python</code></a>, <code>--venv</code> <i>path</i></dt><dd><p>Path to your project's Python environment or interpreter.</p>\n<p>ty uses your Python environment to resolve third-party imports in your code.</p>\n<p>This can be a path to:</p>\n<ul>\n<li>A Python interpreter, e.g. <code>.venv/bin/python3</code> - A virtual environment directory, e.g. <code>.venv</code> - A system Python <a href=\"https://docs.python.org/3/library/sys.html#sys.prefix\"><code>sys.prefix</code></a> directory, e.g. <code>/usr</code></li>\n</ul>\n<p>If you're using a project management tool such as uv or you have an activated Conda or virtual environment, you should not generally need to specify this option.</p>\n\n</dd><dt id=\"ty-check--python-platform\"><a href=\"#ty-check--python-platform\"><code>--python-platform</code></a>, <code>--platform</code> <i>platform</i></dt><dd><p>Target platform to assume when resolving types.</p>\n<p>This is used to specialize the type of <code>sys.platform</code> and will affect the visibility of platform-specific functions and attributes. If the value is set to <code>all</code>, no assumptions are made about the target platform. If unspecified, the current system's platform will be used.</p>\n</dd><dt id=\"ty-check--python-version\"><a href=\"#ty-check--python-version\"><code>--python-version</code></a>, <code>--target-version</code> <i>version</i></dt><dd><p>Python version to assume when resolving types.</p>\n<p>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.</p>\n<p>If a version is not specified on the command line or in a configuration file, ty will try the following techniques in order of preference to determine a value: 1. Check for the <code>project.requires-python</code> setting in a <code>pyproject.toml</code> file and use the minimum version from the specified range 2. Check for an activated or configured Python environment and attempt to infer the Python version of that environment 3. Fall back to the latest stable Python version supported by ty (see <code>ty check --help</code> output)</p>\n<p>Possible values:</p>\n<ul>\n<li><code>3.7</code></li>\n<li><code>3.8</code></li>\n<li><code>3.9</code></li>\n<li><code>3.10</code></li>\n<li><code>3.11</code></li>\n<li><code>3.12</code></li>\n<li><code>3.13</code></li>\n<li><code>3.14</code></li>\n<li><code>3.15</code></li>\n</ul></dd><dt id=\"ty-check--quiet\"><a href=\"#ty-check--quiet\"><code>--quiet</code></a>, <code>-q</code></dt><dd><p>Use quiet output (or <code>-qq</code> for silent output)</p>\n</dd><dt id=\"ty-check--respect-ignore-files\"><a href=\"#ty-check--respect-ignore-files\"><code>--respect-ignore-files</code></a></dt><dd><p>Respect file exclusions via <code>.gitignore</code> and other standard ignore files. Use <code>--no-respect-ignore-files</code> to disable</p>\n</dd><dt id=\"ty-check--typeshed\"><a href=\"#ty-check--typeshed\"><code>--typeshed</code></a>, <code>--custom-typeshed-dir</code> <i>path</i></dt><dd><p>Custom directory to use for stdlib typeshed stubs</p>\n</dd><dt id=\"ty-check--verbose\"><a href=\"#ty-check--verbose\"><code>--verbose</code></a>, <code>-v</code></dt><dd><p>Use verbose output (or <code>-vv</code> and <code>-vvv</code> for more verbose output)</p>\n</dd><dt id=\"ty-check--warn\"><a href=\"#ty-check--warn\"><code>--warn</code></a> <i>rule</i></dt><dd><p>Treat the given rule as having severity 'warn'. Can be specified multiple times. Use 'all' to apply to all rules.</p>\n</dd><dt id=\"ty-check--watch\"><a href=\"#ty-check--watch\"><code>--watch</code></a>, <code>-W</code></dt><dd><p>Watch files for changes and recheck files related to the changed files</p>\n</dd></dl>\n\n## ty server\n\nStart the language server\n\n<h3 class=\"cli-reference\">Usage</h3>\n\n```\nty server\n```\n\n<h3 class=\"cli-reference\">Options</h3>\n\n<dl class=\"cli-reference\"><dt id=\"ty-server--help\"><a href=\"#ty-server--help\"><code>--help</code></a>, <code>-h</code></dt><dd><p>Print help</p>\n</dd></dl>\n\n## ty version\n\nDisplay ty's version\n\n<h3 class=\"cli-reference\">Usage</h3>\n\n```\nty version [OPTIONS]\n```\n\n<h3 class=\"cli-reference\">Options</h3>\n\n<dl class=\"cli-reference\"><dt id=\"ty-version--help\"><a href=\"#ty-version--help\"><code>--help</code></a>, <code>-h</code></dt><dd><p>Print help</p>\n</dd><dt id=\"ty-version--output-format\"><a href=\"#ty-version--output-format\"><code>--output-format</code></a> <i>output-format</i></dt><dd><p>The format in which to display the version information</p>\n<p>[default: text]</p><p>Possible values:</p>\n<ul>\n<li><code>text</code></li>\n<li><code>json</code></li>\n</ul></dd></dl>\n\n## ty generate-shell-completion\n\nGenerate shell completion\n\n<h3 class=\"cli-reference\">Usage</h3>\n\n```\nty generate-shell-completion <SHELL>\n```\n\n<h3 class=\"cli-reference\">Arguments</h3>\n\n<dl class=\"cli-reference\"><dt id=\"ty-generate-shell-completion--shell\"><a href=\"#ty-generate-shell-completion--shell\"><code>SHELL</code></a></dt></dl>\n\n<h3 class=\"cli-reference\">Options</h3>\n\n<dl class=\"cli-reference\"><dt id=\"ty-generate-shell-completion--help\"><a href=\"#ty-generate-shell-completion--help\"><code>--help</code></a>, <code>-h</code></dt><dd><p>Print help</p>\n</dd></dl>\n\n## ty explain\n\nExplain rules and other parts of ty\n\n<h3 class=\"cli-reference\">Usage</h3>\n\n```\nty explain <COMMAND>\n```\n\n<h3 class=\"cli-reference\">Commands</h3>\n\n<dl class=\"cli-reference\"><dt><a href=\"#ty-explain-rule\"><code>ty explain rule</code></a></dt><dd><p>Explain a rule (or all rules)</p></dd>\n<dt><a href=\"#ty-explain-help\"><code>ty explain help</code></a></dt><dd><p>Print this message or the help of the given subcommand(s)</p></dd>\n</dl>\n\n### ty explain rule\n\nExplain a rule (or all rules)\n\n<h3 class=\"cli-reference\">Usage</h3>\n\n```\nty explain rule [OPTIONS] [RULE]\n```\n\n<h3 class=\"cli-reference\">Arguments</h3>\n\n<dl class=\"cli-reference\"><dt id=\"ty-explain-rule--rule\"><a href=\"#ty-explain-rule--rule\"><code>RULE</code></a></dt><dd><p>Rule to explain</p>\n<p>Defaults to all rules if omitted.</p>\n</dd></dl>\n\n<h3 class=\"cli-reference\">Options</h3>\n\n<dl class=\"cli-reference\"><dt id=\"ty-explain-rule--help\"><a href=\"#ty-explain-rule--help\"><code>--help</code></a>, <code>-h</code></dt><dd><p>Print help (see a summary with '-h')</p>\n</dd><dt id=\"ty-explain-rule--output-format\"><a href=\"#ty-explain-rule--output-format\"><code>--output-format</code></a> <i>output-format</i></dt><dd><p>Output format</p>\n<p>[default: text]</p><p>Possible values:</p>\n<ul>\n<li><code>text</code></li>\n<li><code>json</code></li>\n</ul></dd></dl>\n\n### ty explain help\n\nPrint this message or the help of the given subcommand(s)\n\n<h3 class=\"cli-reference\">Usage</h3>\n\n```\nty explain help [COMMAND]\n```\n\n## ty help\n\nPrint this message or the help of the given subcommand(s)\n\n<h3 class=\"cli-reference\">Usage</h3>\n\n```\nty help [COMMAND]\n```\n\n"
  },
  {
    "path": "docs/reference/configuration.md",
    "content": "<!-- WARNING: This file is auto-generated (cargo dev generate-all). Update the doc comments on the 'Options' struct in 'crates/ty_project/src/metadata/options.rs' if you want to change anything here. -->\n\n# Configuration\n## `rules`\n\nConfigures the enabled rules and their severity.\n\nThe keys are either rule names or `all` to set a default severity for all rules.\nSee [the rules documentation](https://ty.dev/rules) for a list of all available rules.\n\nValid severities are:\n\n* `ignore`: Disable the rule.\n* `warn`: Enable the rule and create a warning diagnostic.\n* `error`: Enable the rule and create an error diagnostic.\n  ty will exit with a non-zero code if any error diagnostics are emitted.\n\n**Default value**: `{...}`\n\n**Type**: `dict[RuleName | \"all\", \"ignore\" | \"warn\" | \"error\"]`\n\n**Example usage**:\n\n=== \"pyproject.toml\"\n\n    ```toml\n    [tool.ty.rules]\n    possibly-unresolved-reference = \"warn\"\n    division-by-zero = \"ignore\"\n    ```\n\n=== \"ty.toml\"\n\n    ```toml\n    [rules]\n    possibly-unresolved-reference = \"warn\"\n    division-by-zero = \"ignore\"\n    ```\n\n---\n\n## `analysis`\n\n### `allowed-unresolved-imports`\n\nA list of module glob patterns for which `unresolved-import` diagnostics should be suppressed.\n\nDetails on supported glob patterns:\n- `*` matches zero or more characters except `.`. For example, `foo.*` matches `foo.bar` but\n  not `foo.bar.baz`; `foo*` matches `foo` and `foobar` but not `foo.bar` or `barfoo`; and `*foo`\n  matches `foo` and `barfoo` but not `foo.bar` or `foobar`.\n- `**` matches any number of module components (e.g., `foo.**` matches `foo`, `foo.bar`, etc.)\n- Prefix a pattern with `!` to exclude matching modules\n\nWhen multiple patterns match, later entries take precedence.\n\nGlob patterns can be used in combinations with each other. For example, to suppress errors for\nany module where the first component contains the substring `test`, use `*test*.**`.\n\n**Default value**: `[]`\n\n**Type**: `list[str]`\n\n**Example usage**:\n\n=== \"pyproject.toml\"\n\n    ```toml\n    [tool.ty.analysis]\n    # Suppress errors for all `test` modules except `test.foo`\n    allowed-unresolved-imports = [\"test.**\", \"!test.foo\"]\n    ```\n\n=== \"ty.toml\"\n\n    ```toml\n    [analysis]\n    # Suppress errors for all `test` modules except `test.foo`\n    allowed-unresolved-imports = [\"test.**\", \"!test.foo\"]\n    ```\n\n---\n\n### `replace-imports-with-any`\n\nA list of module glob patterns whose imports should be replaced with `typing.Any`.\n\nUnlike `allowed-unresolved-imports`, this setting replaces the module's type information\nwith `typing.Any` even if the module can be resolved. Import diagnostics are\nunconditionally suppressed for matching modules.\n\n- Prefix a pattern with `!` to exclude matching modules\n\nWhen multiple patterns match, later entries take precedence.\n\nGlob patterns can be used in combinations with each other. For example, to suppress errors for\nany module where the first component contains the substring `test`, use `*test*.**`.\n\nWhen multiple patterns match, later entries take precedence.\n\n**Default value**: `[]`\n\n**Type**: `list[str]`\n\n**Example usage**:\n\n=== \"pyproject.toml\"\n\n    ```toml\n    [tool.ty.analysis]\n    # Replace all pandas and numpy imports with Any\n    replace-imports-with-any = [\"pandas.**\", \"numpy.**\"]\n    ```\n\n=== \"ty.toml\"\n\n    ```toml\n    [analysis]\n    # Replace all pandas and numpy imports with Any\n    replace-imports-with-any = [\"pandas.**\", \"numpy.**\"]\n    ```\n\n---\n\n### `respect-type-ignore-comments`\n\nWhether ty should respect `type: ignore` comments.\n\nWhen set to `false`, `type: ignore` comments are treated like any other normal\ncomment and can't be used to suppress ty errors (you have to use `ty: ignore` instead).\n\nSetting this option can be useful when using ty alongside other type checkers or when\nyou prefer using `ty: ignore` over `type: ignore`.\n\nDefaults to `true`.\n\n**Default value**: `true`\n\n**Type**: `bool`\n\n**Example usage**:\n\n=== \"pyproject.toml\"\n\n    ```toml\n    [tool.ty.analysis]\n    # Disable support for `type: ignore` comments\n    respect-type-ignore-comments = false\n    ```\n\n=== \"ty.toml\"\n\n    ```toml\n    [analysis]\n    # Disable support for `type: ignore` comments\n    respect-type-ignore-comments = false\n    ```\n\n---\n\n## `environment`\n\n### `extra-paths`\n\nUser-provided paths that should take first priority in module resolution.\n\nThis is an advanced option that should usually only be used for first-party or third-party\nmodules that are not installed into your Python environment in a conventional way.\nUse the `python` option to specify the location of your Python environment.\n\nThis option is similar to mypy's `MYPYPATH` environment variable and pyright's `stubPath`\nconfiguration setting.\n\n**Default value**: `[]`\n\n**Type**: `list[str]`\n\n**Example usage**:\n\n=== \"pyproject.toml\"\n\n    ```toml\n    [tool.ty.environment]\n    extra-paths = [\"./shared/my-search-path\"]\n    ```\n\n=== \"ty.toml\"\n\n    ```toml\n    [environment]\n    extra-paths = [\"./shared/my-search-path\"]\n    ```\n\n---\n\n### `python`\n\nPath to your project's Python environment or interpreter.\n\nty uses the `site-packages` directory of your project's Python environment\nto resolve third-party (and, in some cases, first-party) imports in your code.\n\nThis can be a path to:\n\n- A Python interpreter, e.g. `.venv/bin/python3`\n- A virtual environment directory, e.g. `.venv`\n- A system Python [`sys.prefix`] directory, e.g. `/usr`\n\nIf you're using a project management tool such as uv, you should not generally need to\nspecify this option, as commands such as `uv run` will set the `VIRTUAL_ENV` environment\nvariable to point to your project's virtual environment. ty can also infer the location of\nyour environment from an activated Conda environment, and will look for a `.venv` directory\nin the project root if none of the above apply. Failing that, ty will look for a `python3`\nor `python` binary available in `PATH`.\n\n[`sys.prefix`]: https://docs.python.org/3/library/sys.html#sys.prefix\n\n**Default value**: `null`\n\n**Type**: `str`\n\n**Example usage**:\n\n=== \"pyproject.toml\"\n\n    ```toml\n    [tool.ty.environment]\n    python = \"./custom-venv-location/.venv\"\n    ```\n\n=== \"ty.toml\"\n\n    ```toml\n    [environment]\n    python = \"./custom-venv-location/.venv\"\n    ```\n\n---\n\n### `python-platform`\n\nSpecifies the target platform that will be used to analyze the source code.\nIf specified, ty will understand conditions based on comparisons with `sys.platform`, such\nas are commonly found in typeshed to reflect the differing contents of the standard library across platforms.\nIf `all` is specified, ty will assume that the source code can run on any platform.\n\nIf no platform is specified, ty will use the current platform:\n- `win32` for Windows\n- `darwin` for macOS\n- `android` for Android\n- `ios` for iOS\n- `linux` for everything else\n\n**Default value**: `<current-platform>`\n\n**Type**: `\"win32\" | \"darwin\" | \"android\" | \"ios\" | \"linux\" | \"all\" | str`\n\n**Example usage**:\n\n=== \"pyproject.toml\"\n\n    ```toml\n    [tool.ty.environment]\n    # Tailor type stubs and conditionalized type definitions to windows.\n    python-platform = \"win32\"\n    ```\n\n=== \"ty.toml\"\n\n    ```toml\n    [environment]\n    # Tailor type stubs and conditionalized type definitions to windows.\n    python-platform = \"win32\"\n    ```\n\n---\n\n### `python-version`\n\nSpecifies the version of Python that will be used to analyze the source code.\nThe version should be specified as a string in the format `M.m` where `M` is the major version\nand `m` is the minor (e.g. `\"3.0\"` or `\"3.6\"`).\nIf a version is provided, ty will generate errors if the source code makes use of language features\nthat are not supported in that version.\n\nIf a version is not specified, ty will try the following techniques in order of preference\nto determine a value:\n1. Check for the `project.requires-python` setting in a `pyproject.toml` file\n   and use the minimum version from the specified range\n2. Check for an activated or configured Python environment\n   and attempt to infer the Python version of that environment\n3. Fall back to the default value (see below)\n\nFor some language features, ty can also understand conditionals based on comparisons\nwith `sys.version_info`. These are commonly found in typeshed, for example,\nto reflect the differing contents of the standard library across Python versions.\n\n**Default value**: `\"3.14\"`\n\n**Type**: `\"3.7\" | \"3.8\" | \"3.9\" | \"3.10\" | \"3.11\" | \"3.12\" | \"3.13\" | \"3.14\" | <major>.<minor>`\n\n**Example usage**:\n\n=== \"pyproject.toml\"\n\n    ```toml\n    [tool.ty.environment]\n    python-version = \"3.12\"\n    ```\n\n=== \"ty.toml\"\n\n    ```toml\n    [environment]\n    python-version = \"3.12\"\n    ```\n\n---\n\n### `root`\n\nThe root paths of the project, used for finding first-party modules.\n\nAccepts a list of directory paths searched in priority order (first has highest priority).\n\nIf left unspecified, ty will try to detect common project layouts and initialize `root` accordingly.\nThe project root (`.`) is always included. Additionally, the following directories are included\nif they exist and are not packages (i.e. they do not contain `__init__.py` or `__init__.pyi` files):\n\n* `./src`\n* `./<project-name>` (if a `./<project-name>/<project-name>` directory exists)\n* `./python`\n\n**Default value**: `null`\n\n**Type**: `list[str]`\n\n**Example usage**:\n\n=== \"pyproject.toml\"\n\n    ```toml\n    [tool.ty.environment]\n    # Multiple directories (priority order)\n    root = [\"./src\", \"./lib\", \"./vendor\"]\n    ```\n\n=== \"ty.toml\"\n\n    ```toml\n    [environment]\n    # Multiple directories (priority order)\n    root = [\"./src\", \"./lib\", \"./vendor\"]\n    ```\n\n---\n\n### `typeshed`\n\nOptional path to a \"typeshed\" directory on disk for us to use for standard-library types.\nIf this is not provided, we will fallback to our vendored typeshed stubs for the stdlib,\nbundled as a zip file in the binary\n\n**Default value**: `null`\n\n**Type**: `str`\n\n**Example usage**:\n\n=== \"pyproject.toml\"\n\n    ```toml\n    [tool.ty.environment]\n    typeshed = \"/path/to/custom/typeshed\"\n    ```\n\n=== \"ty.toml\"\n\n    ```toml\n    [environment]\n    typeshed = \"/path/to/custom/typeshed\"\n    ```\n\n---\n\n## `overrides`\n\nConfiguration override that applies to specific files based on glob patterns.\n\nAn override allows you to apply different rule configurations to specific\nfiles or directories. Multiple overrides can match the same file, with\nlater overrides take precedence. Override rules take precedence over global\nrules for matching files.\n\nFor example, to relax enforcement of rules in test files:\n\n```toml\n[[tool.ty.overrides]]\ninclude = [\"tests/**\", \"**/test_*.py\"]\n\n[tool.ty.overrides.rules]\npossibly-unresolved-reference = \"warn\"\n```\n\nOr, to ignore a rule in generated files but retain enforcement in an important file:\n\n```toml\n[[tool.ty.overrides]]\ninclude = [\"generated/**\"]\nexclude = [\"generated/important.py\"]\n\n[tool.ty.overrides.rules]\npossibly-unresolved-reference = \"ignore\"\n```\n\n\n### `exclude`\n\nA list of file and directory patterns to exclude from this override.\n\nPatterns follow a syntax similar to `.gitignore`.\nExclude patterns take precedence over include patterns within the same override.\n\nIf not specified, defaults to `[]` (excludes no files).\n\n**Default value**: `null`\n\n**Type**: `list[str]`\n\n**Example usage**:\n\n=== \"pyproject.toml\"\n\n    ```toml\n    [[tool.ty.overrides]]\n    exclude = [\n        \"generated\",\n        \"*.proto\",\n        \"tests/fixtures/**\",\n        \"!tests/fixtures/important.py\"  # Include this one file\n    ]\n    ```\n\n=== \"ty.toml\"\n\n    ```toml\n    [[overrides]]\n    exclude = [\n        \"generated\",\n        \"*.proto\",\n        \"tests/fixtures/**\",\n        \"!tests/fixtures/important.py\"  # Include this one file\n    ]\n    ```\n\n---\n\n### `include`\n\nA list of file and directory patterns to include for this override.\n\nThe `include` option follows a similar syntax to `.gitignore` but reversed:\nIncluding a file or directory will make it so that it (and its contents)\nare affected by this override.\n\nIf not specified, defaults to `[\"**\"]` (matches all files).\n\n**Default value**: `null`\n\n**Type**: `list[str]`\n\n**Example usage**:\n\n=== \"pyproject.toml\"\n\n    ```toml\n    [[tool.ty.overrides]]\n    include = [\n        \"src\",\n        \"tests\",\n    ]\n    ```\n\n=== \"ty.toml\"\n\n    ```toml\n    [[overrides]]\n    include = [\n        \"src\",\n        \"tests\",\n    ]\n    ```\n\n---\n\n### `rules`\n\nRule overrides for files matching the include/exclude patterns.\n\nThese rules will be merged with the global rules, with override rules\ntaking precedence for matching files. You can set rules to different\nseverity levels or disable them entirely.\n\n**Default value**: `{...}`\n\n**Type**: `dict[RuleName | \"all\", \"ignore\" | \"warn\" | \"error\"]`\n\n**Example usage**:\n\n=== \"pyproject.toml\"\n\n    ```toml\n    [[tool.ty.overrides]]\n    include = [\"src\"]\n\n    [tool.ty.overrides.rules]\n    possibly-unresolved-reference = \"ignore\"\n    ```\n\n=== \"ty.toml\"\n\n    ```toml\n    [[overrides]]\n    include = [\"src\"]\n\n    [overrides.rules]\n    possibly-unresolved-reference = \"ignore\"\n    ```\n\n---\n\n## `overrides.analysis`\n\n#### `allowed-unresolved-imports`\n\nA list of module glob patterns for which `unresolved-import` diagnostics should be suppressed.\n\nDetails on supported glob patterns:\n- `*` matches zero or more characters except `.`. For example, `foo.*` matches `foo.bar` but\n  not `foo.bar.baz`; `foo*` matches `foo` and `foobar` but not `foo.bar` or `barfoo`; and `*foo`\n  matches `foo` and `barfoo` but not `foo.bar` or `foobar`.\n- `**` matches any number of module components (e.g., `foo.**` matches `foo`, `foo.bar`, etc.)\n- Prefix a pattern with `!` to exclude matching modules\n\nWhen multiple patterns match, later entries take precedence.\n\nGlob patterns can be used in combinations with each other. For example, to suppress errors for\nany module where the first component contains the substring `test`, use `*test*.**`.\n\n**Default value**: `[]`\n\n**Type**: `list[str]`\n\n**Example usage**:\n\n=== \"pyproject.toml\"\n\n    ```toml\n    [tool.ty.overrides.analysis]\n    # Suppress errors for all `test` modules except `test.foo`\n    allowed-unresolved-imports = [\"test.**\", \"!test.foo\"]\n    ```\n\n=== \"ty.toml\"\n\n    ```toml\n    [overrides.analysis]\n    # Suppress errors for all `test` modules except `test.foo`\n    allowed-unresolved-imports = [\"test.**\", \"!test.foo\"]\n    ```\n\n---\n\n#### `replace-imports-with-any`\n\nA list of module glob patterns whose imports should be replaced with `typing.Any`.\n\nUnlike `allowed-unresolved-imports`, this setting replaces the module's type information\nwith `typing.Any` even if the module can be resolved. Import diagnostics are\nunconditionally suppressed for matching modules.\n\n- Prefix a pattern with `!` to exclude matching modules\n\nWhen multiple patterns match, later entries take precedence.\n\nGlob patterns can be used in combinations with each other. For example, to suppress errors for\nany module where the first component contains the substring `test`, use `*test*.**`.\n\nWhen multiple patterns match, later entries take precedence.\n\n**Default value**: `[]`\n\n**Type**: `list[str]`\n\n**Example usage**:\n\n=== \"pyproject.toml\"\n\n    ```toml\n    [tool.ty.overrides.analysis]\n    # Replace all pandas and numpy imports with Any\n    replace-imports-with-any = [\"pandas.**\", \"numpy.**\"]\n    ```\n\n=== \"ty.toml\"\n\n    ```toml\n    [overrides.analysis]\n    # Replace all pandas and numpy imports with Any\n    replace-imports-with-any = [\"pandas.**\", \"numpy.**\"]\n    ```\n\n---\n\n#### `respect-type-ignore-comments`\n\nWhether ty should respect `type: ignore` comments.\n\nWhen set to `false`, `type: ignore` comments are treated like any other normal\ncomment and can't be used to suppress ty errors (you have to use `ty: ignore` instead).\n\nSetting this option can be useful when using ty alongside other type checkers or when\nyou prefer using `ty: ignore` over `type: ignore`.\n\nDefaults to `true`.\n\n**Default value**: `true`\n\n**Type**: `bool`\n\n**Example usage**:\n\n=== \"pyproject.toml\"\n\n    ```toml\n    [tool.ty.overrides.analysis]\n    # Disable support for `type: ignore` comments\n    respect-type-ignore-comments = false\n    ```\n\n=== \"ty.toml\"\n\n    ```toml\n    [overrides.analysis]\n    # Disable support for `type: ignore` comments\n    respect-type-ignore-comments = false\n    ```\n\n---\n\n## `src`\n\n### `exclude`\n\nA list of file and directory patterns to exclude from type checking.\n\nPatterns follow a syntax similar to `.gitignore`:\n\n- `./src/` matches only a directory\n- `./src` matches both files and directories\n- `src` matches files or directories named `src`\n- `*` matches any (possibly empty) sequence of characters (except `/`).\n- `**` matches zero or more path components.\n  This sequence **must** form a single path component, so both `**a` and `b**` are invalid and will result in an error.\n  A sequence of more than two consecutive `*` characters is also invalid.\n- `?` matches any single character except `/`\n- `[abc]` matches any character inside the brackets. Character sequences can also specify ranges of characters, as ordered by Unicode,\n  so e.g. `[0-9]` specifies any character between `0` and `9` inclusive. An unclosed bracket is invalid.\n- `!pattern` negates a pattern (undoes the exclusion of files that would otherwise be excluded)\n\nAll paths are anchored relative to the project root (`src` only\nmatches `<project_root>/src` and not `<project_root>/test/src`).\nTo exclude any directory or file named `src`, use `**/src` instead.\n\nBy default, ty excludes commonly ignored directories:\n\n- `**/.bzr/`\n- `**/.direnv/`\n- `**/.eggs/`\n- `**/.git/`\n- `**/.git-rewrite/`\n- `**/.hg/`\n- `**/.mypy_cache/`\n- `**/.nox/`\n- `**/.pants.d/`\n- `**/.pytype/`\n- `**/.ruff_cache/`\n- `**/.svn/`\n- `**/.tox/`\n- `**/.venv/`\n- `**/__pypackages__/`\n- `**/_build/`\n- `**/buck-out/`\n- `**/dist/`\n- `**/node_modules/`\n- `**/venv/`\n\nYou can override any default exclude by using a negated pattern. For example,\nto re-include `dist` use `exclude = [\"!dist\"]`\n\n**Default value**: `null`\n\n**Type**: `list[str]`\n\n**Example usage**:\n\n=== \"pyproject.toml\"\n\n    ```toml\n    [tool.ty.src]\n    exclude = [\n        \"generated\",\n        \"*.proto\",\n        \"tests/fixtures/**\",\n        \"!tests/fixtures/important.py\"  # Include this one file\n    ]\n    ```\n\n=== \"ty.toml\"\n\n    ```toml\n    [src]\n    exclude = [\n        \"generated\",\n        \"*.proto\",\n        \"tests/fixtures/**\",\n        \"!tests/fixtures/important.py\"  # Include this one file\n    ]\n    ```\n\n---\n\n### `include`\n\nA list of files and directories to check. The `include` option\nfollows a similar syntax to `.gitignore` but reversed:\nIncluding a file or directory will make it so that it (and its contents)\nare type checked.\n\n- `./src/` matches only a directory\n- `./src` matches both files and directories\n- `src` matches a file or directory named `src`\n- `*` matches any (possibly empty) sequence of characters (except `/`).\n- `**` matches zero or more path components.\n  This sequence **must** form a single path component, so both `**a` and `b**` are invalid and will result in an error.\n  A sequence of more than two consecutive `*` characters is also invalid.\n- `?` matches any single character except `/`\n- `[abc]` matches any character inside the brackets. Character sequences can also specify ranges of characters, as ordered by Unicode,\n  so e.g. `[0-9]` specifies any character between `0` and `9` inclusive. An unclosed bracket is invalid.\n\nAll paths are anchored relative to the project root (`src` only\nmatches `<project_root>/src` and not `<project_root>/test/src`).\n\n`exclude` takes precedence over `include`.\n\n**Default value**: `null`\n\n**Type**: `list[str]`\n\n**Example usage**:\n\n=== \"pyproject.toml\"\n\n    ```toml\n    [tool.ty.src]\n    include = [\n        \"src\",\n        \"tests\",\n    ]\n    ```\n\n=== \"ty.toml\"\n\n    ```toml\n    [src]\n    include = [\n        \"src\",\n        \"tests\",\n    ]\n    ```\n\n---\n\n### `respect-ignore-files`\n\nWhether to automatically exclude files that are ignored by `.ignore`,\n`.gitignore`, `.git/info/exclude`, and global `gitignore` files.\nEnabled by default.\n\n**Default value**: `true`\n\n**Type**: `bool`\n\n**Example usage**:\n\n=== \"pyproject.toml\"\n\n    ```toml\n    [tool.ty.src]\n    respect-ignore-files = false\n    ```\n\n=== \"ty.toml\"\n\n    ```toml\n    [src]\n    respect-ignore-files = false\n    ```\n\n---\n\n### `root`\n\n!!! warning \"Deprecated\"\n    This option has been deprecated. Use `environment.root` instead.\n\nThe root of the project, used for finding first-party modules.\n\nIf left unspecified, ty will try to detect common project layouts and initialize `src.root` accordingly.\nThe project root (`.`) is always included. Additionally, the following directories are included\nif they exist and are not packages (i.e. they do not contain `__init__.py` or `__init__.pyi` files):\n\n* `./src`\n* `./<project-name>` (if a `./<project-name>/<project-name>` directory exists)\n* `./python`\n\n**Default value**: `null`\n\n**Type**: `str`\n\n**Example usage**:\n\n=== \"pyproject.toml\"\n\n    ```toml\n    [tool.ty.src]\n    root = \"./app\"\n    ```\n\n=== \"ty.toml\"\n\n    ```toml\n    [src]\n    root = \"./app\"\n    ```\n\n---\n\n## `terminal`\n\n### `error-on-warning`\n\nUse exit code 1 if there are any warning-level diagnostics.\n\nDefaults to `false`.\n\n**Default value**: `false`\n\n**Type**: `bool`\n\n**Example usage**:\n\n=== \"pyproject.toml\"\n\n    ```toml\n    [tool.ty.terminal]\n    # Error if ty emits any warning-level diagnostics.\n    error-on-warning = true\n    ```\n\n=== \"ty.toml\"\n\n    ```toml\n    [terminal]\n    # Error if ty emits any warning-level diagnostics.\n    error-on-warning = true\n    ```\n\n---\n\n### `output-format`\n\nThe format to use for printing diagnostic messages.\n\nDefaults to `full`.\n\n**Default value**: `full`\n\n**Type**: `full | concise | github | gitlab | junit`\n\n**Example usage**:\n\n=== \"pyproject.toml\"\n\n    ```toml\n    [tool.ty.terminal]\n    output-format = \"concise\"\n    ```\n\n=== \"ty.toml\"\n\n    ```toml\n    [terminal]\n    output-format = \"concise\"\n    ```\n\n---\n\n"
  },
  {
    "path": "docs/reference/editor-settings.md",
    "content": "# Editor settings\n\nThe editor settings supported by ty's language server, as well as the settings specific to [ty's VS\nCode extension][ty-vscode].\n\n## `configuration`\n\nIn-editor configuration of ty's settings. The inline settings always take precedence over the settings from configuration files,\nincluding the configuration specified with [`configurationFile`](#configurationfile).\n\nConsult [the configuration reference](../configuration.md) for a list of all supported configuration options.\n\n**Default value**: `null`\n\n**Type**: `object`\n\n**Example usage**:\n\n=== \"VS Code\"\n\n    ```json\n    {\n      \"ty.configuration\": {\n        \"rules\": {\n          \"unresolved-reference\": \"warn\"\n        }\n      }\n    }\n    ```\n\n=== \"Neovim\"\n\n    ```lua\n    -- Neovim >=0.11:\n    vim.lsp.config('ty', {\n      settings = {\n        ty = {\n          configuration = {\n            rules = {\n              [\"unresolved-reference\"] = \"warn\"\n            }\n          }\n        },\n      },\n    })\n\n    -- Neovim <0.11:\n    require('lspconfig').ty.setup({\n      settings = {\n        ty = {\n          configuration = {\n            rules = {\n              [\"unresolved-reference\"] = \"warn\"\n            }\n          }\n        },\n      },\n    })\n    ```\n\n=== \"Zed\"\n\n    ```json\n    {\n      \"lsp\": {\n        \"ty\": {\n          \"settings\": {\n            \"configuration\": {\n               \"rules\": {\n                \"unresolved-reference\": \"warn\"\n              }\n            }\n          }\n        }\n      }\n    }\n    ```\n\n## `configurationFile`\n\nThe path to a `ty.toml` configuration file. ty will use the specified configuration over any automatically discovered configuration.\nty will expand a tilde `~` at the start of a string to the user's home directory, as well as variables like `$A` or `${A}`.\n\n!!! info\n\n    While ty configuration can be included in a `pyproject.toml` file, it is not allowed in this context.\n\n**Default value**: `null`\n\n**Type**: `string`\n\n**Example usage**:\n\n=== \"VS Code\"\n\n    ```json\n    {\n      \"ty.configurationFile\": \"./.config/ty.toml\"\n    }\n    ```\n\n=== \"Neovim\"\n\n    ```lua\n    -- Neovim >=0.11:\n    vim.lsp.config('ty', {\n      settings = {\n        ty = {\n          configurationFile = \"./.config/ty.toml\"\n        },\n      },\n    })\n\n    -- Neovim <0.11:\n    require('lspconfig').ty.setup({\n      settings = {\n        ty = {\n          configurationFile = \"./.config/ty.toml\"\n        },\n      },\n    })\n    ```\n\n=== \"Zed\"\n\n    ```json\n    {\n      \"lsp\": {\n        \"ty\": {\n          \"settings\": {\n            \"configurationFile\": \"./.config/ty.toml\"\n          }\n        }\n      }\n    }\n    ```\n\n______________________________________________________________________\n\n## `disableLanguageServices`\n\nWhether to disable the language services for the ty language server like code completion, hover,\ngo to definition, etc.\n\nThis is useful if you want to use ty exclusively for type checking and want to use another language\nserver for features like code completion, hover, go to definition, etc.\n\n**Default value**: `false`\n\n**Type**: `boolean`\n\n**Example usage**:\n\n=== \"VS Code\"\n\n    ```json\n    {\n      \"ty.disableLanguageServices\": true\n    }\n    ```\n\n=== \"Neovim\"\n\n    ```lua\n    -- Neovim >=0.11:\n    vim.lsp.config('ty', {\n      settings = {\n        ty = {\n          disableLanguageServices = true,\n        },\n      },\n    })\n\n    -- Neovim <0.11:\n    require('lspconfig').ty.setup({\n      settings = {\n        ty = {\n          disableLanguageServices = true,\n        },\n      },\n    })\n    ```\n\n=== \"Zed\"\n\n    ```json\n    {\n      \"lsp\": {\n        \"ty\": {\n          \"settings\": {\n            \"disableLanguageServices\": true\n          }\n        }\n      }\n    }\n    ```\n\n______________________________________________________________________\n\n## `diagnosticMode`\n\nDetermines the scope of the diagnostics reported by the language server.\n\nSetting this to `off` is useful if you want to use ty exclusively for the language server features\nlike code completion, hover, go to definition, etc.\n\n- `off`: Diagnostics are disabled.\n- `openFilesOnly`: Diagnostics are reported only for files that are currently open in the editor.\n- `workspace`: Diagnostics are reported for all files in the workspace.\n\n**Default value**: `\"openFilesOnly\"`\n\n**Type**: `\"off\" | \"workspace\" | \"openFilesOnly\"`\n\n**Example usage**:\n\n=== \"VS Code\"\n\n    ```json\n    {\n      \"ty.diagnosticMode\": \"workspace\"\n    }\n    ```\n\n=== \"Neovim\"\n\n    ```lua\n    -- Neovim >=0.11:\n    vim.lsp.config('ty', {\n      settings = {\n        ty = {\n          diagnosticMode = 'workspace',\n        },\n      },\n    })\n\n    -- Neovim <0.11:\n    require('lspconfig').ty.setup({\n      settings = {\n        ty = {\n          diagnosticMode = 'workspace',\n        },\n      },\n    })\n    ```\n\n=== \"Zed\"\n\n    ```json\n    {\n      \"lsp\": {\n        \"ty\": {\n          \"settings\": {\n            \"diagnosticMode\": \"workspace\"\n          }\n        }\n      }\n    }\n    ```\n\n______________________________________________________________________\n\n## `showSyntaxErrors`\n\nWhether to show syntax error diagnostics.\n\nThis is useful when using ty with other language servers, allowing the user to refer to syntax errors\nfrom only one source.\n\n**Default value**: `true`\n\n**Type**: `bool`\n\n**Example usage**:\n\n=== \"VS Code\"\n\n    ```json\n    {\n        \"ty.showSyntaxErrors\": false\n    }\n    ```\n\n=== \"Neovim\"\n\n    ```lua\n    -- Neovim >=0.11:\n    vim.lsp.config('ty', {\n      settings = {\n        ty = {\n          showSyntaxErrors = false,\n        },\n      },\n    })\n\n    -- Neovim <0.11:\n    require('lspconfig').ty.setup({\n      settings = {\n        ty = {\n          showSyntaxErrors = false,\n        },\n      },\n    })\n    ```\n\n=== \"Zed\"\n\n    ```json\n    {\n      \"lsp\": {\n        \"ty\": {\n          \"settings\": {\n            \"showSyntaxErrors\": false\n          }\n        }\n      }\n    }\n    ```\n\n______________________________________________________________________\n\n## `inlayHints`\n\nThese settings control the inline hints that ty provides in an editor.\n\n### `variableTypes`\n\nWhether to show the types of variables as inline hints.\n\n**Default value**: `true`\n\n**Type**: `boolean`\n\n**Example usage**:\n\n=== \"VS Code\"\n\n    ```json\n    {\n      \"ty.inlayHints.variableTypes\": false\n    }\n    ```\n\n=== \"Neovim\"\n\n    ```lua\n    -- Neovim >=0.11:\n    vim.lsp.config('ty', {\n      settings = {\n        ty = {\n          inlayHints = {\n            variableTypes = false,\n          },\n        },\n      },\n    })\n\n    -- Neovim <0.11:\n    require('lspconfig').ty.setup({\n      settings = {\n        ty = {\n          inlayHints = {\n            variableTypes = false,\n          },\n        },\n      },\n    })\n    ```\n\n=== \"Zed\"\n\n    ```json\n    {\n      \"lsp\": {\n        \"ty\": {\n          \"settings\": {\n            \"inlayHints\": {\n              \"variableTypes\": false\n            }\n          }\n        }\n      }\n    }\n    ```\n\n### `callArgumentNames`\n\nWhether to show argument names in call expressions as inline hints.\n\n**Default value**: `true`\n\n**Type**: `boolean`\n\n**Example usage**:\n\n=== \"VS Code\"\n\n    ```json\n    {\n      \"ty.inlayHints.callArgumentNames\": false\n    }\n    ```\n\n=== \"Neovim\"\n\n    ```lua\n    -- Neovim >=0.11:\n    vim.lsp.config('ty', {\n      settings = {\n        ty = {\n          inlayHints = {\n            callArgumentNames = false,\n          },\n        },\n      },\n    })\n\n    -- Neovim <0.11:\n    require('lspconfig').ty.setup({\n      settings = {\n        ty = {\n          inlayHints = {\n            callArgumentNames = false,\n          },\n        },\n      },\n    })\n    ```\n\n=== \"Zed\"\n\n    ```json\n    {\n      \"lsp\": {\n        \"ty\": {\n          \"settings\": {\n            \"inlayHints\": {\n              \"callArgumentNames\": false\n            }\n          }\n        }\n      }\n    }\n    ```\n\n______________________________________________________________________\n\n## `completions`\n\nThese settings control how code completions offered by ty work.\n\n### `autoImport`\n\nWhether to include auto-import suggestions in code completions. That is, code completions will\ninclude symbols not currently in scope but available in your environment.\n\n**Default value**: `true`\n\n**Type**: `boolean`\n\n**Example usage**:\n\n=== \"VS Code\"\n\n    ```json\n    {\n      \"ty.completions.autoImport\": true\n    }\n    ```\n\n=== \"Neovim\"\n\n    ```lua\n    -- Neovim >=0.11:\n    vim.lsp.config('ty', {\n      settings = {\n        ty = {\n          completions = {\n            autoImport = true,\n          },\n        },\n      },\n    })\n\n    -- Neovim <0.11:\n    require('lspconfig').ty.setup({\n      settings = {\n        ty = {\n          completions = {\n            autoImport = true,\n          },\n        },\n      },\n    })\n    ```\n\n=== \"Zed\"\n\n    ```json\n    {\n      \"lsp\": {\n        \"ty\": {\n          \"settings\": {\n            \"completions\": {\n              \"autoImport\": true\n            }\n          }\n        }\n      }\n    }\n    ```\n\n______________________________________________________________________\n\n## VS Code specific\n\nThe following settings are specific to [ty's VS Code extension][ty-vscode].\n\n### `importStrategy`\n\nStrategy for loading the `ty` executable.\n\n- `fromEnvironment` finds ty in the environment, falling back to the bundled version\n- `useBundled` uses the version bundled with the extension\n\n**Default value**: `\"fromEnvironment\"`\n\n**Type**: `\"fromEnvironment\" | \"useBundled\"`\n\n**Example usage**:\n\n```json\n{\n  \"ty.importStrategy\": \"useBundled\"\n}\n```\n\n______________________________________________________________________\n\n### `interpreter`\n\nA list of paths to Python interpreters. Even though this is a list, only the first interpreter is\nused.\n\nThe interpreter path is used to find the `ty` executable when\n[`ty.importStrategy`](#importstrategy) is set to `fromEnvironment`.\n\n**Default value**: `[]`\n\n**Type**: `string[]`\n\n**Example usage**:\n\n```json\n{\n  \"ty.interpreter\": [\"/home/user/.local/bin/python\"]\n}\n```\n\n______________________________________________________________________\n\n### `path`\n\nA list of path to `ty` executables.\n\nThe extension uses the first executable that exists. This setting takes precedence over the\n[`ty.importStrategy`](#importstrategy) setting.\n\n**Default value**: `[]`\n\n**Type**: `string[]`\n\n**Example usage**:\n\n```json\n{\n  \"ty.path\": [\"/home/user/.local/bin/ty\"]\n}\n```\n\n______________________________________________________________________\n\n### `trace.server`\n\nThe detail level at which messages between the language server and the editor (client) are logged.\n\nThis setting is useful for debugging issues with the language server. Refer to the [troubleshooting\nguide](https://github.com/astral-sh/ty-vscode/blob/6cf16b4e87342a49f2bec1310a730cde8229e1d9/TROUBLESHOOTING.md)\nin [ty's VS Code extension][ty-vscode] for more information.\n\n**Default value**: `\"off\"`\n\n**Type**: `\"off\" | \"messages\" | \"verbose\"`\n\n**Example usage**:\n\n```json\n{\n  \"ty.trace.server\": \"messages\"\n}\n```\n\n______________________________________________________________________\n\n## Initialization options\n\nThe following settings are required when ty is initialized in an editor. These settings are\nstatic so changing them requires restarting the editor to take effect.\n\nFor VS Code users, these settings are defined in the `ty.*` namespace as usual, but for other\neditors, they would need to be provided in a separate field of the configuration that corresponds to\nthe initialization options. Refer to the examples below for how to set these options in different\neditors.\n\n### `logFile`\n\nPath to the file to which the language server writes its log messages. By default, ty writes log messages to stderr.\n\n**Default value**: `null`\n\n**Type**: `string`\n\n**Example usage**:\n\n=== \"VS Code\"\n\n    ```json\n    {\n      \"ty.logFile\": \"/path/to/ty.log\"\n    }\n    ```\n\n=== \"Neovim\"\n\n    ```lua\n    -- Neovim >=0.11:\n    vim.lsp.config('ty', {\n      init_options = {\n        logFile = '/path/to/ty.log',\n      },\n    })\n\n    -- Neovim <0.11:\n    require('lspconfig').ty.setup({\n      init_options = {\n        logFile = '/path/to/ty.log',\n      },\n    })\n    ```\n\n=== \"Zed\"\n\n    ```json\n    {\n      \"lsp\": {\n        \"ty\": {\n          \"initialization_options\": {\n            \"logFile\": \"/path/to/ty.log\"\n          }\n        }\n      }\n    }\n    ```\n\n______________________________________________________________________\n\n### `logLevel`\n\nThe log level to use for the language server.\n\n**Default value**: `\"info\"`\n\n**Type**: `\"trace\" | \"debug\" | \"info\" | \"warn\" | \"error\"`\n\n**Example usage**:\n\n=== \"VS Code\"\n\n    ```json\n    {\n      \"ty.logLevel\": \"debug\"\n    }\n    ```\n\n=== \"Neovim\"\n\n    ```lua\n    -- Neovim >=0.11:\n    vim.lsp.config('ty', {\n      init_options = {\n        logLevel = 'debug',\n      },\n    })\n\n    -- Neovim <0.11:\n    require('lspconfig').ty.setup({\n      init_options = {\n        logLevel = 'debug',\n      },\n    })\n    ```\n\n=== \"Zed\"\n\n    ```json\n    {\n      \"lsp\": {\n        \"ty\": {\n          \"initialization_options\": {\n            \"logLevel\": \"debug\"\n          }\n        }\n      }\n    }\n    ```\n\n[ty-vscode]: https://marketplace.visualstudio.com/items?itemName=astral-sh.ty\n"
  },
  {
    "path": "docs/reference/environment.md",
    "content": "# Environment variables\n\nty defines and respects the following environment variables:\n\n### `TY_CONFIG_FILE`\n\nPath to a `ty.toml` configuration file to use.\n\nWhen set, ty will use this file for configuration instead of\ndiscovering configuration files automatically.\n\nEquivalent to the `--config-file` command-line argument.\n\n### `TY_LOG`\n\nIf set, ty will use this value as the log level for its `--verbose` output.\nAccepts any filter compatible with the `tracing_subscriber` crate.\n\nFor example:\n\n- `TY_LOG=ty=debug` is the equivalent of `-vv` to the command line\n- `TY_LOG=trace` will enable all trace-level logging.\n\nSee the [tracing documentation](https://docs.rs/tracing-subscriber/latest/tracing_subscriber/filter/struct.EnvFilter.html#example-syntax)\nfor more.\n\n### `TY_LOG_PROFILE`\n\nIf set to `\"1\"` or `\"true\"`, ty will enable flamegraph profiling.\nThis creates a `tracing.folded` file that can be used to generate flame graphs\nfor performance analysis.\n\n### `TY_MAX_PARALLELISM`\n\nSpecifies an upper limit for the number of tasks ty is allowed to run in parallel.\n\nFor example, how many files should be checked in parallel.\nThis isn't the same as a thread limit. ty may spawn additional threads\nwhen necessary, e.g. to watch for file system changes or a dedicated UI thread.\n\n### `TY_OUTPUT_FORMAT`\n\nThe format to use for printing diagnostic messages.\n\nWhen set, ty will use this format for output instead of the default.\n\nAccepts the same values as the `--output-format` command-line argument.\n\n## Externally-defined variables\n\nty also reads the following externally defined environment variables:\n\n### `CONDA_DEFAULT_ENV`\n\nUsed to determine the name of the active Conda environment.\n\n### `CONDA_PREFIX`\n\nUsed to detect the path of an active Conda environment.\nIf both `VIRTUAL_ENV` and `CONDA_PREFIX` are present, `VIRTUAL_ENV` will be preferred.\n\n### `PYTHONPATH`\n\nAdds additional directories to ty's search paths.\nThe format is the same as the shell’s PATH:\none or more directory pathnames separated by os appropriate pathsep\n(e.g. colons on Unix or semicolons on Windows).\n\n### `RAYON_NUM_THREADS`\n\nSpecifies an upper limit for the number of threads ty uses when performing work in parallel.\nEquivalent to `TY_MAX_PARALLELISM`.\n\nThis is a standard Rayon environment variable.\n\n### `VIRTUAL_ENV`\n\nUsed to detect an activated virtual environment.\n\n### `XDG_CONFIG_HOME`\n\nPath to user-level configuration directory on Unix systems.\n\n### `_CONDA_ROOT`\n\nUsed to determine the root install path of Conda.\n\n"
  },
  {
    "path": "docs/reference/exit-codes.md",
    "content": "# Exit codes\n\nThe ty command line interface uses the following exit codes:\n\n| Exit code | Description                                              |\n| :-------- | :------------------------------------------------------- |\n| `0`       | no violations with severity `error` or higher were found |\n| `1`       | violations with severity `error` or higher were found    |\n| `2`       | invalid CLI options, invalid configuration, or IO errors |\n| `101`     | internal error                                           |\n\nty supports two command line arguments that change how exit codes work:\n\n- `--exit-zero`: ty will exit with `0` even if violations were found.\n- `--error-on-warning`: ty will exit with `1` if it finds any violations with severity `warning` or\n    higher.\n"
  },
  {
    "path": "docs/reference/rules.md",
    "content": "<!-- WARNING: This file is auto-generated (cargo dev generate-all). Edit the lint-declarations in 'crates/ty_python_semantic/src/types/diagnostic.rs' if you want to change anything here. -->\n\n# Rules\n\n## `abstract-method-in-final-class`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.13\">0.0.13</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22abstract-method-in-final-class%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2321\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for `@final` classes that have unimplemented abstract methods.\n\n**Why is this bad?**\n\nA class decorated with `@final` cannot be subclassed. If such a class has abstract\nmethods that are not implemented, the class can never be properly instantiated, as\nthe abstract methods can never be implemented (since subclassing is prohibited).\n\nAt runtime, instantiation of classes with unimplemented abstract methods is only\nprevented for classes that have `ABCMeta` (or a subclass of it) as their metaclass.\nHowever, type checkers also enforce this for classes that do not use `ABCMeta`, since\nthe intent for the class to be abstract is clear from the use of `@abstractmethod`.\n\n**Example**\n\n\n```python\nfrom abc import ABC, abstractmethod\nfrom typing import final\n\nclass Base(ABC):\n    @abstractmethod\n    def method(self) -> int: ...\n\n@final\nclass Derived(Base):  # Error: `Derived` does not implement `method`\n    pass\n```\n\n## `ambiguous-protocol-member`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'warn'.\"><code>warn</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.20\">0.0.1-alpha.20</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22ambiguous-protocol-member%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L654\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for protocol classes with members that will lead to ambiguous interfaces.\n\n**Why is this bad?**\n\nAssigning to an undeclared variable in a protocol class leads to an ambiguous\ninterface which may lead to the type checker inferring unexpected things. It's\nrecommended to ensure that all members of a protocol class are explicitly declared.\n\n**Examples**\n\n\n```py\nfrom typing import Protocol\n\nclass BaseProto(Protocol):\n    a: int                               # fine (explicitly declared as `int`)\n    def method_member(self) -> int: ...  # fine: a method definition using `def` is considered a declaration\n    c = \"some variable\"                  # error: no explicit declaration, leading to ambiguity\n    b = method_member                    # error: no explicit declaration, leading to ambiguity\n\n    # error: this creates implicit assignments of `d` and `e` in the protocol class body.\n    # Were they really meant to be considered protocol members?\n    for d, e in enumerate(range(42)):\n        pass\n\nclass SubProto(BaseProto, Protocol):\n    a = 42  # fine (declared in superclass)\n```\n\n## `assert-type-unspellable-subtype`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.14\">0.0.14</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22assert-type-unspellable-subtype%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2457\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for `assert_type()` calls where the actual type\nis an unspellable subtype of the asserted type.\n\n**Why is this bad?**\n\n`assert_type()` is intended to ensure that the inferred type of a value\nis exactly the same as the asserted type. But in some situations, ty\nhas nonstandard extensions to the type system that allow it to infer\nmore precise types than can be expressed in user annotations. ty emits a\ndifferent error code to [`type-assertion-failure`](#type-assertion-failure) in these situations so\nthat users can easily differentiate between the two cases.\n\n**Example**\n\n\n```python\ndef _(x: int):\n    assert_type(x, int)  # fine\n    if x:\n        assert_type(x, int)  # error: [assert-type-unspellable-subtype]\n                             # the actual type is `int & ~AlwaysFalsy`,\n                             # which excludes types like `Literal[0]`\n```\n\n## `byte-string-type-annotation`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22byte-string-type-annotation%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fstring_annotation.rs#L37\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for byte-strings in type annotation positions.\n\n**Why is this bad?**\n\nStatic analysis tools like ty can't analyze type annotations that use byte-string notation.\n\n**Examples**\n\n```python\ndef test(): -> b\"int\":\n    ...\n```\n\nUse instead:\n```python\ndef test(): -> \"int\":\n    ...\n```\n\n## `call-abstract-method`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nPreview (since <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.16\">0.0.16</a>) ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22call-abstract-method%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2356\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for calls to abstract `@classmethod`s or `@staticmethod`s\nwith \"trivial bodies\" when accessed on the class object itself.\n\n\"Trivial bodies\" are bodies that solely consist of `...`, `pass`,\na docstring, and/or `raise NotImplementedError`.\n\n**Why is this bad?**\n\nAn abstract method with a trivial body has no concrete implementation\nto execute, so calling such a method directly on the class will probably\nnot have the desired effect.\n\nIt is also unsound to call these methods directly on the class. Unlike\nother methods, ty permits abstract methods with trivial bodies to have\nnon-`None` return types even though they always return `None` at runtime.\nThis is because it is expected that these methods will always be\noverridden rather than being called directly. As a result of this\nexception to the normal rule, ty may infer an incorrect type if one of\nthese methods is called directly, which may then mean that type errors\nelsewhere in your code go undetected by ty.\n\nCalling abstract classmethods or staticmethods via `type[X]` is allowed,\nsince the actual runtime type could be a concrete subclass with an implementation.\n\n**Example**\n\n```python\nfrom abc import ABC, abstractmethod\n\nclass Foo(ABC):\n    @classmethod\n    @abstractmethod\n    def method(cls) -> int: ...\n\nFoo.method()  # Error: cannot call abstract classmethod\n```\n\n## `call-non-callable`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22call-non-callable%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L170\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for calls to non-callable objects.\n\n**Why is this bad?**\n\nCalling a non-callable object will raise a `TypeError` at runtime.\n\n**Examples**\n\n```python\n4()  # TypeError: 'int' object is not callable\n```\n\n## `call-top-callable`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.7\">0.0.7</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22call-top-callable%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L188\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for calls to objects typed as `Top[Callable[..., T]]` (the infinite union of all\ncallable types with return type `T`).\n\n**Why is this bad?**\n\nWhen an object is narrowed to `Top[Callable[..., object]]` (e.g., via `callable(x)` or\n`isinstance(x, Callable)`), we know the object is callable, but we don't know its\nprecise signature. This type represents the set of all possible callable types\n(including, e.g., functions that take no arguments and functions that require arguments),\nso no specific set of arguments can be guaranteed to be valid.\n\n**Examples**\n\n```python\ndef f(x: object):\n    if callable(x):\n        x()  # error: We know `x` is callable, but not what arguments it accepts\n```\n\n## `conflicting-argument-forms`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22conflicting-argument-forms%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L239\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks whether an argument is used as both a value and a type form in a call.\n\n**Why is this bad?**\n\nSuch calls have confusing semantics and often indicate a logic error.\n\n**Examples**\n\n```python\nfrom typing import reveal_type\nfrom ty_extensions import is_singleton\n\nif flag:\n    f = repr  # Expects a value\nelse:\n    f = is_singleton  # Expects a type form\n\nf(int)  # error\n```\n\n## `conflicting-declarations`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22conflicting-declarations%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L265\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks whether a variable has been declared as two conflicting types.\n\n**Why is this bad**\n\nA variable with two conflicting declarations likely indicates a mistake.\nMoreover, it could lead to incorrect or ill-defined type inference for\nother code that relies on these variables.\n\n**Examples**\n\n```python\nif b:\n    a: int\nelse:\n    a: str\n\na = 1\n```\n\n## `conflicting-metaclass`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22conflicting-metaclass%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L290\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for class definitions where the metaclass of the class\nbeing created would not be a subclass of the metaclasses of\nall the class's bases.\n\n**Why is it bad?**\n\nSuch a class definition raises a `TypeError` at runtime.\n\n**Examples**\n\n```python\nclass M1(type): ...\nclass M2(type): ...\nclass A(metaclass=M1): ...\nclass B(metaclass=M2): ...\n\n# TypeError: metaclass conflict\nclass C(A, B): ...\n```\n\n## `cyclic-class-definition`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22cyclic-class-definition%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L316\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for class definitions in stub files that inherit\n(directly or indirectly) from themselves.\n\n**Why is it bad?**\n\nAlthough forward references are natively supported in stub files,\ninheritance cycles are still disallowed, as it is impossible to\nresolve a consistent [method resolution order] for a class that\ninherits from itself.\n\n**Examples**\n\n```python\n# foo.pyi\nclass A(B): ...\nclass B(A): ...\n```\n\n[method resolution order]: https://docs.python.org/3/glossary.html#term-method-resolution-order\n\n## `cyclic-type-alias-definition`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.29\">0.0.1-alpha.29</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22cyclic-type-alias-definition%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L342\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for type alias definitions that (directly or mutually) refer to themselves.\n\n**Why is it bad?**\n\nAlthough it is permitted to define a recursive type alias, it is not meaningful\nto have a type alias whose expansion can only result in itself, and is therefore not allowed.\n\n**Examples**\n\n```python\ntype Itself = Itself\n\ntype A = B\ntype B = A\n```\n\n## `dataclass-field-order`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.15\">0.0.15</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22dataclass-field-order%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L460\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for dataclass definitions where required fields are defined after\nfields with default values.\n\n**Why is this bad?**\n\nIn dataclasses, all required fields (fields without default values) must be\ndefined before fields with default values. This is a Python requirement that\nwill raise a `TypeError` at runtime if violated.\n\n**Example**\n\n```python\nfrom dataclasses import dataclass\n\n@dataclass\nclass Example:\n    x: int = 1    # Field with default value\n    y: str        # Error: Required field after field with default\n```\n\n## `deprecated`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'warn'.\"><code>warn</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.16\">0.0.1-alpha.16</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22deprecated%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L386\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for uses of deprecated items\n\n**Why is this bad?**\n\nDeprecated items should no longer be used.\n\n**Examples**\n\n```python\n@warnings.deprecated(\"use new_func instead\")\ndef old_func(): ...\n\nold_func()  # emits [deprecated] diagnostic\n```\n\n## `division-by-zero`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'ignore'.\"><code>ignore</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22division-by-zero%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L364\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nIt detects division by zero.\n\n**Why is this bad?**\n\nDividing by zero raises a `ZeroDivisionError` at runtime.\n\n**Rule status**\n\nThis rule is currently disabled by default because of the number of\nfalse positives it can produce.\n\n**Examples**\n\n```python\n5 / 0\n```\n\n## `duplicate-base`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22duplicate-base%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L407\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for class definitions with duplicate bases.\n\n**Why is this bad?**\n\nClass definitions with duplicate bases raise `TypeError` at runtime.\n\n**Examples**\n\n```python\nclass A: ...\n\n# TypeError: duplicate base class\nclass B(A, A): ...\n```\n\n## `duplicate-kw-only`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.12\">0.0.1-alpha.12</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22duplicate-kw-only%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L428\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for dataclass definitions with more than one field\nannotated with `KW_ONLY`.\n\n**Why is this bad?**\n\n`dataclasses.KW_ONLY` is a special marker used to\nemulate the `*` syntax in normal signatures.\nIt can only be used once per dataclass.\n\nAttempting to annotate two different fields with\nit will lead to a runtime error.\n\n**Examples**\n\n```python\nfrom dataclasses import dataclass, KW_ONLY\n\n@dataclass\nclass A:  # Crash at runtime\n    b: int\n    _1: KW_ONLY\n    c: str\n    _2: KW_ONLY\n    d: bytes\n```\n\n## `empty-body`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.14\">0.0.14</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22empty-body%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L943\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nDetects functions with empty bodies that have a non-`None` return type annotation.\n\nThe errors reported by this rule have the same motivation as the [`invalid-return-type`](#invalid-return-type)\nrule. The diagnostic exists as a separate error code to allow users to disable this\nrule while prototyping code. While we strongly recommend enabling this rule if\npossible, users migrating from other type checkers may also find it useful to\ntemporarily disable this rule on some or all of their codebase if they find it\nresults in a large number of diagnostics.\n\n**Why is this bad?**\n\nA function with an empty body (containing only `...`, `pass`, or a docstring) will\nimplicitly return `None` at runtime. Returning `None` when the return type is non-`None`\nis unsound, and will lead to ty inferring incorrect types elsewhere.\n\nFunctions with empty bodies are permitted in certain contexts where they serve as\ndeclarations rather than implementations:\n\n- Functions in stub files (`.pyi`)\n- Methods in Protocol classes\n- Abstract methods decorated with `@abstractmethod`\n- Overload declarations decorated with `@overload`\n- Functions in `if TYPE_CHECKING` blocks\n\n**Examples**\n\n```python\ndef foo() -> int: ...  # error: [empty-body]\n\ndef bar() -> str:\n    \"\"\"A function that does nothing.\"\"\"\n    pass  # error: [empty-body]\n```\n\n## `escape-character-in-forward-annotation`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22escape-character-in-forward-annotation%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fstring_annotation.rs#L155\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for forward annotations that contain escape characters.\n\n**Why is this bad?**\n\nStatic analysis tools like ty can't analyze type annotations that contain escape characters.\n\n**Example**\n\n\n```python\ndef foo() -> \"intt\\b\": ...\n```\n\n## `final-on-non-method`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.20\">0.0.20</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22final-on-non-method%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2268\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for `@final` decorators applied to non-method functions.\n\n**Why is this bad?**\n\nThe `@final` decorator is only meaningful on methods and classes.\nApplying it to a module-level function or a nested function has no\neffect and is likely a mistake.\n\n**Example**\n\n\n```python\nfrom typing import final\n\n# Error: @final is not allowed on non-method functions\n@final\ndef my_function() -> int:\n    return 0\n```\n\n## `final-without-value`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.15\">0.0.15</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22final-without-value%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2294\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for `Final` symbols that are declared without a value and are never\nassigned a value in their scope.\n\n**Why is this bad?**\n\nA `Final` symbol must be initialized with a value at the time of declaration\nor in a subsequent assignment. At module or function scope, the assignment must\noccur in the same scope. In a class body, the assignment may occur in `__init__`.\n\n**Examples**\n\n```python\nfrom typing import Final\n\n# Error: `Final` symbol without a value\nMY_CONSTANT: Final[int]\n\n# OK: `Final` symbol with a value\nMY_CONSTANT: Final[int] = 1\n```\n\n## `fstring-type-annotation`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22fstring-type-annotation%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fstring_annotation.rs#L12\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for f-strings in type annotation positions.\n\n**Why is this bad?**\n\nStatic analysis tools like ty can't analyze type annotations that use f-string notation.\n\n**Examples**\n\n```python\ndef test(): -> f\"int\":\n    ...\n```\n\nUse instead:\n```python\ndef test(): -> \"int\":\n    ...\n```\n\n## `ignore-comment-unknown-rule`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'warn'.\"><code>warn</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22ignore-comment-unknown-rule%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Fsuppression.rs#L84\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for `ty: ignore[code]` where `code` isn't a known lint rule.\n\n**Why is this bad?**\n\nA `ty: ignore[code]` directive with a `code` that doesn't match\nany known rule will not suppress any type errors, and is probably a mistake.\n\n**Examples**\n\n```py\na = 20 / 0  # ty: ignore[division-by-zer]\n```\n\nUse instead:\n\n```py\na = 20 / 0  # ty: ignore[division-by-zero]\n```\n\n## `implicit-concatenated-string-type-annotation`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22implicit-concatenated-string-type-annotation%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fstring_annotation.rs#L87\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for implicit concatenated strings in type annotation positions.\n\n**Why is this bad?**\n\nStatic analysis tools like ty can't analyze type annotations that use implicit concatenated strings.\n\n**Examples**\n\n```python\ndef test(): -> \"Literal[\" \"5\" \"]\":\n    ...\n```\n\nUse instead:\n```python\ndef test(): -> \"Literal[5]\":\n    ...\n```\n\n## `inconsistent-mro`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22inconsistent-mro%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L737\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for classes with an inconsistent [method resolution order] (MRO).\n\n**Why is this bad?**\n\nClasses with an inconsistent MRO will raise a `TypeError` at runtime.\n\n**Examples**\n\n```python\nclass A: ...\nclass B(A): ...\n\n# TypeError: Cannot create a consistent method resolution order\nclass C(A, B): ...\n```\n\n[method resolution order]: https://docs.python.org/3/glossary.html#term-method-resolution-order\n\n## `index-out-of-bounds`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22index-out-of-bounds%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L761\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for attempts to use an out of bounds index to get an item from\na container.\n\n**Why is this bad?**\n\nUsing an out of bounds index will raise an `IndexError` at runtime.\n\n**Examples**\n\n```python\nt = (0, 1, 2)\nt[3]  # IndexError: tuple index out of range\n```\n\n## `ineffective-final`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'warn'.\"><code>warn</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.33\">0.0.1-alpha.33</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22ineffective-final%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2240\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for calls to `final()` that type checkers cannot interpret.\n\n**Why is this bad?**\n\nThe `final()` function is designed to be used as a decorator. When called directly\nas a function (e.g., `final(type(...))`), type checkers will not understand the\napplication of `final` and will not prevent subclassing.\n\n**Example**\n\n\n```python\nfrom typing import final\n\n# Incorrect: type checkers will not prevent subclassing\nMyClass = final(type(\"MyClass\", (), {}))\n\n# Correct: use `final` as a decorator\n@final\nclass MyClass: ...\n```\n\n## `instance-layout-conflict`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.12\">0.0.1-alpha.12</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22instance-layout-conflict%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L543\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for classes definitions which will fail at runtime due to\n\"instance memory layout conflicts\".\n\nThis error is usually caused by attempting to combine multiple classes\nthat define non-empty `__slots__` in a class's [Method Resolution Order]\n(MRO), or by attempting to combine multiple builtin classes in a class's\nMRO.\n\n**Why is this bad?**\n\nInheriting from bases with conflicting instance memory layouts\nwill lead to a `TypeError` at runtime.\n\nAn instance memory layout conflict occurs when CPython cannot determine\nthe memory layout instances of a class should have, because the instance\nmemory layout of one of its bases conflicts with the instance memory layout\nof one or more of its other bases.\n\nFor example, if a Python class defines non-empty `__slots__`, this will\nimpact the memory layout of instances of that class. Multiple inheritance\nfrom more than one different class defining non-empty `__slots__` is not\nallowed:\n\n```python\nclass A:\n    __slots__ = (\"a\", \"b\")\n\nclass B:\n    __slots__ = (\"a\", \"b\")  # Even if the values are the same\n\n# TypeError: multiple bases have instance lay-out conflict\nclass C(A, B): ...\n```\n\nAn instance layout conflict can also be caused by attempting to use\nmultiple inheritance with two builtin classes, due to the way that these\nclasses are implemented in a CPython C extension:\n\n```python\nclass A(int, float): ...  # TypeError: multiple bases have instance lay-out conflict\n```\n\nNote that pure-Python classes with no `__slots__`, or pure-Python classes\nwith empty `__slots__`, are always compatible:\n\n```python\nclass A: ...\nclass B:\n    __slots__ = ()\nclass C:\n    __slots__ = (\"a\", \"b\")\n\n# fine\nclass D(A, B, C): ...\n```\n\n**Known problems**\n\nClasses that have \"dynamic\" definitions of `__slots__` (definitions do not consist\nof string literals, or tuples of string literals) are not currently considered disjoint\nbases by ty.\n\nAdditionally, this check is not exhaustive: many C extensions (including several in\nthe standard library) define classes that use extended memory layouts and thus cannot\ncoexist in a single MRO. Since it is currently not possible to represent this fact in\nstub files, having a full knowledge of these classes is also impossible. When it comes\nto classes that do not define `__slots__` at the Python level, therefore, ty, currently\nonly hard-codes a number of cases where it knows that a class will produce instances with\nan atypical memory layout.\n\n**Further reading**\n\n- [CPython documentation: `__slots__`](https://docs.python.org/3/reference/datamodel.html#slots)\n- [CPython documentation: Method Resolution Order](https://docs.python.org/3/glossary.html#term-method-resolution-order)\n\n[Method Resolution Order]: https://docs.python.org/3/glossary.html#term-method-resolution-order\n\n## `invalid-argument-type`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-argument-type%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L899\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nDetects call arguments whose type is not assignable to the corresponding typed parameter.\n\n**Why is this bad?**\n\nPassing an argument of a type the function (or callable object) does not accept violates\nthe expectations of the function author and may cause unexpected runtime errors within the\nbody of the function.\n\n**Examples**\n\n```python\ndef func(x: int): ...\nfunc(\"foo\")  # error: [invalid-argument-type]\n```\n\n## `invalid-assignment`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-assignment%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L983\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for assignments where the type of the value\nis not [assignable to] the type of the assignee.\n\n**Why is this bad?**\n\nSuch assignments break the rules of the type system and\nweaken a type checker's ability to accurately reason about your code.\n\n**Examples**\n\n```python\na: int = ''\n```\n\n[assignable to]: https://typing.python.org/en/latest/spec/glossary.html#term-assignable\n\n## `invalid-attribute-access`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-attribute-access%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2786\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for assignments to class variables from instances\nand assignments to instance variables from its class.\n\n**Why is this bad?**\n\nIncorrect assignments break the rules of the type system and\nweaken a type checker's ability to accurately reason about your code.\n\n**Examples**\n\n```python\nclass C:\n    class_var: ClassVar[int] = 1\n    instance_var: int\n\nC.class_var = 3  # okay\nC().class_var = 3  # error: Cannot assign to class variable\n\nC().instance_var = 3  # okay\nC.instance_var = 3  # error: Cannot assign to instance variable\n```\n\n## `invalid-await`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.19\">0.0.1-alpha.19</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-await%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1005\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for `await` being used with types that are not [Awaitable].\n\n**Why is this bad?**\n\nSuch expressions will lead to `TypeError` being raised at runtime.\n\n**Examples**\n\n```python\nimport asyncio\n\nclass InvalidAwait:\n    def __await__(self) -> int:\n        return 5\n\nasync def main() -> None:\n    await InvalidAwait()  # error: [invalid-await]\n    await 42  # error: [invalid-await]\n\nasyncio.run(main())\n```\n\n[Awaitable]: https://docs.python.org/3/library/collections.abc.html#collections.abc.Awaitable\n\n## `invalid-base`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-base%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1035\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for class definitions that have bases which are not instances of `type`.\n\n**Why is this bad?**\n\nClass definitions with bases like this will lead to `TypeError` being raised at runtime.\n\n**Examples**\n\n```python\nclass A(42): ...  # error: [invalid-base]\n```\n\n## `invalid-context-manager`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-context-manager%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1119\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for expressions used in `with` statements\nthat do not implement the context manager protocol.\n\n**Why is this bad?**\n\nSuch a statement will raise `TypeError` at runtime.\n\n**Examples**\n\n```python\n# TypeError: 'int' object does not support the context manager protocol\nwith 1:\n    print(2)\n```\n\n## `invalid-dataclass`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.12\">0.0.12</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-dataclass%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L512\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for invalid applications of the `@dataclass` decorator.\n\n**Why is this bad?**\n\nApplying `@dataclass` to a class that inherits from `NamedTuple`, `TypedDict`,\n`Enum`, or `Protocol` is invalid:\n\n- `NamedTuple` and `TypedDict` classes will raise an exception at runtime when\n  instantiating the class.\n- `Enum` classes with `@dataclass` are [explicitly not supported].\n- `Protocol` classes define interfaces and cannot be instantiated.\n\n**Examples**\n\n```python\nfrom dataclasses import dataclass\nfrom typing import NamedTuple\n\n@dataclass  # error: [invalid-dataclass]\nclass Foo(NamedTuple):\n    x: int\n```\n\n[explicitly not supported]: https://docs.python.org/3/howto/enum.html#dataclass-support\n\n## `invalid-dataclass-override`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.13\">0.0.13</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-dataclass-override%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L486\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for dataclass definitions that have both `frozen=True` and a custom `__setattr__` or\n`__delattr__` method defined.\n\n**Why is this bad?**\n\nFrozen dataclasses synthesize `__setattr__` and `__delattr__` methods which raise a\n`FrozenInstanceError` to emulate immutability.\n\nOverriding either of these methods raises a runtime error.\n\n**Examples**\n\n```python\nfrom dataclasses import dataclass\n\n@dataclass(frozen=True)\nclass A:\n    def __setattr__(self, name: str, value: object) -> None: ...\n```\n\n## `invalid-declaration`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-declaration%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1140\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for declarations where the inferred type of an existing symbol\nis not [assignable to] its post-hoc declared type.\n\n**Why is this bad?**\n\nSuch declarations break the rules of the type system and\nweaken a type checker's ability to accurately reason about your code.\n\n**Examples**\n\n```python\na = 1\na: str\n```\n\n[assignable to]: https://typing.python.org/en/latest/spec/glossary.html#term-assignable\n\n## `invalid-enum-member-annotation`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'warn'.\"><code>warn</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.20\">0.0.20</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-enum-member-annotation%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1199\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for enum members that have explicit type annotations.\n\n**Why is this bad?**\n\nThe [typing spec] states that type checkers should infer a literal type\nfor all enum members. An explicit type annotation on an enum member is\nmisleading because the annotated type will be incorrect — the actual\nruntime type is the enum class itself, not the annotated type.\n\nIn CPython's `enum` module, annotated assignments with values are still\ntreated as members at runtime, but the annotation will confuse readers of the code.\n\n**Examples**\n\n```python\nfrom enum import Enum\n\nclass Pet(Enum):\n    CAT = 1       # OK\n    DOG: int = 2  # Error: enum members should not be annotated\n```\n\nUse instead:\n```python\nfrom enum import Enum\n\nclass Pet(Enum):\n    CAT = 1\n    DOG = 2\n```\n\n**References**\n\n- [Typing spec: Enum members](https://typing.python.org/en/latest/spec/enums.html#enum-members)\n\n[typing spec]: https://typing.python.org/en/latest/spec/enums.html#enum-members\n\n## `invalid-exception-caught`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-exception-caught%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1163\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for exception handlers that catch non-exception classes.\n\n**Why is this bad?**\n\nCatching classes that do not inherit from `BaseException` will raise a `TypeError` at runtime.\n\n**Example**\n\n```python\ntry:\n    1 / 0\nexcept 1:\n    ...\n```\n\nUse instead:\n```python\ntry:\n    1 / 0\nexcept ZeroDivisionError:\n    ...\n```\n\n**References**\n\n- [Python documentation: except clause](https://docs.python.org/3/reference/compound_stmts.html#except-clause)\n- [Python documentation: Built-in Exceptions](https://docs.python.org/3/library/exceptions.html#built-in-exceptions)\n\n**Ruff rule**\n\n This rule corresponds to Ruff's [`except-with-non-exception-classes` (`B030`)](https://docs.astral.sh/ruff/rules/except-with-non-exception-classes)\n\n## `invalid-explicit-override`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.28\">0.0.1-alpha.28</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-explicit-override%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2399\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for methods that are decorated with `@override` but do not override any method in a superclass.\n\n**Why is this bad?**\n\nDecorating a method with `@override` declares to the type checker that the intention is that it should\noverride a method from a superclass.\n\n**Example**\n\n\n```python\nfrom typing import override\n\nclass A:\n    @override\n    def foo(self): ...  # Error raised here\n\nclass B(A):\n    @override\n    def ffooo(self): ...  # Error raised here\n\nclass C:\n    @override\n    def __repr__(self): ...  # fine: overrides `object.__repr__`\n\nclass D(A):\n    @override\n    def foo(self): ...  # fine: overrides `A.foo`\n```\n\n## `invalid-frozen-dataclass-subclass`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.35\">0.0.1-alpha.35</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-frozen-dataclass-subclass%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L3119\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for dataclasses with invalid frozen inheritance:\n- A frozen dataclass cannot inherit from a non-frozen dataclass.\n- A non-frozen dataclass cannot inherit from a frozen dataclass.\n\n**Why is this bad?**\n\nPython raises a `TypeError` at runtime when either of these inheritance\npatterns occurs.\n\n**Example**\n\n\n```python\nfrom dataclasses import dataclass\n\n@dataclass\nclass Base:\n    x: int\n\n@dataclass(frozen=True)\nclass Child(Base):  # Error raised here\n    y: int\n\n@dataclass(frozen=True)\nclass FrozenBase:\n    x: int\n\n@dataclass\nclass NonFrozenChild(FrozenBase):  # Error raised here\n    y: int\n```\n\n## `invalid-generic-class`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-generic-class%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1283\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for the creation of invalid generic classes\n\n**Why is this bad?**\n\nThere are several requirements that you must follow when defining a generic class.\nMany of these result in `TypeError` being raised at runtime if they are violated.\n\n**Examples**\n\n```python\nfrom typing_extensions import Generic, TypeVar\n\nT = TypeVar(\"T\")\nU = TypeVar(\"U\", default=int)\n\n# error: class uses both PEP-695 syntax and legacy syntax\nclass C[U](Generic[T]): ...\n\n# error: type parameter with default comes before type parameter without default\nclass D(Generic[U, T]): ...\n```\n\n**References**\n\n- [Typing spec: Generics](https://typing.python.org/en/latest/spec/generics.html#introduction)\n\n## `invalid-generic-enum`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.12\">0.0.12</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-generic-enum%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1241\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for enum classes that are also generic.\n\n**Why is this bad?**\n\nEnum classes cannot be generic. Python does not support generic enums:\nattempting to create one will either result in an immediate `TypeError`\nat runtime, or will create a class that cannot be specialized in the way\nthat a normal generic class can.\n\n**Examples**\n\n```python\nfrom enum import Enum\nfrom typing import Generic, TypeVar\n\nT = TypeVar(\"T\")\n\n# error: enum class cannot be generic (class creation fails with `TypeError`)\nclass E[T](Enum):\n    A = 1\n\n# error: enum class cannot be generic (class creation fails with `TypeError`)\nclass F(Enum, Generic[T]):\n    A = 1\n\n# error: enum class cannot be generic -- the class creation does not immediately fail...\nclass G(Generic[T], Enum):\n    A = 1\n\n# ...but this raises `KeyError`:\nx: G[int]\n```\n\n**References**\n\n- [Python documentation: Enum](https://docs.python.org/3/library/enum.html)\n\n## `invalid-ignore-comment`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'warn'.\"><code>warn</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-ignore-comment%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Fsuppression.rs#L109\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for `type: ignore` and `ty: ignore` comments that are syntactically incorrect.\n\n**Why is this bad?**\n\nA syntactically incorrect ignore comment is probably a mistake and is useless.\n\n**Examples**\n\n```py\na = 20 / 0  # type: ignoree\n```\n\nUse instead:\n\n```py\na = 20 / 0  # type: ignore\n```\n\n## `invalid-key`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.17\">0.0.1-alpha.17</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-key%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L782\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for subscript accesses with invalid keys and `TypedDict` construction with an\nunknown key.\n\n**Why is this bad?**\n\nSubscripting with an invalid key will raise a `KeyError` at runtime.\n\nCreating a `TypedDict` with an unknown key is likely a mistake; if the `TypedDict` is\n`closed=true` it also violates the expectations of the type.\n\n**Examples**\n\n```python\nfrom typing import TypedDict\n\nclass Person(TypedDict):\n    name: str\n    age: int\n\nalice = Person(name=\"Alice\", age=30)\nalice[\"height\"]  # KeyError: 'height'\n\nbob: Person = { \"namee\": \"Bob\", \"age\": 30 }  # typo!\n\ncarol = Person(name=\"Carol\", aeg=25)  # typo!\n```\n\n## `invalid-legacy-positional-parameter`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'warn'.\"><code>warn</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.15\">0.0.15</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-legacy-positional-parameter%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L3197\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\n\nChecks for parameters that appear to be attempting to use the legacy convention\nto specify that a parameter is positional-only, but do so incorrectly.\n\nThe \"legacy convention\" for specifying positional-only parameters was\nspecified in [PEP 484]. It states that parameters with names starting with\n`__` should be considered positional-only by type checkers. [PEP 570], introduced\nin Python 3.8, added dedicated syntax for specifying positional-only parameters,\nrendering the legacy convention obsolete. However, some codebases may still\nuse the legacy convention for compatibility with older Python versions.\n\n**Why is this bad?**\n\n\nIn most cases, a type checker will not consider a parameter to be positional-only\nif it comes after a positional-or-keyword parameter, even if its name starts with\n`__`. This may be unexpected to the author of the code.\n\n**Example**\n\n\n```python\ndef f(x, __y):  # Error: `__y` is not considered positional-only\n    pass\n```\n\nUse instead:\n\n```python\ndef f(__x, __y):  # If you need compatibility with Python <=3.7\n    pass\n```\n\nor:\n\n```python\ndef f(x, y, /):  # Python 3.8+ syntax\n    pass\n```\n\n**References**\n\n\n- [Typing spec: positional-only parameters (legacy syntax)](https://typing.python.org/en/latest/spec/historical.html#pos-only-double-underscore)\n- [Python glossary: parameters](https://docs.python.org/3/glossary.html#term-parameter)\n\n[PEP 484]: https://peps.python.org/pep-0484/#positional-only-arguments\n[PEP 570]: https://peps.python.org/pep-0570/\n\n## `invalid-legacy-type-variable`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-legacy-type-variable%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1314\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for the creation of invalid legacy `TypeVar`s\n\n**Why is this bad?**\n\nThere are several requirements that you must follow when creating a legacy `TypeVar`.\n\n**Examples**\n\n```python\nfrom typing import TypeVar\n\nT = TypeVar(\"T\")  # okay\nQ = TypeVar(\"S\")  # error: TypeVar name must match the variable it's assigned to\nT = TypeVar(\"T\")  # error: TypeVars should not be redefined\n\n# error: TypeVar must be immediately assigned to a variable\ndef f(t: TypeVar(\"U\")): ...\n```\n\n**References**\n\n- [Typing spec: Generics](https://typing.python.org/en/latest/spec/generics.html#introduction)\n\n## `invalid-match-pattern`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.18\">0.0.18</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-match-pattern%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1687\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for invalid match patterns.\n\n**Why is this bad?**\n\nMatching on invalid patterns will lead to a runtime error.\n\n**Examples**\n\n```python\nNotAClass = 42\n\nmatch x:\n    case NotAClass():    # TypeError at runtime: must be a class\n        ...\n```\n\n## `invalid-metaclass`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-metaclass%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1411\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for arguments to `metaclass=` that are invalid.\n\n**Why is this bad?**\n\nPython allows arbitrary expressions to be used as the argument to `metaclass=`.\nThese expressions, however, need to be callable and accept the same arguments\nas `type.__new__`.\n\n**Example**\n\n\n```python\ndef f(): ...\n\n# TypeError: f() takes 0 positional arguments but 3 were given\nclass B(metaclass=f): ...\n```\n\n**References**\n\n- [Python documentation: Metaclasses](https://docs.python.org/3/reference/datamodel.html#metaclasses)\n\n## `invalid-method-override`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.20\">0.0.1-alpha.20</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-method-override%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L3021\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nDetects method overrides that violate the [Liskov Substitution Principle] (\"LSP\").\n\nThe LSP states that an instance of a subtype should be substitutable for an instance of its supertype.\nApplied to Python, this means:\n1. All argument combinations a superclass method accepts\n   must also be accepted by an overriding subclass method.\n2. The return type of an overriding subclass method must be a subtype\n   of the return type of the superclass method.\n\n**Why is this bad?**\n\nViolating the Liskov Substitution Principle will lead to many of ty's assumptions and\ninferences being incorrect, which will mean that it will fail to catch many possible\ntype errors in your code.\n\n**Example**\n\n```python\nclass Super:\n    def method(self, x) -> int:\n        return 42\n\nclass Sub(Super):\n    # Liskov violation: `str` is not a subtype of `int`,\n    # but the supertype method promises to return an `int`.\n    def method(self, x) -> str:  # error: [invalid-override]\n        return \"foo\"\n\ndef accepts_super(s: Super) -> int:\n    return s.method(x=42)\n\naccepts_super(Sub())  # The result of this call is a string, but ty will infer\n                      # it to be an `int` due to the violation of the Liskov Substitution Principle.\n\nclass Sub2(Super):\n    # Liskov violation: the superclass method can be called with a `x=`\n    # keyword argument, but the subclass method does not accept it.\n    def method(self, y) -> int:  # error: [invalid-override]\n       return 42\n\naccepts_super(Sub2())  # TypeError at runtime: method() got an unexpected keyword argument 'x'\n                       # ty cannot catch this error due to the violation of the Liskov Substitution Principle.\n```\n\n**Common issues**\n\n\n**Why does ty complain about my `__eq__` method?**\n\n\n`__eq__` and `__ne__` methods in Python are generally expected to accept arbitrary\nobjects as their second argument, for example:\n\n```python\nclass A:\n    x: int\n\n    def __eq__(self, other: object) -> bool:\n        # gracefully handle an object of an unexpected type\n        # without raising an exception\n        if not isinstance(other, A):\n            return False\n        return self.x == other.x\n```\n\nIf `A.__eq__` here were annotated as only accepting `A` instances for its second argument,\nit would imply that you wouldn't be able to use `==` between instances of `A` and\ninstances of unrelated classes without an exception possibly being raised. While some\nclasses in Python do indeed behave this way, the strongly held convention is that it should\nbe avoided wherever possible. As part of this check, therefore, ty enforces that `__eq__`\nand `__ne__` methods accept `object` as their second argument.\n\n**Why does ty disagree with Ruff about how to write my method?**\n\n\nRuff has several rules that will encourage you to rename a parameter, or change its type\nsignature, if it thinks you're falling into a certain anti-pattern. For example, Ruff's\n[ARG002](https://docs.astral.sh/ruff/rules/unused-method-argument/) rule recommends that an\nunused parameter should either be removed or renamed to start with `_`. Applying either of\nthese suggestions can cause ty to start reporting an [`invalid-method-override`](#invalid-method-override) error if\nthe function in question is a method on a subclass that overrides a method on a superclass,\nand the change would cause the subclass method to no longer accept all argument combinations\nthat the superclass method accepts.\n\nThis can usually be resolved by adding [`@typing.override`][override] to your method\ndefinition. Ruff knows that a method decorated with `@typing.override` is intended to\noverride a method by the same name on a superclass, and avoids reporting rules like ARG002\nfor such methods; it knows that the changes recommended by ARG002 would violate the Liskov\nSubstitution Principle.\n\nCorrect use of `@override` is enforced by ty's [`invalid-explicit-override`](#invalid-explicit-override) rule.\n\n[Liskov Substitution Principle]: https://en.wikipedia.org/wiki/Liskov_substitution_principle\n[override]: https://docs.python.org/3/library/typing.html#typing.override\n\n## `invalid-named-tuple`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.19\">0.0.1-alpha.19</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-named-tuple%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L689\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for invalidly defined `NamedTuple` classes.\n\n**Why is this bad?**\n\nAn invalidly defined `NamedTuple` class may lead to the type checker\ndrawing incorrect conclusions. It may also lead to `TypeError`s or\n`AttributeError`s at runtime.\n\n**Examples**\n\nA class definition cannot combine `NamedTuple` with other base classes\nin multiple inheritance; doing so raises a `TypeError` at runtime. The sole\nexception to this rule is `Generic[]`, which can be used alongside `NamedTuple`\nin a class's bases list.\n\n```pycon\n>>> from typing import NamedTuple\n>>> class Foo(NamedTuple, object): ...\nTypeError: can only inherit from a NamedTuple type and Generic\n```\n\nFurther, `NamedTuple` field names cannot start with an underscore:\n\n```pycon\n>>> from typing import NamedTuple\n>>> class Foo(NamedTuple):\n...     _bar: int\nValueError: Field names cannot start with an underscore: '_bar'\n```\n\n`NamedTuple` classes also have certain synthesized attributes (like `_asdict`, `_make`,\n`_replace`, etc.) that cannot be overwritten. Attempting to assign to these attributes\nwithout a type annotation will raise an `AttributeError` at runtime.\n\n```pycon\n>>> from typing import NamedTuple\n>>> class Foo(NamedTuple):\n...     x: int\n...     _asdict = 42\nAttributeError: Cannot overwrite NamedTuple attribute _asdict\n```\n\n## `invalid-newtype`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.27\">0.0.1-alpha.27</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-newtype%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1387\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for the creation of invalid `NewType`s\n\n**Why is this bad?**\n\nThere are several requirements that you must follow when creating a `NewType`.\n\n**Examples**\n\n```python\nfrom typing import NewType\n\ndef get_name() -> str: ...\n\nFoo = NewType(\"Foo\", int)        # okay\nBar = NewType(get_name(), int)   # error: The first argument to `NewType` must be a string literal\nBaz = NewType(\"Baz\", int | str)  # error: invalid base for `typing.NewType`\n```\n\n## `invalid-overload`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-overload%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1438\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for various invalid `@overload` usages.\n\n**Why is this bad?**\n\nThe `@overload` decorator is used to define functions and methods that accepts different\ncombinations of arguments and return different types based on the arguments passed. This is\nmainly beneficial for type checkers. But, if the `@overload` usage is invalid, the type\nchecker may not be able to provide correct type information.\n\n**Example**\n\n\nDefining only one overload:\n\n```py\nfrom typing import overload\n\n@overload\ndef foo(x: int) -> int: ...\ndef foo(x: int | None) -> int | None:\n    return x\n```\n\nOr, not providing an implementation for the overloaded definition:\n\n```py\nfrom typing import overload\n\n@overload\ndef foo() -> None: ...\n@overload\ndef foo(x: int) -> int: ...\n```\n\n**References**\n\n- [Python documentation: `@overload`](https://docs.python.org/3/library/typing.html#typing.overload)\n\n## `invalid-parameter-default`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-parameter-default%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1537\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for default values that can't be\nassigned to the parameter's annotated type.\n\n**Why is this bad?**\n\nThis breaks the rules of the type system and\nweakens a type checker's ability to accurately reason about your code.\n\n**Examples**\n\n```python\ndef f(a: int = ''): ...\n```\n\n## `invalid-paramspec`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-paramspec%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1342\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for the creation of invalid `ParamSpec`s\n\n**Why is this bad?**\n\nThere are several requirements that you must follow when creating a `ParamSpec`.\n\n**Examples**\n\n```python\nfrom typing import ParamSpec\n\nP1 = ParamSpec(\"P1\")  # okay\nP2 = ParamSpec(\"S2\")  # error: ParamSpec name must match the variable it's assigned to\n```\n\n**References**\n\n- [Typing spec: ParamSpec](https://typing.python.org/en/latest/spec/generics.html#paramspec)\n\n## `invalid-protocol`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-protocol%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L625\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for protocol classes that will raise `TypeError` at runtime.\n\n**Why is this bad?**\n\nAn invalidly defined protocol class may lead to the type checker inferring\nunexpected things. It may also lead to `TypeError`s at runtime.\n\n**Examples**\n\nA `Protocol` class cannot inherit from a non-`Protocol` class;\nthis raises a `TypeError` at runtime:\n\n```pycon\n>>> from typing import Protocol\n>>> class Foo(int, Protocol): ...\n...\nTraceback (most recent call last):\n  File \"<python-input-1>\", line 1, in <module>\n    class Foo(int, Protocol): ...\nTypeError: Protocols can only inherit from other protocols, got <class 'int'>\n```\n\n## `invalid-raise`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-raise%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1557\" target=\"_blank\">View source</a>\n</small>\n\n\nChecks for `raise` statements that raise non-exceptions or use invalid\ncauses for their raised exceptions.\n\n**Why is this bad?**\n\nOnly subclasses or instances of `BaseException` can be raised.\nFor an exception's cause, the same rules apply, except that `None` is also\npermitted. Violating these rules results in a `TypeError` at runtime.\n\n**Examples**\n\n```python\ndef f():\n    try:\n        something()\n    except NameError:\n        raise \"oops!\" from f\n\ndef g():\n    raise NotImplemented from 42\n```\n\nUse instead:\n```python\ndef f():\n    try:\n        something()\n    except NameError as e:\n        raise RuntimeError(\"oops!\") from e\n\ndef g():\n    raise NotImplementedError from None\n```\n\n**References**\n\n- [Python documentation: The `raise` statement](https://docs.python.org/3/reference/simple_stmts.html#raise)\n- [Python documentation: Built-in Exceptions](https://docs.python.org/3/library/exceptions.html#built-in-exceptions)\n\n## `invalid-return-type`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-return-type%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L920\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nDetects returned values that can't be assigned to the function's annotated return type.\n\nNote that the special case of a function with a non-`None` return type and an empty body\nis handled by the separate [`empty-body`](#empty-body) error code.\n\n**Why is this bad?**\n\nReturning an object of a type incompatible with the annotated return type\nis unsound, and will lead to ty inferring incorrect types elsewhere.\n\n**Examples**\n\n```python\ndef func() -> int:\n    return \"a\"  # error: [invalid-return-type]\n```\n\n## `invalid-super-argument`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-super-argument%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1600\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nDetects `super()` calls where:\n- the first argument is not a valid class literal, or\n- the second argument is not an instance or subclass of the first argument.\n\n**Why is this bad?**\n\n`super(type, obj)` expects:\n- the first argument to be a class,\n- and the second argument to satisfy one of the following:\n  - `isinstance(obj, type)` is `True`\n  - `issubclass(obj, type)` is `True`\n\nViolating this relationship will raise a `TypeError` at runtime.\n\n**Examples**\n\n```python\nclass A:\n    ...\nclass B(A):\n    ...\n\nsuper(A, B())  # it's okay! `A` satisfies `isinstance(B(), A)`\n\nsuper(A(), B()) # error: `A()` is not a class\n\nsuper(B, A())  # error: `A()` does not satisfy `isinstance(A(), B)`\nsuper(B, A)  # error: `A` does not satisfy `issubclass(A, B)`\n```\n\n**References**\n\n- [Python documentation: super()](https://docs.python.org/3/library/functions.html#super)\n\n## `invalid-syntax-in-forward-annotation`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-syntax-in-forward-annotation%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fstring_annotation.rs#L112\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for string-literal annotations where the string cannot be\nparsed as a Python expression.\n\n**Why is this bad?**\n\nType annotations are expected to be Python expressions that\ndescribe the expected type of a variable, parameter, attribute or\n`return` statement.\n\nType annotations are permitted to be string-literal expressions, in\norder to enable forward references to names not yet defined.\nHowever, it must be possible to parse the contents of that string\nliteral as a normal Python expression.\n\n**Example**\n\n\n```python\ndef foo() -> \"intstance of C\":\n    return 42\n\nclass C: ...\n```\n\nUse instead:\n\n```python\ndef foo() -> \"C\":\n    return 42\n\nclass C: ...\n```\n\n**References**\n\n- [Typing spec: The meaning of annotations](https://typing.python.org/en/latest/spec/annotations.html#the-meaning-of-annotations)\n- [Typing spec: String annotations](https://typing.python.org/en/latest/spec/annotations.html#string-annotations)\n\n## `invalid-total-ordering`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.10\">0.0.10</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-total-ordering%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L3157\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for classes decorated with `@functools.total_ordering` that don't\ndefine any ordering method (`__lt__`, `__le__`, `__gt__`, or `__ge__`).\n\n**Why is this bad?**\n\nThe `@total_ordering` decorator requires the class to define at least one\nordering method. If none is defined, Python raises a `ValueError` at runtime.\n\n**Example**\n\n\n```python\nfrom functools import total_ordering\n\n@total_ordering\nclass MyClass:  # Error: no ordering method defined\n    def __eq__(self, other: object) -> bool:\n        return True\n```\n\nUse instead:\n\n```python\nfrom functools import total_ordering\n\n@total_ordering\nclass MyClass:\n    def __eq__(self, other: object) -> bool:\n        return True\n\n    def __lt__(self, other: \"MyClass\") -> bool:\n        return True\n```\n\n## `invalid-type-alias-type`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.6\">0.0.1-alpha.6</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-type-alias-type%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1366\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for the creation of invalid `TypeAliasType`s\n\n**Why is this bad?**\n\nThere are several requirements that you must follow when creating a `TypeAliasType`.\n\n**Examples**\n\n```python\nfrom typing import TypeAliasType\n\nIntOrStr = TypeAliasType(\"IntOrStr\", int | str)  # okay\nNewAlias = TypeAliasType(get_name(), int)        # error: TypeAliasType name must be a string literal\n```\n\n## `invalid-type-arguments`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.29\">0.0.1-alpha.29</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-type-arguments%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1947\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for invalid type arguments in explicit type specialization.\n\n**Why is this bad?**\n\nProviding the wrong number of type arguments or type arguments that don't\nsatisfy the type variable's bounds or constraints will lead to incorrect\ntype inference and may indicate a misunderstanding of the generic type's\ninterface.\n\n**Examples**\n\n\nUsing legacy type variables:\n```python\nfrom typing import Generic, TypeVar\n\nT1 = TypeVar('T1', int, str)\nT2 = TypeVar('T2', bound=int)\n\nclass Foo1(Generic[T1]): ...\nclass Foo2(Generic[T2]): ...\n\nFoo1[bytes]  # error: bytes does not satisfy T1's constraints\nFoo2[str]  # error: str does not satisfy T2's bound\n```\n\nUsing PEP 695 type variables:\n```python\nclass Foo[T]: ...\nclass Bar[T, U]: ...\n\nFoo[int, str]  # error: too many arguments\nBar[int]  # error: too few arguments\n```\n\n## `invalid-type-checking-constant`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-type-checking-constant%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1639\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for a value other than `False` assigned to the `TYPE_CHECKING` variable, or an\nannotation not assignable from `bool`.\n\n**Why is this bad?**\n\nThe name `TYPE_CHECKING` is reserved for a flag that can be used to provide conditional\ncode seen only by the type checker, and not at runtime. Normally this flag is imported from\n`typing` or `typing_extensions`, but it can also be defined locally. If defined locally, it\nmust be assigned the value `False` at runtime; the type checker will consider its value to\nbe `True`. If annotated, it must be annotated as a type that can accept `bool` values.\n\n**Examples**\n\n```python\nTYPE_CHECKING: str\nTYPE_CHECKING = ''\n```\n\n## `invalid-type-form`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-type-form%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1663\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for expressions that are used as [type expressions]\nbut cannot validly be interpreted as such.\n\n**Why is this bad?**\n\nSuch expressions cannot be understood by ty.\nIn some cases, they might raise errors at runtime.\n\n**Examples**\n\n```python\nfrom typing import Annotated\n\na: type[1]  # `1` is not a type\nb: Annotated[int]  # `Annotated` expects at least two arguments\n```\n[type expressions]: https://typing.python.org/en/latest/spec/annotations.html#type-and-annotation-expressions\n\n## `invalid-type-guard-call`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.11\">0.0.1-alpha.11</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-type-guard-call%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1737\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for type guard function calls without a valid target.\n\n**Why is this bad?**\n\nThe first non-keyword non-variadic argument to a type guard function\nis its target and must map to a symbol.\n\nStarred (`is_str(*a)`), literal (`is_str(42)`) and other non-symbol-like\nexpressions are invalid as narrowing targets.\n\n**Examples**\n\n```python\nfrom typing import TypeIs\n\ndef f(v: object) -> TypeIs[int]: ...\n\nf()  # Error\nf(*a)  # Error\nf(10)  # Error\n```\n\n## `invalid-type-guard-definition`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.11\">0.0.1-alpha.11</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-type-guard-definition%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1709\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for type guard functions without\na first non-self-like non-keyword-only non-variadic parameter.\n\n**Why is this bad?**\n\nType narrowing functions must accept at least one positional argument\n(non-static methods must accept another in addition to `self`/`cls`).\n\nExtra parameters/arguments are allowed but do not affect narrowing.\n\n**Examples**\n\n```python\nfrom typing import TypeIs\n\ndef f() -> TypeIs[int]: ...  # Error, no parameter\ndef f(*, v: object) -> TypeIs[int]: ...  # Error, no positional arguments allowed\ndef f(*args: object) -> TypeIs[int]: ... # Error, expect variadic arguments\nclass C:\n    def f(self) -> TypeIs[int]: ...  # Error, only positional argument expected is `self`\n```\n\n## `invalid-type-variable-bound`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.15\">0.0.15</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-type-variable-bound%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1806\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for [type variables] whose bounds reference type variables.\n\n**Why is this bad?**\n\nThe bound of a type variable must be a concrete type.\n\n**Examples**\n\n```python\nT = TypeVar('T', bound=list['T'])  # error: [invalid-type-variable-bound]\nU = TypeVar('U')\nT = TypeVar('T', bound=U)  # error: [invalid-type-variable-bound]\n\ndef f[T: list[T]](): ...  # error: [invalid-type-variable-bound]\ndef g[U, T: U](): ...  # error: [invalid-type-variable-bound]\n```\n\n[type variable]: https://docs.python.org/3/library/typing.html#typing.TypeVar\n\n## `invalid-type-variable-constraints`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-type-variable-constraints%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1765\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\n\nChecks for constrained [type variables] with only one constraint,\nor that those constraints reference type variables.\n\n**Why is this bad?**\n\n\nA constrained type variable must have at least two constraints.\n\n**Examples**\n\n\n```python\nfrom typing import TypeVar\n\nT = TypeVar('T', str)  # invalid constrained TypeVar\n\nI = TypeVar('I', bound=int)\nU = TypeVar('U', list[I], int)  # invalid constrained TypeVar\n```\n\nUse instead:\n\n```python\nT = TypeVar('T', str, int)  # valid constrained TypeVar\n\n# or\n\nT = TypeVar('T', bound=str)  # valid bound TypeVar\n\nU = TypeVar('U', list[int], int)  # valid constrained Type\n```\n\n[type variables]: https://docs.python.org/3/library/typing.html#typing.TypeVar\n\n## `invalid-type-variable-default`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.16\">0.0.16</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-type-variable-default%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1831\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for [type variables] whose default type is not compatible with\nthe type variable's bound or constraints.\n\n**Why is this bad?**\n\nIf a type variable has a bound, the default must be assignable to that\nbound (see: [bound rules]). If a type variable has constraints, the default\nmust be one of the constraints (see: [constraint rules]).\n\n**Examples**\n\n```python\nT = TypeVar(\"T\", bound=str, default=int)  # error: [invalid-type-variable-default]\nU = TypeVar(\"U\", int, str, default=bytes)  # error: [invalid-type-variable-default]\n```\n\n[type variables]: https://docs.python.org/3/library/typing.html#typing.TypeVar\n[bound rules]: https://typing.python.org/en/latest/spec/generics.html#bound-rules\n[constraint rules]: https://typing.python.org/en/latest/spec/generics.html#constraint-rules\n\n## `invalid-typed-dict-header`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.14\">0.0.14</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-typed-dict-header%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2992\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nDetects errors in `TypedDict` class headers, such as unexpected arguments\nor invalid base classes.\n\n**Why is this bad?**\n\nThe typing spec states that `TypedDict`s are not permitted to have\ncustom metaclasses. Using `**` unpacking in a `TypedDict` header\nis also prohibited by ty, as it means that ty cannot statically determine\nwhether keys in the `TypedDict` are intended to be required or optional.\n\n**Example**\n\n```python\nfrom typing import TypedDict\n\nclass Foo(TypedDict, metaclass=whatever):  # error: [invalid-typed-dict-header]\n    ...\n\ndef f(x: dict):\n    class Bar(TypedDict, **x):  # error: [invalid-typed-dict-header]\n        ...\n```\n\n## `invalid-typed-dict-statement`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.9\">0.0.9</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22invalid-typed-dict-statement%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2967\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nDetects statements other than annotated declarations in `TypedDict` class bodies.\n\n**Why is this bad?**\n\n`TypedDict` class bodies aren't allowed to contain any other types of statements. For\nexample, method definitions and field values aren't allowed. None of these will be\navailable on \"instances of the `TypedDict`\" at runtime (as `dict` is the runtime class of\nall \"`TypedDict` instances\").\n\n**Example**\n\n```python\nfrom typing import TypedDict\n\nclass Foo(TypedDict):\n    def bar(self):  # error: [invalid-typed-dict-statement]\n        pass\n```\n\n## `isinstance-against-protocol`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.14\">0.0.14</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22isinstance-against-protocol%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L815\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nReports invalid runtime checks against `Protocol` classes.\nThis includes explicit calls `isinstance()`/`issubclass()` against\nnon-runtime-checkable protocols, `issubclass()` calls against protocols\nthat have non-method members, and implicit `isinstance()` checks against\nnon-runtime-checkable protocols via pattern matching.\n\n**Why is this bad?**\n\nThese calls (implicit or explicit) raise `TypeError` at runtime.\n\n**Examples**\n\n```python\nfrom typing_extensions import Protocol, runtime_checkable\n\nclass HasX(Protocol):\n    x: int\n\n@runtime_checkable\nclass HasY(Protocol):\n    y: int\n\ndef f(arg: object, arg2: type):\n    isinstance(arg, HasX)  # error: [isinstance-against-protocol] (not runtime-checkable)\n    issubclass(arg2, HasX)  # error: [isinstance-against-protocol] (not runtime-checkable)\n\ndef g(arg: object):\n    match arg:\n        case HasX():  # error: [isinstance-against-protocol] (not runtime-checkable)\n            pass\n\ndef h(arg2: type):\n    isinstance(arg2, HasY)  # fine (runtime-checkable)\n\n    # `HasY` is runtime-checkable, but has non-method members,\n    # so it still can't be used in `issubclass` checks)\n    issubclass(arg2, HasY)  # error: [isinstance-against-protocol]\n```\n\n**References**\n\n- [Typing documentation: `@runtime_checkable`](https://docs.python.org/3/library/typing.html#typing.runtime_checkable)\n\n## `isinstance-against-typed-dict`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.15\">0.0.15</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22isinstance-against-typed-dict%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L863\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nReports runtime checks against `TypedDict` classes.\nThis includes explicit calls to `isinstance()`/`issubclass()` and implicit\nchecks performed by `match` class patterns.\n\n**Why is this bad?**\n\nUsing a `TypedDict` class in these contexts raises `TypeError` at runtime.\n\n**Examples**\n\n```python\nfrom typing_extensions import TypedDict\n\nclass Movie(TypedDict):\n    name: str\n    director: str\n\ndef f(arg: object, arg2: type):\n    isinstance(arg, Movie)  # error: [isinstance-against-typed-dict]\n    issubclass(arg2, Movie)  # error: [isinstance-against-typed-dict]\n\ndef g(arg: object):\n    match arg:\n        case Movie():  # error: [isinstance-against-typed-dict]\n            pass\n```\n\n**References**\n\n- [Typing specification: `TypedDict`](https://typing.python.org/en/latest/spec/typeddict.html)\n\n## `missing-argument`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22missing-argument%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1887\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for missing required arguments in a call.\n\n**Why is this bad?**\n\nFailing to provide a required argument will raise a `TypeError` at runtime.\n\n**Examples**\n\n```python\ndef func(x: int): ...\nfunc()  # TypeError: func() missing 1 required positional argument: 'x'\n```\n\n## `missing-typed-dict-key`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.20\">0.0.1-alpha.20</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22missing-typed-dict-key%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2940\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nDetects missing required keys in `TypedDict` constructor calls.\n\n**Why is this bad?**\n\n`TypedDict` requires all non-optional keys to be provided during construction.\nMissing items can lead to a `KeyError` at runtime.\n\n**Example**\n\n```python\nfrom typing import TypedDict\n\nclass Person(TypedDict):\n    name: str\n    age: int\n\nalice: Person = {\"name\": \"Alice\"}  # missing required key 'age'\n\nalice[\"age\"]  # KeyError\n```\n\n## `no-matching-overload`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22no-matching-overload%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1906\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for calls to an overloaded function that do not match any of the overloads.\n\n**Why is this bad?**\n\nFailing to provide the correct arguments to one of the overloads will raise a `TypeError`\nat runtime.\n\n**Examples**\n\n```python\n@overload\ndef func(x: int): ...\n@overload\ndef func(x: bool): ...\nfunc(\"string\")  # error: [no-matching-overload]\n```\n\n## `not-iterable`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22not-iterable%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1988\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for objects that are not iterable but are used in a context that requires them to be.\n\n**Why is this bad?**\n\nIterating over an object that is not iterable will raise a `TypeError` at runtime.\n\n**Examples**\n\n\n```python\nfor i in 34:  # TypeError: 'int' object is not iterable\n    pass\n```\n\n## `not-subscriptable`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22not-subscriptable%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1929\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for subscripting objects that do not support subscripting.\n\n**Why is this bad?**\n\nSubscripting an object that does not support it will raise a `TypeError` at runtime.\n\n**Examples**\n\n```python\n4[1]  # TypeError: 'int' object is not subscriptable\n```\n\n## `override-of-final-method`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.29\">0.0.1-alpha.29</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22override-of-final-method%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2186\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for methods on subclasses that override superclass methods decorated with `@final`.\n\n**Why is this bad?**\n\nDecorating a method with `@final` declares to the type checker that it should not be\noverridden on any subclass.\n\n**Example**\n\n\n```python\nfrom typing import final\n\nclass A:\n    @final\n    def foo(self): ...\n\nclass B(A):\n    def foo(self): ...  # Error raised here\n```\n\n## `override-of-final-variable`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.16\">0.0.16</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22override-of-final-variable%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2213\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for class variables on subclasses that override a superclass variable\nthat has been declared as `Final`.\n\n**Why is this bad?**\n\nDeclaring a variable as `Final` indicates to the type checker that it should not be\noverridden on any subclass.\n\n**Example**\n\n\n```python\nfrom typing import Final\n\nclass A:\n    X: Final[int] = 1\n\nclass B(A):\n    X = 2  # Error raised here\n```\n\n## `parameter-already-assigned`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22parameter-already-assigned%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2039\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for calls which provide more than one argument for a single parameter.\n\n**Why is this bad?**\n\nProviding multiple values for a single parameter will raise a `TypeError` at runtime.\n\n**Examples**\n\n\n```python\ndef f(x: int) -> int: ...\n\nf(1, x=2)  # Error raised here\n```\n\n## `positional-only-parameter-as-kwarg`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.22\">0.0.1-alpha.22</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22positional-only-parameter-as-kwarg%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2613\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for keyword arguments in calls that match positional-only parameters of the callable.\n\n**Why is this bad?**\n\nProviding a positional-only parameter as a keyword argument will raise `TypeError` at runtime.\n\n**Example**\n\n\n```python\ndef f(x: int, /) -> int: ...\n\nf(x=1)  # Error raised here\n```\n\n## `possibly-missing-attribute`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'ignore'.\"><code>ignore</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.22\">0.0.1-alpha.22</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22possibly-missing-attribute%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2060\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for possibly missing attributes.\n\n**Why is this bad?**\n\nAttempting to access a missing attribute will raise an `AttributeError` at runtime.\n\n**Rule status**\n\nThis rule is currently disabled by default because of the number of\nfalse positives it can produce.\n\n**Examples**\n\n```python\nclass A:\n    if b:\n        c = 0\n\nA.c  # AttributeError: type object 'A' has no attribute 'c'\n```\n\n## `possibly-missing-implicit-call`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'warn'.\"><code>warn</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.22\">0.0.1-alpha.22</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22possibly-missing-implicit-call%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L213\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for implicit calls to possibly missing methods.\n\n**Why is this bad?**\n\nExpressions such as `x[y]` and `x * y` call methods\nunder the hood (`__getitem__` and `__mul__` respectively).\nCalling a missing method will raise an `AttributeError` at runtime.\n\n**Examples**\n\n```python\nimport datetime\n\nclass A:\n    if datetime.date.today().weekday() != 6:\n        def __getitem__(self, v): ...\n\nA()[0]  # TypeError: 'A' object is not subscriptable\n```\n\n## `possibly-missing-import`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'ignore'.\"><code>ignore</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.22\">0.0.1-alpha.22</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22possibly-missing-import%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2107\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for imports of symbols that may be missing.\n\n**Why is this bad?**\n\nImporting a missing module or name will raise a `ModuleNotFoundError`\nor `ImportError` at runtime.\n\n**Rule status**\n\nThis rule is currently disabled by default because of the number of\nfalse positives it can produce.\n\n**Examples**\n\n```python\n# module.py\nimport datetime\n\nif datetime.date.today().weekday() != 6:\n    a = 1\n\n# main.py\nfrom module import a  # ImportError: cannot import name 'a' from 'module'\n```\n\n## `possibly-missing-submodule`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'warn'.\"><code>warn</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.23\">0.0.23</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22possibly-missing-submodule%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2086\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for accesses of submodules that might not've been imported.\n\n**Why is this bad?**\n\nWhen module `a` has a submodule `b`, `import a` isn't generally enough to let you access\n`a.b.` You either need to explicitly `import a.b`, or else you need the `__init__.py` file\nof `a` to include `from . import b`. Without one of those, `a.b` is an `AttributeError`.\n\n**Examples**\n\n```python\nimport html\nhtml.parser  # AttributeError: module 'html' has no attribute 'parser'\n```\n\n## `possibly-unresolved-reference`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'ignore'.\"><code>ignore</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22possibly-unresolved-reference%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2137\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for references to names that are possibly not defined.\n\n**Why is this bad?**\n\nUsing an undefined variable will raise a `NameError` at runtime.\n\n**Rule status**\n\nThis rule is currently disabled by default because of the number of\nfalse positives it can produce.\n\n**Example**\n\n\n```python\nfor i in range(0):\n    x = i\n\nprint(x)  # NameError: name 'x' is not defined\n```\n\n## `raw-string-type-annotation`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22raw-string-type-annotation%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fstring_annotation.rs#L62\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for raw-strings in type annotation positions.\n\n**Why is this bad?**\n\nStatic analysis tools like ty can't analyze type annotations that use raw-string notation.\n\n**Examples**\n\n```python\ndef test(): -> r\"int\":\n    ...\n```\n\nUse instead:\n```python\ndef test(): -> \"int\":\n    ...\n```\n\n## `redundant-cast`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'warn'.\"><code>warn</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22redundant-cast%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2814\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nDetects redundant `cast` calls where the value already has the target type.\n\n**Why is this bad?**\n\nThese casts have no effect and can be removed.\n\n**Example**\n\n```python\ndef f() -> int:\n    return 10\n\ncast(int, f())  # Redundant\n```\n\n## `redundant-final-classvar`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'warn'.\"><code>warn</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.18\">0.0.18</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22redundant-final-classvar%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2835\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for redundant combinations of the `ClassVar` and `Final` type qualifiers.\n\n**Why is this bad?**\n\nAn attribute that is marked `Final` in a class body is implicitly a class variable.\nMarking it as `ClassVar` is therefore redundant.\n\nNote that this diagnostic is not emitted for dataclass fields, where\n`ClassVar[Final[int]]` has a distinct meaning from `Final[int]`.\n\n**Examples**\n\n```python\nfrom typing import ClassVar, Final\n\nclass C:\n    x: ClassVar[Final[int]] = 1  # redundant\n    y: Final[ClassVar[int]] = 1  # redundant\n```\n\n## `shadowed-type-variable`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.20\">0.0.20</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22shadowed-type-variable%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2861\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for type variables in nested generic classes or functions that shadow type variables\nfrom an enclosing scope.\n\n**Why is this bad?**\n\nShadowing type variables makes the code confusing and is disallowed by the typing spec.\n\n**Examples**\n\n```python\nclass Outer[T]:\n    # Error: `T` is already used by `Outer`\n    class Inner[T]: ...\n\n    # Error: `T` is already used by `Outer`\n    def method[T](self, x: T) -> T: ...\n```\n\n**References**\n\n- [Typing spec: Generics](https://typing.python.org/en/latest/spec/generics.html#introduction)\n\n## `static-assert-error`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22static-assert-error%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2762\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nMakes sure that the argument of `static_assert` is statically known to be true.\n\n**Why is this bad?**\n\nA `static_assert` call represents an explicit request from the user\nfor the type checker to emit an error if the argument cannot be verified\nto evaluate to `True` in a boolean context.\n\n**Examples**\n\n```python\nfrom ty_extensions import static_assert\n\nstatic_assert(1 + 1 == 3)  # error: evaluates to `False`\n\nstatic_assert(int(2.0 * 3.0) == 6)  # error: does not have a statically known truthiness\n```\n\n## `subclass-of-final-class`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22subclass-of-final-class%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2163\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for classes that subclass final classes.\n\n**Why is this bad?**\n\nDecorating a class with `@final` declares to the type checker that it should not be subclassed.\n\n**Example**\n\n\n```python\nfrom typing import final\n\n@final\nclass A: ...\nclass B(A): ...  # Error raised here\n```\n\n## `super-call-in-named-tuple-method`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.30\">0.0.1-alpha.30</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22super-call-in-named-tuple-method%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2547\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for calls to `super()` inside methods of `NamedTuple` classes.\n\n**Why is this bad?**\n\nUsing `super()` in a method of a `NamedTuple` class will raise an exception at runtime.\n\n**Examples**\n\n```python\nfrom typing import NamedTuple\n\nclass F(NamedTuple):\n    x: int\n\n    def method(self):\n        super()  # error: super() is not supported in methods of NamedTuple classes\n```\n\n**References**\n\n- [Python documentation: super()](https://docs.python.org/3/library/functions.html#super)\n\n## `too-many-positional-arguments`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22too-many-positional-arguments%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2487\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for calls that pass more positional arguments than the callable can accept.\n\n**Why is this bad?**\n\nPassing too many positional arguments will raise `TypeError` at runtime.\n\n**Example**\n\n\n```python\ndef f(): ...\n\nf(\"foo\")  # Error raised here\n```\n\n## `type-assertion-failure`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22type-assertion-failure%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2435\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for `assert_type()` and `assert_never()` calls where the actual type\nis not the same as the asserted type.\n\n**Why is this bad?**\n\n`assert_type()` allows confirming the inferred type of a certain value.\n\n**Example**\n\n\n```python\ndef _(x: int):\n    assert_type(x, int)  # fine\n    assert_type(x, str)  # error: Actual type does not match asserted type\n```\n\n## `unavailable-implicit-super-arguments`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22unavailable-implicit-super-arguments%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2508\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nDetects invalid `super()` calls where implicit arguments like the enclosing class or first method argument are unavailable.\n\n**Why is this bad?**\n\nWhen `super()` is used without arguments, Python tries to find two things:\nthe nearest enclosing class and the first argument of the immediately enclosing function (typically self or cls).\nIf either of these is missing, the call will fail at runtime with a `RuntimeError`.\n\n**Examples**\n\n```python\nsuper()  # error: no enclosing class or function found\n\ndef func():\n    super()  # error: no enclosing class or first argument exists\n\nclass A:\n    f = super()  # error: no enclosing function to provide the first argument\n\n    def method(self):\n        def nested():\n            super()  # error: first argument does not exist in this nested function\n\n        lambda: super()  # error: first argument does not exist in this lambda\n\n        (super() for _ in range(10))  # error: argument is not available in generator expression\n\n        super()  # okay! both enclosing class and first argument are available\n```\n\n**References**\n\n- [Python documentation: super()](https://docs.python.org/3/library/functions.html#super)\n\n## `unbound-type-variable`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.20\">0.0.20</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22unbound-type-variable%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1857\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for type variables that are used in a scope where they are not bound\nto any enclosing generic context.\n\n**Why is this bad?**\n\nUsing a type variable outside of a scope that binds it has no well-defined meaning.\n\n**Examples**\n\n```python\nfrom typing import TypeVar, Generic\n\nT = TypeVar(\"T\")\nS = TypeVar(\"S\")\n\nx: T  # error: unbound type variable in module scope\n\nclass C(Generic[T]):\n    x: list[S] = []  # error: S is not in this class's generic context\n```\n\n**References**\n\n- [Typing spec: Scoping rules for type variables](https://typing.python.org/en/latest/spec/generics.html#scoping-rules-for-type-variables)\n\n## `undefined-reveal`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'warn'.\"><code>warn</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22undefined-reveal%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2574\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for calls to `reveal_type` without importing it.\n\n**Why is this bad?**\n\nUsing `reveal_type` without importing it will raise a `NameError` at runtime.\n\n**Examples**\n\n```python\nreveal_type(1)  # NameError: name 'reveal_type' is not defined\n```\n\n## `unknown-argument`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22unknown-argument%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2592\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for keyword arguments in calls that don't match any parameter of the callable.\n\n**Why is this bad?**\n\nProviding an unknown keyword argument will raise `TypeError` at runtime.\n\n**Example**\n\n\n```python\ndef f(x: int) -> int: ...\n\nf(x=1, y=2)  # Error raised here\n```\n\n## `unresolved-attribute`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22unresolved-attribute%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2634\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for unresolved attributes.\n\n**Why is this bad?**\n\nAccessing an unbound attribute will raise an `AttributeError` at runtime.\nAn unresolved attribute is not guaranteed to exist from the type alone,\nso this could also indicate that the object is not of the type that the user expects.\n\n**Examples**\n\n```python\nclass A: ...\n\nA().foo  # AttributeError: 'A' object has no attribute 'foo'\n```\n\n## `unresolved-global`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'warn'.\"><code>warn</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.15\">0.0.1-alpha.15</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22unresolved-global%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2888\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nDetects variables declared as `global` in an inner scope that have no explicit\nbindings or declarations in the global scope.\n\n**Why is this bad?**\n\nFunction bodies with `global` statements can run in any order (or not at all), which makes\nit hard for static analysis tools to infer the types of globals without\nexplicit definitions or declarations.\n\n**Example**\n\n```python\ndef f():\n    global x  # unresolved global\n    x = 42\n\ndef g():\n    print(x)  # unresolved reference\n```\n\nUse instead:\n\n```python\nx: int\n\ndef f():\n    global x\n    x = 42\n\ndef g():\n    print(x)\n```\n\nOr:\n\n```python\nx: int | None = None\n\ndef f():\n    global x\n    x = 42\n\ndef g():\n    print(x)\n```\n\n## `unresolved-import`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22unresolved-import%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2656\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for import statements for which the module cannot be resolved.\n\n**Why is this bad?**\n\nImporting a module that cannot be resolved will raise a `ModuleNotFoundError`\nat runtime.\n\n**Examples**\n\n```python\nimport foo  # ModuleNotFoundError: No module named 'foo'\n```\n\n## `unresolved-reference`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22unresolved-reference%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2675\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for references to names that are not defined.\n\n**Why is this bad?**\n\nUsing an undefined variable will raise a `NameError` at runtime.\n\n**Example**\n\n\n```python\nprint(x)  # NameError: name 'x' is not defined\n```\n\n## `unsupported-base`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'warn'.\"><code>warn</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.7\">0.0.1-alpha.7</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22unsupported-base%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1053\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for class definitions that have bases which are unsupported by ty.\n\n**Why is this bad?**\n\nIf a class has a base that is an instance of a complex type such as a union type,\nty will not be able to resolve the [method resolution order] (MRO) for the class.\nThis will lead to an inferior understanding of your codebase and unpredictable\ntype-checking behavior.\n\n**Examples**\n\n```python\nimport datetime\n\nclass A: ...\nclass B: ...\n\nif datetime.date.today().weekday() != 6:\n    C = A\nelse:\n    C = B\n\nclass D(C): ...  # error: [unsupported-base]\n```\n\n[method resolution order]: https://docs.python.org/3/glossary.html#term-method-resolution-order\n\n## `unsupported-bool-conversion`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22unsupported-bool-conversion%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2008\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for bool conversions where the object doesn't correctly implement `__bool__`.\n\n**Why is this bad?**\n\nIf an exception is raised when you attempt to evaluate the truthiness of an object,\nusing the object in a boolean context will fail at runtime.\n\n**Examples**\n\n\n```python\nclass NotBoolable:\n    __bool__ = None\n\nb1 = NotBoolable()\nb2 = NotBoolable()\n\nif b1:  # exception raised here\n    pass\n\nb1 and b2  # exception raised here\nnot b1  # exception raised here\nb1 < b2 < b1  # exception raised here\n```\n\n## `unsupported-dynamic-base`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'ignore'.\"><code>ignore</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.12\">0.0.12</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22unsupported-dynamic-base%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1086\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for dynamic class definitions (using `type()`) that have bases\nwhich are unsupported by ty.\n\nThis is equivalent to [`unsupported-base`](#unsupported-base) but applies to classes created\nvia `type()` rather than `class` statements.\n\n**Why is this bad?**\n\nIf a dynamically created class has a base that is an unsupported type\nsuch as `type[T]`, ty will not be able to resolve the\n[method resolution order] (MRO) for the class. This may lead to an inferior\nunderstanding of your codebase and unpredictable type-checking behavior.\n\n**Default level**\n\nThis rule is disabled by default because it will not cause a runtime error,\nand may be noisy on codebases that use `type()` in highly dynamic ways.\n\n**Examples**\n\n```python\ndef factory(base: type[Base]) -> type:\n    # `base` has type `type[Base]`, not `type[Base]` itself\n    return type(\"Dynamic\", (base,), {})  # error: [unsupported-dynamic-base]\n```\n\n[method resolution order]: https://docs.python.org/3/glossary.html#term-method-resolution-order\n\n## `unsupported-operator`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22unsupported-operator%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2694\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for binary expressions, comparisons, and unary expressions where\nthe operands don't support the operator.\n\n**Why is this bad?**\n\nAttempting to use an unsupported operator will raise a `TypeError` at\nruntime.\n\n**Examples**\n\n```python\nclass A: ...\n\nA() + A()  # TypeError: unsupported operand type(s) for +: 'A' and 'A'\n```\n\n## `unused-awaitable`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'warn'.\"><code>warn</code></a> ·\nPreview (since <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.21\">0.0.21</a>) ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22unused-awaitable%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2716\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for awaitable objects (such as coroutines) used as expression\nstatements without being awaited.\n\n**Why is this bad?**\n\nCalling an `async def` function returns a coroutine object. If the\ncoroutine is never awaited, the body of the async function will never\nexecute, which is almost always a bug. Python emits a\n`RuntimeWarning: coroutine was never awaited` at runtime in this case.\n\n**Examples**\n\n```python\nasync def fetch_data() -> str:\n    return \"data\"\n\nasync def main() -> None:\n    fetch_data()  # Warning: coroutine is not awaited\n    await fetch_data()  # OK\n```\n\n## `unused-ignore-comment`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'warn'.\"><code>warn</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22unused-ignore-comment%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Fsuppression.rs#L25\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for `ty: ignore` directives that are no longer applicable.\n\n**Why is this bad?**\n\nA `ty: ignore` directive that no longer matches any diagnostic violations is likely\nincluded by mistake, and should be removed to avoid confusion.\n\n**Examples**\n\n```py\na = 20 / 2  # ty: ignore[division-by-zero]\n```\n\nUse instead:\n\n```py\na = 20 / 2\n```\n\n**Options**\n\nSet [`analysis.respect-type-ignore-comments`](https://docs.astral.sh/ty/reference/configuration/#respect-type-ignore-comments)\nto `false` to prevent this rule from reporting unused `type: ignore` comments.\n\n## `unused-type-ignore-comment`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'warn'.\"><code>warn</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.14\">0.0.14</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22unused-type-ignore-comment%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Fsuppression.rs#L54\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for `type: ignore` directives that are no longer applicable.\n\n**Why is this bad?**\n\nA `type: ignore` directive that no longer matches any diagnostic violations is likely\nincluded by mistake, and should be removed to avoid confusion.\n\n**Examples**\n\n```py\na = 20 / 2  # type: ignore\n```\n\nUse instead:\n\n```py\na = 20 / 2\n```\n\n**Options**\n\n\nThis rule is skipped if [`analysis.respect-type-ignore-comments`](https://docs.astral.sh/ty/reference/configuration/#respect-type-ignore-comments)\nto `false`.\n\n## `useless-overload-body`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'warn'.\"><code>warn</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.22\">0.0.1-alpha.22</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22useless-overload-body%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1481\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for various `@overload`-decorated functions that have non-stub bodies.\n\n**Why is this bad?**\n\nFunctions decorated with `@overload` are ignored at runtime; they are overridden\nby the implementation function that follows the series of overloads. While it is\nnot illegal to provide a body for an `@overload`-decorated function, it may indicate\na misunderstanding of how the `@overload` decorator works.\n\n**Example**\n\n\n```py\nfrom typing import overload\n\n@overload\ndef foo(x: int) -> int:\n    return x + 1  # will never be executed\n\n@overload\ndef foo(x: str) -> str:\n    return \"Oh no, got a string\"  # will never be executed\n\ndef foo(x: int | str) -> int | str:\n    raise Exception(\"unexpected type encountered\")\n```\n\nUse instead:\n\n```py\nfrom typing import assert_never, overload\n\n@overload\ndef foo(x: int) -> int: ...\n\n@overload\ndef foo(x: str) -> str: ...\n\ndef foo(x: int | str) -> int | str:\n    if isinstance(x, int):\n        return x + 1\n    elif isinstance(x, str):\n        return \"Oh no, got a string\"\n    else:\n        assert_never(x)\n```\n\n**References**\n\n- [Python documentation: `@overload`](https://docs.python.org/3/library/typing.html#typing.overload)\n\n## `zero-stepsize-in-slice`\n\n<small>\nDefault level: <a href=\"../../rules#rule-levels\" title=\"This lint has a default level of 'error'.\"><code>error</code></a> ·\nAdded in <a href=\"https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1\">0.0.1-alpha.1</a> ·\n<a href=\"https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20%22zero-stepsize-in-slice%22\" target=\"_blank\">Related issues</a> ·\n<a href=\"https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2743\" target=\"_blank\">View source</a>\n</small>\n\n\n**What it does**\n\nChecks for step size 0 in slices.\n\n**Why is this bad?**\n\nA slice with a step size of zero will raise a `ValueError` at runtime.\n\n**Examples**\n\n```python\nl = list(range(10))\nl[1:10:0]  # ValueError: slice step cannot be zero\n```\n\n"
  },
  {
    "path": "docs/reference/typing-faq.md",
    "content": "# Typing FAQ\n\nThis page answers some commonly asked questions about ty and Python's type system.\n\n## Why does ty report an error on my code?\n\nCheck the [documentation](https://docs.astral.sh/ty/reference/rules/) for the specific error code\nyou are seeing; it may explain the problem.\n\n## What is the `Unknown` type and when does it appear?\n\n`Unknown` is ty's way of representing a type that could not be fully inferred. It behaves the same\nway as `Any`, but appears implicitly, rather than through an explicit `Any` annotation:\n\n```py\nfrom missing_module import MissingClass  # error: unresolved-import\n\nreveal_type(MissingClass)  # Unknown\n```\n\nty also uses unions with `Unknown` to maintain the\n[gradual guarantee](../features/type-system.md#gradual-guarantee), which helps avoid false positive\nerrors in untyped code while still providing useful type information where possible.\n\nFor example, consider the following untyped `Message` class (which could come from a third-party\ndependency that you have no control over). ty treats the `data` attribute as having type\n`Unknown | None`, since there is no type annotation that restricts it further. The `Unknown` in the\nunion allows ty to avoid raising errors on the `msg.data = …` assignment. On the other hand, the\n`None` in the union reflects the fact that `data` *could* possibly be `None`, and requires code that\nuses `msg.data` to handle that case explicitly.\n\n```py\nclass Message:\n    data = None\n\n    def __init__(self, title):\n        self.title = title\n\n\ndef receive(msg: Message):\n    reveal_type(msg.data)  # Unknown | None\n\n\nmsg = Message(\"Favorite color\")\nmsg.data = {\"color\": \"blue\"}\n```\n\n([Full example in the playground](https://play.ty.dev/862941a8-a3f6-4818-9ea1-d9d59b0bd2fa))\n\n## Why does ty show `int | float` when I annotate something as `float`?\n\nThe [Python typing specification](https://typing.python.org/en/latest/spec/special-types.html)\nincludes a special rule for numeric types where an `int` can be used wherever a `float` is expected:\n\n```py\ndef circle_area(radius: float) -> float:\n    return 3.14 * radius * radius\n\ncircle_area(2)      # OK: int is allowed where float is expected\n```\n\nThis rule is a special case, since `int` is not actually a subclass of `float`. To support this, ty\ntreats `float` annotations as meaning `int | float`. Unlike some other type checkers, ty makes this\nbehavior explicit in type hints and error messages. For example, if you\n[hover over the `radius` parameter](https://play.ty.dev/fdc144c6-031c-4af9-b520-a4c6ccde9261), ty\nwill show `int | float`.\n\nA similar rule applies to `complex`, which is treated as `int | float | complex`.\n\n!!! info\n\n    These special rules for `float` and `complex` exist for a reason. In almost all cases, you\n    probably want to accept both `int` and `float` when you annotate something as `float`.\n    If you really need to accept *only* `float` and not `int`, you can use ty's `JustFloat`\n    type. At the time of writing, this import needs to be guarded by a `TYPE_CHECKING` block:\n\n    ```py\n    from typing import TYPE_CHECKING\n\n    if TYPE_CHECKING:\n        from ty_extensions import JustFloat\n    else:\n        JustFloat = float\n\n    def only_actual_floats_allowed(f: JustFloat) -> None: ...\n\n    only_actual_floats_allowed(1.0)  # OK\n    only_actual_floats_allowed(1)    # error: invalid-argument-type\n    ```\n\n    ([Full example in the playground](https://play.ty.dev/fb034780-3ba7-4c6a-9449-5b0f44128bab))\n\n    If you need this for `complex`, you can use `ty_extensions.JustComplex` in a similar way.\n\n## Why can't I use `list[Subtype]` when a `list[Supertype]` is expected? { #invariant-generics }\n\nLet's say you have a class hierarchy with an `Entry` base class as well as `Directory` and `File` subclasses. Since\na `Directory` *is* an `Entry`, you can use it everywhere an `Entry` is expected.\nYou might therefore expect a `list[Directory]` to\nbe usable in any context where a `list[Entry]` is expected, but this is not\nthe case. The reason for this is mutability:\n\n```py\n# Setup of `Entry`, `Directory`, and `File` classes (1)\n\ndef modify(entries: list[Entry]):\n    entries.append(File(\"README.txt\")) # mutation\n\ndirectories: list[Directory] = [Directory(\"Downloads\"), Directory(\"Documents\")]\nmodify(directories)  # ty emits an error on this call\n```\n\n1. The full example might look like this:\n\n    ```py\n    from dataclasses import dataclass\n\n    @dataclass\n    class Entry:\n         path: str\n         def size_bytes(self) -> int: ...\n\n    @dataclass\n    class Directory(Entry):\n        def children(self) -> list[Entry]: ...\n\n    @dataclass\n    class File(Entry):\n        def content(self) -> bytes: ...\n\n    def modify(entries: list[Entry]):\n        entries.append(File(\"README.txt\")) # mutation\n\n    directories: list[Directory] = [Directory(\"Downloads\"), Directory(\"Documents\")]\n    modify(directories)  # ty emits an error on this call\n    ```\n\n    You can try it out in [this playground example](https://play.ty.dev/01013e73-da54-40c4-a9c5-2af269abda9d).\n\nThe `modify` call mutates the contents of the `directories` list. After this call,\nit contains two directories *and one `File`*, which clearly violates the\n`list[Directory]` type annotation. If this call *were* allowed, subsequent code\nthat relies on the fact that `directories` only contains `Directory` instances might\nbreak at runtime:\n\n```py\nfor directory in directories:\n    directory.children()  # runtime: 'File' object has no attribute 'children'\n```\n\n!!! info\n\n    In type system terminology, we say `list` is *invariant*, which means that\n    just because `A` is a subtype of `B` does not mean that `list[A]` will be a\n    subtype of `list[B]`. The same is true for other builtin collections such as\n    `set` or `dict`. In contrast, read-only collections like `tuple` or\n    `frozenset` are *covariant* in their type parameter. It is safe to assign a\n    `frozenset[bool]` to a `frozenset[int]` because the contents cannot be\n    mutated.\n\nYou might run into problems with invariance in situations where mutability isn't\nrequired:\n\n```py\ndef total_size_bytes(entries: list[Entry]) -> int:\n    return sum(entry.size_bytes() for entry in entries)\n\n# inferred as `list[Directory]`\nmedia_entries = [Directory(\"Pictures\"), Directory(\"Videos\")]\n\n# still a type-check error, but should be fine in principle (no mutation occurs)\nsize = total_size_bytes(media_entries)\n```\n\nTo prevent this, you can adapt the signature of `total_size_bytes` to take an\nargument of type\n[`Sequence[Entry]`](https://docs.python.org/3/library/collections.abc.html#collections-abstract-base-classes)\ninstead. This type describes read-only sequences (that contain values of type\n`Entry`). `Sequence` is therefore covariant in its type parameter.\n\nIf you cannot adapt the signature of the function you are calling, you can also\nwiden the type of the argument by annotating `media_entries` as `list[Entry]`.\nIn some cases it's also a reasonable solution to create a copy of the list\n(`total_size_bytes(list(media_entries))`).\n\n!!! note\n\n    If you are looking for a covariant alternative to `dict[str, V]`, you can use [`Mapping[str, V]`](https://docs.python.org/3/library/collections.abc.html#collections.abc.Mapping).\n\n## Why does ty say `Callable` has no attribute `__name__`?\n\nWhen you access `__name__`, `__qualname__`, `__module__`, or `__doc__` on a value typed as `Callable`,\nty reports an `unresolved-attribute` error. This is because not all callables have these attributes.\nFunctions do (including lambdas), but other callable objects do not. The `FileUpload` class below, for\nexample, is callable, but instances of `FileUpload` do not have a `__name__` attribute. Passing a\n`FileUpload` instance to `retry` would lead to an `AttributeError` at runtime.\n\n```py\nfrom typing import Callable\n\ndef retry(times: int, operation: Callable[[], bool]) -> bool:\n    for i in range(times):\n        # WRONG: `operation` does not necessarily have a `__name__` attribute\n        print(f\"Calling {operation.__name__}, attempt {i + 1} of {times}\")\n        if operation():\n            return True\n    return False\n\nclass FileUpload:\n    def __init__(self, name: str) -> None:\n        # …\n\n    def __call__(self) -> bool:\n        # …\n\nretry(3, FileUpload(\"image.png\"))\n```\n\nTo fix this, you could use `getattr` with a fall back to a default name when the\nattribute is not present (or use a `hasattr(…, \"__name__\")` check if you access\nit multiple times):\n\n```py\nname = getattr(operation, \"__name__\", \"operation\")\n```\n\nAlternatively, you could use an `isinstance(…, types.FunctionType)` check to narrow the type of\n`operation` to something that definitely has a `__name__` attribute:\n\n```py\nif isinstance(operation, FunctionType):\n    print(f\"Calling {operation.__name__}, attempt {i + 1} of {times}\")\nelse:\n    print(f\"Calling operation, attempt {i + 1} of {times}\")\n```\n\nYou can try various approaches in [this playground example](https://play.ty.dev/f6f7f35a-47c3-423d-be8d-33d03c61d40c).\nSee also [this discussion](https://github.com/astral-sh/ty/issues/1495) for some plans to improve\nthe developer experience around this in the future.\n\n!!! info\n\n    ty has first-class support for intersection types. If you only want to accept function-like\n    callables, you could define `FunctionLikeCallable` as an intersection of `Callable` and\n    `types.FunctionType`:\n\n    ```py\n    from typing import Callable, TYPE_CHECKING\n    from types import FunctionType\n\n    if TYPE_CHECKING:\n        from ty_extensions import Intersection\n\n        type FunctionLikeCallable[**P, R] = Intersection[Callable[P, R], FunctionType]\n    else:\n        FunctionLikeCallable = Callable\n\n\n    def retry(times: int, operation: FunctionLikeCallable[[], bool]) -> bool:\n        ...\n    ```\n\n    You can check out the full example [here](https://play.ty.dev/7a1ea4ab-04e1-4271-adf5-ddc3a5d2fcfd),\n    which demonstrates that `FileUpload` instances are no longer accepted by `retry`.\n\n## Does ty have a strict mode?\n\nNot yet. A stricter inference mode is tracked in\n[this issue](https://github.com/astral-sh/ty/issues/1240). In the meantime, you can consider using Ruff's\n[`flake8-annotations` rules](https://docs.astral.sh/ruff/rules/#flake8-annotations-ann) to enforce\nmore explicit type annotations in your code.\n\n## Why doesn't ty warn about missing type annotations?\n\nty does not report an error for unannotated function parameters, return types, or variables. When\nty encounters an unannotated symbol, it infers the type as [`Unknown`](#what-is-the-unknown-type-and-when-does-it-appear)\nwhile still providing useful diagnostics where possible.\n\nIf you are looking for the equivalent of mypy's\n[`disallow_untyped_defs`](https://mypy.readthedocs.io/en/stable/config_file.html#confval-disallow_untyped_defs)\n(error code: `no-untyped-def`), Ruff provides this as a set of opt-in lint rules via its\n[`flake8-annotations` (`ANN`)](https://docs.astral.sh/ruff/rules/#flake8-annotations-ann) rule\ngroup.\n\nSome rules you might find useful include:\n\n- [`ANN001`](https://docs.astral.sh/ruff/rules/missing-type-function-argument/): Missing type\n    annotation for function argument\n- [`ANN002`](https://docs.astral.sh/ruff/rules/missing-type-args/): Missing type annotation for\n    `*args`\n- [`ANN003`](https://docs.astral.sh/ruff/rules/missing-type-kwargs/): Missing type annotation for\n    `**kwargs`\n- [`ANN201`](https://docs.astral.sh/ruff/rules/missing-return-type-undocumented-public-function/):\n    Missing return type annotation for public function\n- [`ANN202`](https://docs.astral.sh/ruff/rules/missing-return-type-private-function/): Missing\n    return type annotation for private function\n- [`RUF045`](https://docs.astral.sh/ruff/rules/implicit-class-var-in-dataclass/): Implicit class\n    variable in dataclass\n\n## Why can't ty resolve my imports?\n\nImport resolution issues are often caused by a missing or incorrect environment configuration. When\nty reports *\"Cannot resolve imported module …\"*, check the following:\n\n1. **Virtual environment**: Make sure your virtual environment is discoverable. ty looks for an\n    active virtual environment via `VIRTUAL_ENV` or a `.venv` directory in your project root. See the\n    [module discovery](../modules.md#python-environment) documentation for more details.\n\n1. **Project structure**: If your source code is not in the project root or `src/` directory,\n    configure [`environment.root`](./configuration.md#root) in your `pyproject.toml`:\n\n    ```toml\n    [tool.ty.environment]\n    root = [\"./app\"]\n    ```\n\n1. **Third-party packages**: Ensure dependencies are installed in your virtual environment. Run ty\n    with `-v` to see the search paths being used.\n\n1. **Compiled extensions**: ty requires `.py` or `.pyi` files for type information. If a package\n    contains only compiled extensions (`.so` or `.pyd` files), you'll need stub files (`.pyi`) for ty\n    to understand the types. See also [this issue](https://github.com/astral-sh/ty/issues/487) which\n    tracks improvements in this area.\n\n## Does ty support monorepos?\n\nty can work with monorepos, but automatic discovery of nested projects is limited. By default, ty\nuses the current working directory or the `--project` option to determine the project root.\n\nFor monorepos with multiple Python packages, you have a few options:\n\n1. **Run ty per-package**: Run `ty check` from each package directory, or use `--project` to specify\n    the package:\n\n    ```bash\n    ty check --project packages/package-a\n    ty check --project packages/package-b\n    ```\n\n1. **Configure multiple source roots**: Use [`environment.root`](./configuration.md#root) to specify\n    multiple source directories:\n\n    ```toml\n    [tool.ty.environment]\n    root = [\"packages/package-a\", \"packages/package-b\"]\n    ```\n\n    This has the disadvantage of treating all packages as a single project, which may lead to cases\n    in which ty thinks something is importable when it wouldn't be at runtime.\n\nYou can follow [this issue](https://github.com/astral-sh/ty/issues/819) to get updates on this\ntopic.\n\n## Does ty support PEP 723 inline-metadata scripts?\n\nIt depends on what you want to do. If you have a single inline-metadata script, you can type check\nit with ty by using uv's `--with-requirements` flag to install the dependencies specified in the\nscript header:\n\n```bash\nuvx --with-requirements script.py ty check script.py\n```\n\nIf you have multiple scripts in your workspace, ty does not yet recognize that they have different\ndependencies based on their inline metadata.\n\nYou can follow [this issue](https://github.com/astral-sh/ty/issues/691) for updates.\n\n## Is there a pre-commit hook for ty?\n\nNot yet. You can track progress in [this issue](https://github.com/astral-sh/ty/issues/269), which\nalso includes some suggested manual hooks you can use in the meantime.\n\n## Does ty support (mypy) plugins?\n\nNo. ty does not have a plugin system and there is currently no plan to add one.\n\nWe prefer extending the type system with well-specified features rather than relying on\ntype-checker-specific plugins. That said, we are considering adding support for popular third-party\nlibraries like pydantic, SQLAlchemy, attrs, or django directly into ty.\n\n## What is `Top[list[Unknown]]`, and why does it appear?\n\nThis type represents \"all possible lists of any element type\" (as opposed to `list[Unknown]`, which\nrepresents \"a list of some unknown element type\"). It usually arises from a check such as\n`if isinstance(x, list):`. If `x` was previously of type `Item | list[Item]`, you might expect this\ncheck to narrow the type to `list[Item]`, but ty respects the possibility that there could be a\ncommon subclass of both `Item` and `list` (which may not be a list of `Item`!), and so the narrowed\ntype is instead `(Item & Top[list[Unknown]]) | list[Item]`. This code can be made more robust by\ninstead checking `if instance(x, Item)`, or by declaring the `Item` type as `@typing.final`.\n\nSee also the [discussion\nhere](https://docs.astral.sh/ty/features/type-system/#top-and-bottom-materializations) and [in this\nissue](https://github.com/astral-sh/ty/issues/1578).\n"
  },
  {
    "path": "docs/requirements.in",
    "content": "black>=23.10.0\nmkdocs>=1.5.0\nmkdocs-material>=9.7.0\nmkdocs-redirects>=1.2.1\nmdformat>=0.7.17\nmdformat-mkdocs>=2.0.4\nmdformat-admon>=2.0.2\nmkdocs-redirects>=1.2.2\nmkdocs-git-revision-date-localized-plugin>=1.3.0\nmkdocs-llmstxt>=0.2.0\n"
  },
  {
    "path": "docs/requirements.txt",
    "content": "# This file was autogenerated by uv via the following command:\n#    uv pip compile docs/requirements.in -o docs/requirements.txt --universal -p 3.12\nbabel==2.15.0\n    # via\n    #   mkdocs-git-revision-date-localized-plugin\n    #   mkdocs-material\nbackrefs==6.1\n    # via mkdocs-material\nbeautifulsoup4==4.13.4\n    # via\n    #   markdownify\n    #   mkdocs-llmstxt\nblack==24.4.2\n    # via -r docs/requirements.in\ncertifi==2024.7.4\n    # via requests\ncharset-normalizer==3.3.2\n    # via requests\nclick==8.1.7\n    # via\n    #   black\n    #   mkdocs\ncolorama==0.4.6\n    # via\n    #   click\n    #   mkdocs\n    #   mkdocs-material\nghp-import==2.1.0\n    # via mkdocs\ngitdb==4.0.12\n    # via gitpython\ngitpython==3.1.44\n    # via mkdocs-git-revision-date-localized-plugin\nidna==3.7\n    # via requests\njinja2==3.1.4\n    # via\n    #   mkdocs\n    #   mkdocs-material\nlinkify-it-py==2.0.3\n    # via markdown-it-py\nmarkdown==3.6\n    # via\n    #   mkdocs\n    #   mkdocs-material\n    #   pymdown-extensions\nmarkdown-it-py==3.0.0\n    # via\n    #   mdformat\n    #   mdformat-gfm\n    #   mdit-py-plugins\nmarkdownify==1.1.0\n    # via mkdocs-llmstxt\nmarkupsafe==2.1.5\n    # via\n    #   jinja2\n    #   mkdocs\nmdformat==0.7.22\n    # via\n    #   -r docs/requirements.in\n    #   mdformat-admon\n    #   mdformat-gfm\n    #   mdformat-mkdocs\n    #   mdformat-tables\n    #   mkdocs-llmstxt\nmdformat-admon==2.0.6\n    # via\n    #   -r docs/requirements.in\n    #   mdformat-mkdocs\nmdformat-gfm==0.3.6\n    # via mdformat-mkdocs\nmdformat-mkdocs==3.0.0\n    # via -r docs/requirements.in\nmdformat-tables==0.4.1\n    # via mdformat-gfm\nmdit-py-plugins==0.4.1\n    # via\n    #   mdformat-admon\n    #   mdformat-gfm\n    #   mdformat-mkdocs\nmdurl==0.1.2\n    # via markdown-it-py\nmergedeep==1.3.4\n    # via\n    #   mkdocs\n    #   mkdocs-get-deps\nmkdocs==1.6.0\n    # via\n    #   -r docs/requirements.in\n    #   mkdocs-git-revision-date-localized-plugin\n    #   mkdocs-material\n    #   mkdocs-redirects\nmkdocs-get-deps==0.2.0\n    # via mkdocs\nmkdocs-git-revision-date-localized-plugin==1.3.0\n    # via -r docs/requirements.in\nmkdocs-llmstxt==0.2.0\n    # via -r docs/requirements.in\nmkdocs-material==9.7.0\n    # via -r docs/requirements.in\nmkdocs-material-extensions==1.3.1\n    # via mkdocs-material\nmkdocs-redirects==1.2.2\n    # via -r docs/requirements.in\nmore-itertools==10.3.0\n    # via mdformat-mkdocs\nmypy-extensions==1.0.0\n    # via black\npackaging==24.1\n    # via\n    #   black\n    #   mkdocs\npaginate==0.5.6\n    # via mkdocs-material\npathspec==0.12.1\n    # via\n    #   black\n    #   mkdocs\nplatformdirs==4.2.2\n    # via\n    #   black\n    #   mkdocs-get-deps\npygments==2.18.0\n    # via mkdocs-material\npymdown-extensions==10.8.1\n    # via mkdocs-material\npython-dateutil==2.9.0.post0\n    # via ghp-import\npytz==2025.1\n    # via mkdocs-git-revision-date-localized-plugin\npyyaml==6.0.1\n    # via\n    #   mkdocs\n    #   mkdocs-get-deps\n    #   pymdown-extensions\n    #   pyyaml-env-tag\npyyaml-env-tag==0.1\n    # via mkdocs\nrequests==2.32.3\n    # via mkdocs-material\nsix==1.16.0\n    # via\n    #   markdownify\n    #   python-dateutil\nsmmap==5.0.2\n    # via gitdb\nsoupsieve==2.7\n    # via beautifulsoup4\ntyping-extensions==4.14.0\n    # via beautifulsoup4\nuc-micro-py==1.0.3\n    # via linkify-it-py\nurllib3==2.2.2\n    # via requests\nwatchdog==4.0.1\n    # via mkdocs\n"
  },
  {
    "path": "docs/rules.md",
    "content": "# Rules\n\nRules are individual checks that ty performs to detect common issues in your code, such as\nincompatible assignments, missing imports, or invalid type annotations. Each rule focuses on a\nspecific pattern and can be turned on or off depending on your project’s needs.\n\n!!! tip\n\n    See the [rules reference](./reference/rules.md) for an enumeration of all supported rules.\n\n## Rule levels\n\nEach rule has a configurable level:\n\n- `error`: violations are reported as errors and ty exits with an exit code of 1 if there's any.\n- `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`.\n- `ignore`: the rule is turned off\n\nYou can configure the level for each rule on the command line using the `--warn`, `--error`, and\n`--ignore` flags. For example:\n\n```shell\n\nty check \\\n  --warn unused-ignore-comment \\        # Make `unused-ignore-comment` a warning\n  --ignore redundant-cast \\             # Disable `redundant-cast`\n  --error possibly-missing-attribute \\  # Error on `possibly-missing-attribute`\n  --error possibly-missing-import       # Error on `possibly-missing-import`\n```\n\nThe options can be repeated. Subsequent options override earlier options.\n\nRule levels can also be changed in the [`rules`](./reference/configuration.md#rules) section of a\n[configuration file](./configuration.md).\n\nFor example, the following is equivalent to the command above:\n\n```toml title=\"pyproject.toml\"\n[tool.ty.rules]\nunused-ignore-comment = \"warn\"\nredundant-cast = \"ignore\"\npossibly-missing-attribute = \"error\"\npossibly-missing-import = \"error\"\n```\n\nYou can also configure the level for all rules at once.\n\nOn the command line you can use `--error all`, `--warn all`, or `--ignore all`. For example:\n\n```shell\n\nty check --error all\n```\n\nYou can also configure this setting in the [`rules`](./reference/configuration.md#rules) section of a\n[configuration file](./configuration.md).\n\nFor example, the following is equivalent to the command above:\n\n```toml title=\"pyproject.toml\"\n[tool.ty.rules]\nall = \"error\"\n```\n"
  },
  {
    "path": "docs/stylesheets/extra.css",
    "content": ":root {\n  --black: #261230;\n  --white: #ffffff;\n  --radiate: #d7ff64;\n  --flare: #6340ac;\n  --rock: #78876e;\n  --galaxy: #261230;\n  --space: #30173d;\n  --comet: #6f5d6f;\n  --cosmic: #de5fe9;\n  --sun: #ffac2f;\n  --electron: #46ebe1;\n  --aurora: #46eb74;\n  --constellation: #5f6de9;\n  --neutron: #cff3cf;\n  --proton: #f6afbc;\n  --nebula: #cdcbfb;\n  --supernova: #f1aff6;\n  --starlight: #f4f4f1;\n  --lunar: #fbf2fc;\n  --asteroid: #e3cee3;\n  --crater: #f0dfdf;\n}\n\n[data-md-color-scheme=\"astral-light\"] {\n  --md-default-bg-color--dark: var(--black);\n  --md-primary-fg-color: var(--galaxy);\n  --md-typeset-a-color: var(--flare);\n  --md-accent-fg-color: var(--cosmic);\n  --md-default-fg-color--lightest: rgba(0, 0, 0, 0.14);\n}\n\n[data-md-color-scheme=\"astral-dark\"] {\n  --md-default-bg-color: var(--galaxy);\n  --md-default-fg-color: var(--white);\n  --md-default-fg-color--light: var(--white);\n  --md-default-fg-color--lighter: var(--white);\n  --md-default-fg-color--lightest: rgba(255, 255, 255, 0.5);\n  --md-primary-fg-color: var(--space);\n  --md-primary-bg-color: var(--white);\n  --md-accent-fg-color: var(--cosmic);\n\n  --md-typeset-color: var(--white);\n  --md-typeset-a-color: var(--radiate);\n  --md-typeset-mark-color: var(--sun);\n\n  --md-code-fg-color: var(--white);\n  --md-code-bg-color: var(--space);\n\n  --md-code-hl-comment-color: var(--asteroid);\n  --md-code-hl-punctuation-color: var(--asteroid);\n  --md-code-hl-generic-color: var(--supernova);\n  --md-code-hl-variable-color: var(--starlight);\n  --md-code-hl-string-color: var(--radiate);\n  --md-code-hl-keyword-color: var(--supernova);\n  --md-code-hl-operator-color: var(--supernova);\n  --md-code-hl-number-color: var(--electron);\n  --md-code-hl-special-color: var(--electron);\n  --md-code-hl-function-color: var(--neutron);\n  --md-code-hl-constant-color: var(--radiate);\n  --md-code-hl-name-color: var(--md-code-fg-color);\n\n  --md-typeset-del-color: hsla(6, 90%, 60%, 0.15);\n  --md-typeset-ins-color: hsla(150, 90%, 44%, 0.15);\n\n  --md-typeset-table-color: hsla(0, 0%, 100%, 0.12);\n  --md-typeset-table-color--light: hsla(0, 0%, 100%, 0.035);\n}\n\n[data-md-color-scheme=\"astral-light\"] img[src$=\"#only-dark\"],\n[data-md-color-scheme=\"astral-light\"] img[src$=\"#gh-dark-mode-only\"] {\n  display: none; /* Hide dark images in light mode */\n}\n\n[data-md-color-scheme=\"astral-light\"] img[src$=\"#only-light\"],\n[data-md-color-scheme=\"astral-light\"] img[src$=\"#gh-light-mode-only\"] {\n  display: inline; /* Show light images in light mode */\n}\n\n[data-md-color-scheme=\"astral-dark\"] img[src$=\"#only-light\"],\n[data-md-color-scheme=\"astral-dark\"] img[src$=\"#gh-light-mode-only\"] {\n  display: none; /* Hide light images in dark mode */\n}\n\n[data-md-color-scheme=\"astral-dark\"] img[src$=\"#only-dark\"],\n[data-md-color-scheme=\"astral-dark\"] img[src$=\"#gh-dark-mode-only\"] {\n  display: inline; /* Show dark images in dark mode */\n}\n\n/* See: https://github.com/squidfunk/mkdocs-material/issues/175#issuecomment-616694465 */\n.md-typeset__table {\n  min-width: 100%;\n}\n.md-typeset table:not([class]) {\n  display: table;\n}\n\n/* See: https://github.com/astral-sh/ruff/issues/8519 */\n[data-md-color-scheme=\"astral-dark\"] details summary a {\n  color: var(--flare);\n}\n\n/* See: https://github.com/astral-sh/ruff/issues/9046 */\n[data-md-color-scheme=\"astral-dark\"] div.admonition {\n  color: var(--md-code-fg-color);\n  background-color: var(--md-code-bg-color);\n}\n\n/* Prevent the shadow from the nav title from blurring the top link.\nThe box shadow isn't really doing anything anyway.\n\nThis is a consequence of the reduced nav spacing below. */\n.md-nav--primary .md-nav__title {\n  box-shadow: none;\n}\n\n/* Omits the nav title \"ty\" entirely unless on a small screen, in which case\nthe nav title is needed for backwards navigation in the collapsible\nnav variant.\n\nSee https://github.com/astral-sh/uv/issues/5130 */\n@media screen and (min-width: 76.25em) {\n  .md-nav__title {\n    display: none;\n  }\n}\n\n\n/* Always take the full screen for content, require scrolling to see the footer\nThis stops the size of the nav from jumping around when you visit a page without\na lot of content (i.e., an overview page). We don't apply this to sma screens\nbecause the nav is in a hamburger menu anyway\n*/\n@media screen and (min-width: 76.25em) {\n  .md-main {\n    min-height: 100vh;\n  }\n}\n\n/* Tweak the formatting of the primary nav on a large screen */\n@media screen and (min-width: 76.25em) {\n  .md-nav--primary .md-nav {\n    font-size: 0.75rem;\n  }\n  /* Remove the bold from the section headings, use a larger font instead */\n  .md-nav__item--section > .md-nav__link {\n      font-weight: normal;\n      font-size: 0.85rem;\n  }\n  /* Reducing spacing between nav items to fit more content \n  First, disable `nav__link` spacing then use `nav__item` to enforce margins this reduces inconsistencies in the spacing. */\n  .md-nav--primary .md-nav__link {\n    margin: 0;\n  }\n  .md-nav--primary .md-nav__item {\n    margin-top: 0.35em;\n  }\n  /* Use larger spacing for the sections headings */\n  .md-nav--primary .md-nav__item--section {\n    margin-bottom: 0.75em;\n    margin-top: 1em;\n  }\n  /* Decrease the font size of items in a collapsible section */\n  .md-nav__item--section> .md-nav > .md-nav__list > .md-nav__item > .md-nav > .md-nav__list {\n    font-size: 0.725rem;\n  }\n  /* Increase top margin on the first item of a collapsible section */\n  .md-nav__item--section> .md-nav > .md-nav__list > .md-nav__item > .md-nav > .md-nav__list > .md-nav__item:first-of-type {\n    margin-top: 0.5em;\n  }\n  /* Increase bottom margin on the last item of a collapsible section */\n  .md-nav__item--section> .md-nav > .md-nav__list > .md-nav__item > .md-nav > .md-nav__list > .md-nav__item:last-of-type {\n    margin-bottom: 0.575em;\n  }\n  /* Increase the size of the first nav item to match the sections \n  It has no children, so it is not considered a section */\n  .md-nav--primary > .md-nav__list > .md-nav__item:first-of-type {\n    font-size: 0.85rem;\n    margin-bottom: 0.75em; \n  }\n}\n\n/* Bold the active nav link for accessibility */\n.md-nav__link--active {\n  font-weight: bold;\n}\n\n/* See: https://mkdocstrings.github.io/recipes/#prevent-selection-of-prompts-and-output-in-python-code-blocks */\n.highlight .gp, .highlight .go { /* Generic.Prompt, Generic.Output */\n  user-select: none;\n}\n\n/* Styling for the generated CLI reference page */\n.cli-reference dd {\n  margin-top: 0.1em;\n  margin-bottom: 0.5em;\n}\n.cli-reference dd p {\n  margin-block-start: 0.2em;\n  margin-block-end: 0.3em;\n}\n.cli-reference ul {\n  margin-bottom: 0.1em;\n}\nh3.cli-reference {\n  font-size: 1.1em;\n  margin: 0 0 0 0;\n}\n\n/* Styling for anchor link headers */\n.toclink {\n  color: unset !important;\n}\n\n.toclink:hover {\n  color: var(--md-accent-fg-color) !important;\n}\n\n/* Omit the first breadcrumb item, which is the \"Introduction\" */\n.md-path__list > .md-path__item:first-of-type {\n  display: none;\n}\n.md-path__list > .md-path__item:nth-of-type(2):before {\n  display: none;\n}\n\n/* Hide the modified date — its positioning is awkward but will require theme\nmodifications */\n.md-source-file__fact {\n  visibility: hidden;\n}\n"
  },
  {
    "path": "docs/suppression.md",
    "content": "# Suppression\n\nRules can also be ignored in specific locations in your code (instead of disabling the rule\nentirely) to silence false positives or permissible violations.\n\n!!! note\n\n    To disable a rule entirely, set it to the `ignore` level as described in [rule levels](rules.md/#rule-levels).\n\n## ty suppression comments\n\nTo suppress a rule violation inline add a `# ty: ignore[<rule>]` comment at the end of the line:\n\n```py\na = 10 + \"test\"  # ty: ignore[unsupported-operator]\n```\n\nRule violations spanning multiple lines can be suppressed by adding the comment at the end of the\nviolation's first or last line:\n\n```py\ndef sum_three_numbers(a: int, b: int, c: int) -> int: ...\n\n# on the first line\n\nsum_three_numbers(  # ty: ignore[missing-argument]\n    3,\n    2\n)\n\n# or, on the last line\n\nsum_three_numbers(\n    3,\n    2\n)  # ty: ignore[missing-argument]\n```\n\nTo suppress multiple violations on a single line, enumerate each rule separated by a comma:\n\n```python\nsum_three_numbers(\"one\", 5)  # ty: ignore[missing-argument, invalid-argument-type]\n```\n\n!!! note\n\n    Enumerating rule names (e.g., `[rule1, rule2]`) is optional. However, we strongly recommend\n    including suppressing specific rules to avoid accidental suppression of other errors.\n\n## Standard suppression comments\n\nty supports the standard [`type: ignore`](https://typing.python.org/en/latest/spec/directives.html#type-ignore-comments) comment\nformat introduced by PEP 484.\n\nty handles these similarly to `ty: ignore` comments, but suppresses all violations on that line,\neven when `type: ignore[code]` is used.\n\n```python\n# Ignore all typing errors on the next line\nsum_three_numbers(\"one\", 5)  # type: ignore\n```\n\n## Multiple suppressions comments\n\nTo suppress a typing error on a line that already has a suppression comment from another tool,\nadd the `# ty: ignore` comment to the same line.\n\nFor example, to suppress a type error and disable formatting for a specific line:\n\n```python\nresult = calculate()  # ty: ignore[invalid-argument-type]  # fmt: skip\n\n# or\nresult = calculate()  # fmt: off  # ty: ignore[invalid-argument-type]\n```\n\n## Unused suppression comments\n\nIf the [`unused-ignore-comment`](./reference/rules.md#unused-ignore-comment) rule is enabled, ty\nwill report unused `ty: ignore` and `type: ignore` comments.\n\n`unused-ignore-comment` violations can only be suppressed using `# ty: ignore[unused-ignore-comment]`.\nThey cannot be suppressed using `# ty: ignore` without a rule code or `# type: ignore`.\n\n## `@no_type_check` directive\n\nty supports the\n[`@no_type_check`](https://typing.python.org/en/latest/spec/directives.html#no-type-check) decorator\nto suppress all violations inside a function.\n\n```python\nfrom typing import no_type_check\n\ndef sum_three_numbers(a: int, b: int, c: int) -> int:\n    return a + b + c\n\n@no_type_check\ndef main():\n    sum_three_numbers(1, 2)  # no error for the missing argument\n```\n\nDecorating a class with `@no_type_check` isn't supported.\n"
  },
  {
    "path": "docs/type-checking.md",
    "content": "# Type checking\n\nAfter [installing ty](./installation.md), it's time to type check some code!\n\n## Running the type checker\n\nTo run the type checker, use the `check` command:\n\n```shell\nty check\n```\n\n!!! tip\n\n    If you're in a project, you may need to use `uv run` or activate your virtual environment first\n    for ty to find your dependencies.\n\n## Environment discovery\n\nThe type checker needs to discover your installed packages in order to check your use of imported\ndependencies.\n\nty will find installed packages in the active virtual environment (via `VIRTUAL_ENV`) or discover a\nvirtual environment named `.venv` in the project root or working directory. Failing that, ty will\nlook for a `python3` or `python` binary available in `PATH`. Alternatively, the `--python` flag can\nbe provided to ty to explicitly specify a path to a Python interpreter.\n\nSee the [module discovery](./modules.md) documentation for details.\n\n## File selection\n\nty will run on all Python files in the working directory (including subdirectories, recursively).\nIf used from a project, ty will run on all Python files in the project (starting in the directory\nwith the `pyproject.toml`).\n\nYou can also provide specific paths to check:\n\n```shell\nty check example.py\n```\n\nYou can also persistently configure [included and excluded files](./exclusions.md).\n\n## Rule selection and severity\n\nty's type checking diagnostics are often associated with a rule.\n\nty's type checking rules can be configured to your project's needs. See the [rules](./rules.md)\ndocumentation for details.\n\nYou can also suppress specific violations of rules using [suppression comments](./suppression.md).\n\n## Watch mode\n\nty can be run in an incremental watch mode:\n\n```shell\nty check --watch\n```\n\nty will watch files for changes and recheck any affected files — including files that depend on the\nchanged file. ty uses [fine-grained incrementality](./features/language-server.md#fine-grained-incrementality)\nto perform subsequent checks much faster than running `ty check` repeatedly.\n\n## The type system\n\nTo learn more about what makes type checking in ty unique, read about the\n[type system](./features/type-system.md).\n"
  },
  {
    "path": "mkdocs.yml",
    "content": "site_name: ty\ntheme:\n  name: material\n  logo: assets/logo-letter.svg\n  favicon: assets/favicon.ico\n  features:\n    - navigation.path\n    - navigation.instant\n    - navigation.instant.prefetch\n    - navigation.instant.progress\n    - navigation.sections\n    - navigation.indexes\n    - navigation.tracking\n    - content.code.annotate\n    - toc.follow\n    - navigation.footer\n    - navigation.top\n    - content.code.copy\n    - content.tabs.link\n  palette:\n    # https://squidfunk.github.io/mkdocs-material/setup/changing-the-colors/#automatic-light-dark-mode\n    - media: \"(prefers-color-scheme)\"\n      toggle:\n        icon: material/brightness-auto\n        name: Switch to light mode\n    - media: \"(prefers-color-scheme: light)\"\n      scheme: astral-light\n      toggle:\n        icon: material/brightness-7\n        name: Switch to dark mode\n    - media: \"(prefers-color-scheme: dark)\"\n      scheme: astral-dark\n      toggle:\n        icon: material/brightness-4\n        name: Switch to system preference\n  custom_dir: docs/.overrides\nrepo_url: https://github.com/astral-sh/ty\nrepo_name: ty\nsite_author: astral-sh\nsite_url: https://docs.astral.sh/ty/\nsite_dir: site/ty\nsite_description: ty is an extremely fast Python type checker.\nmarkdown_extensions:\n  - admonition\n  - pymdownx.details\n  - pymdownx.snippets:\n  - pymdownx.magiclink:\n  - attr_list:\n  - toc:\n      anchorlink: true\n      anchorlink_class: \"toclink\"\n  - md_in_html:\n  - pymdownx.inlinehilite:\n  - pymdownx.superfences:\n  - markdown.extensions.attr_list:\n  - pymdownx.keys:\n  - pymdownx.tasklist:\n      custom_checkbox: true\n  - pymdownx.highlight:\n      anchor_linenums: true\n  - pymdownx.tabbed:\n      alternate_style: true\nplugins:\n  - search\n  - git-revision-date-localized:\n      timezone: UTC # It can only be in UTC unless the ISO time can include timezone.\n  - llmstxt:\n      markdown_description: |\n        ty is an extremely fast Python type checker and a language server written in Rust. \n        It can type check large Python codebases in seconds, providing fast feedback\n        during development.\n\n        ty includes both a CLI (`ty check`) and a language server (`ty server`) for editor integration.\n\n        When fetching documentation, use explicit `index.md` paths for directories, e.g.,\n        `https://docs.astral.sh/ty/features/index.md`. This returns clean markdown instead\n        of rendered HTML with JS/CSS.\n      sections:\n        Guides:\n          - installation.md\n          - type-checking.md\n          - editors.md\n        Concepts:\n          - configuration.md\n          - modules.md\n          - python-version.md\n          - exclusions.md\n          - rules.md\n          - suppression.md\n        Features:\n          - features/type-system.md\n          - features/diagnostics.md\n          - features/language-server.md\n        Reference:\n          - reference/configuration.md\n          - reference/typing-faq.md\n          - reference/rules.md\n          - reference/cli.md\n          - reference/exit-codes.md\n          - reference/environment.md\n          - reference/editor-settings.md\nextra_css:\n  - stylesheets/extra.css\nextra_javascript:\n  - js/extra.js\nextra:\n  analytics:\n    provider: fathom\n  social:\n    - icon: fontawesome/brands/github\n      link: https://github.com/astral-sh/ty\n    - icon: fontawesome/brands/discord\n      link: https://discord.com/invite/astral-sh\n    - icon: fontawesome/brands/python\n      link: https://pypi.org/project/ty/\n    - icon: fontawesome/brands/x-twitter\n      link: https://x.com/astral_sh\nnav:\n  - Introduction: index.md\n  - Guides:\n      - Installation: installation.md\n      - Type checking: type-checking.md\n      - Editor integration: editors.md\n  - Concepts:\n      - Configuration: configuration.md\n      - Module discovery: modules.md\n      - Python version: python-version.md\n      - File exclusions: exclusions.md\n      - Rules: rules.md\n      - Suppression: suppression.md\n  - Features:\n      - Type system: features/type-system.md\n      - Diagnostics: features/diagnostics.md\n      - Language server: features/language-server.md\n  - Reference:\n      - Configuration: reference/configuration.md\n      - Typing FAQ: reference/typing-faq.md\n      - Rules: reference/rules.md\n      - CLI: reference/cli.md\n      - Exit codes: reference/exit-codes.md\n      - Environment variables: reference/environment.md\n      - Editor settings: reference/editor-settings.md\nvalidation:\n  omitted_files: warn\n  absolute_links: warn\n  unrecognized_links: warn\n"
  },
  {
    "path": "pyproject.toml",
    "content": "[project]\nname = \"ty\"\nversion = \"0.0.24\"\nrequires-python = \">=3.8\"\ndependencies = []\ndescription = \"An extremely fast Python type checker, written in Rust.\"\nreadme = \"README.md\"\nauthors = [{ name = \"Astral Software Inc.\", email = \"hey@astral.sh\" }]\nkeywords = [\"ty\", \"typing\", \"analysis\", \"check\"]\nclassifiers = [\n    \"Development Status :: 4 - Beta\",\n    \"Environment :: Console\",\n    \"Intended Audience :: Developers\",\n    \"Operating System :: OS Independent\",\n    \"License :: OSI Approved :: MIT License\",\n    \"Programming Language :: Python\",\n    \"Programming Language :: Python :: 3.8\",\n    \"Programming Language :: Python :: 3.9\",\n    \"Programming Language :: Python :: 3.10\",\n    \"Programming Language :: Python :: 3.11\",\n    \"Programming Language :: Python :: 3.12\",\n    \"Programming Language :: Python :: 3.13\",\n    \"Programming Language :: Python :: 3.14\",\n    \"Programming Language :: Python :: 3 :: Only\",\n    \"Programming Language :: Rust\",\n    \"Topic :: Software Development :: Quality Assurance\",\n    \"Topic :: Software Development :: Testing\",\n    \"Topic :: Software Development :: Libraries\",\n    \"Topic :: Software Development :: Libraries :: Python Modules\",\n]\n\n[project.urls]\nRepository = \"https://github.com/astral-sh/ty\"\nChangelog = \"https://github.com/astral-sh/ty/blob/main/CHANGELOG.md\"\nReleases = \"https://github.com/astral-sh/ty/releases\"\nDiscord = \"https://discord.gg/astral-sh\"\n\n[build-system]\nrequires = [\"maturin>=1.0,<2.0\"]\nbuild-backend = \"maturin\"\n\n[dependency-groups]\nrelease = [\"rooster\"]\n\n[tool.uv]\ncache-keys = [\n    { file = \"pyproject.toml\" },\n    { file = \"dist-workspace.toml\" },\n    { file = \"ruff/Cargo.toml\" },\n    { file = \"ruff/Cargo.lock\" },\n    { file = \"**/*.rs\" },\n]\n\n[tool.uv.dependency-groups]\nrelease = {requires-python = \">=3.12\"}\n\n[tool.ruff]\nextend-exclude = [\"ruff\"]\nper-file-target-version = { \"scripts/**\" = \"py313\" }\n\n[tool.ruff.lint]\nselect = [\n    \"E\",   # pycodestyle (error)\n    \"F\",   # pyflakes\n    \"B\",   # bugbear\n    \"B9\",\n    \"C4\",  # flake8-comprehensions\n    \"SIM\", # flake8-simplify\n    \"I\",   # isort\n    \"UP\",  # pyupgrade\n    \"PIE\", # flake8-pie\n    \"PGH\", # pygrep-hooks\n    \"PYI\", # flake8-pyi\n    \"RUF\",\n]\n\nignore = [\n    # only relevant if you run a script with `python -0`,\n    # which seems unlikely for any of the scripts in this repo\n    \"B011\",\n    # Leave it to the formatter to split long lines and\n    # the judgement of all of us.\n    \"E501\",\n]\n\n[tool.ruff.lint.isort]\nrequired-imports = [\"from __future__ import annotations\"]\n\n[tool.maturin]\nbindings = \"bin\"\nmanifest-path = \"ruff/crates/ty/Cargo.toml\"\nmodule-name = \"ty\"\npython-source = \"python\"\nstrip = true\ninclude = [\n    { path = \"dist-workspace.toml\", format = [\n        \"sdist\",\n    ] },\n    { path = \"LICENSE\", format = \"sdist\" },\n]\n\n[tool.rooster]\nversion-files = [\n    \"pyproject.toml\",\n    { path = \"dist-workspace.toml\", field = \"workspace.version\", format = \"cargo\" },\n    \"docs/installation.md\",\n]\nsubmodules = [\"ruff\"]\nrequire-labels = [{ submodule = \"ruff\", labels = [\"ty\"] }]\nignore-labels = [\n    \"internal\",\n    \"testing\",\n    \"ci\",\n    \"playground\",\n    \"documentation\",\n    \"release\",\n]\nchangelog-ignore-authors = [\"github-actions\"]\nmajor-labels = [] # We do not use the major version number yet\nminor-labels = [] # We do not use the minor version number yet\nversion-format = \"cargo\"\ntrim-title-prefixes = [\"[ty]\"]\n\n[tool.rooster.section-labels]\n\"Breaking changes\" = [\"breaking\"]\n\"Preview features\" = [\"preview\"]\n\"Bug fixes\" = [\"bug\"]\n\"LSP server\" = [\"server\"]\n\"CLI\" = [\"cli\"]\n\"Configuration\" = [\"configuration\"]\n"
  },
  {
    "path": "python/ty/__init__.py",
    "content": "from __future__ import annotations\n\nfrom ._find_ty import find_ty_bin\n\n__all__ = [\"find_ty_bin\"]\n"
  },
  {
    "path": "python/ty/__main__.py",
    "content": "from __future__ import annotations\n\nimport os\nimport sys\n\nfrom ty import find_ty_bin\n\n\ndef _run() -> None:\n    ty = find_ty_bin()\n\n    if sys.platform == \"win32\":\n        import subprocess\n\n        # Avoid emitting a traceback on interrupt\n        try:\n            completed_process = subprocess.run([ty, *sys.argv[1:]])\n        except KeyboardInterrupt:\n            sys.exit(2)\n\n        sys.exit(completed_process.returncode)\n    else:\n        os.execvp(ty, [ty, *sys.argv[1:]])\n\n\nif __name__ == \"__main__\":\n    _run()\n"
  },
  {
    "path": "python/ty/_find_ty.py",
    "content": "from __future__ import annotations\n\nimport os\nimport sys\nimport sysconfig\n\n\nclass TyNotFound(FileNotFoundError): ...\n\n\ndef find_ty_bin() -> str:\n    \"\"\"Return the ty binary path.\"\"\"\n\n    ty_exe = \"ty\" + sysconfig.get_config_var(\"EXE\")\n\n    targets = [\n        # The scripts directory for the current Python\n        sysconfig.get_path(\"scripts\"),\n        # The scripts directory for the base prefix\n        sysconfig.get_path(\"scripts\", vars={\"base\": sys.base_prefix}),\n        # Above the package root, e.g., from `pip install --prefix` or `uv run --with`\n        (\n            # On Windows, with module path `<prefix>/Lib/site-packages/ty`\n            _join(_matching_parents(_module_path(), \"Lib/site-packages/ty\"), \"Scripts\")\n            if sys.platform == \"win32\"\n            # On Unix,  with module path `<prefix>/lib/python3.13/site-packages/ty`\n            else _join(\n                _matching_parents(_module_path(), \"lib/python*/site-packages/ty\"),\n                \"bin\",\n            )\n        ),\n        # Adjacent to the package root, e.g., from `pip install --target`\n        # with module path `<target>/ty`\n        _join(_matching_parents(_module_path(), \"ty\"), \"bin\"),\n        # The user scheme scripts directory, e.g., `~/.local/bin`\n        sysconfig.get_path(\"scripts\", scheme=_user_scheme()),\n    ]\n\n    seen = []\n    for target in targets:\n        if not target:\n            continue\n        if target in seen:\n            continue\n        seen.append(target)\n        path = os.path.join(target, ty_exe)\n        if os.path.isfile(path):\n            return path\n\n    locations = \"\\n\".join(f\" - {target}\" for target in seen)\n    raise TyNotFound(\n        f\"Could not find the ty binary in any of the following locations:\\n{locations}\\n\"\n    )\n\n\ndef _module_path() -> str | None:\n    path = os.path.dirname(__file__)\n    return path\n\n\ndef _matching_parents(path: str | None, match: str) -> str | None:\n    \"\"\"\n    Return the parent directory of `path` after trimming a `match` from the end.\n    The match is expected to contain `/` as a path separator, while the `path`\n    is expected to use the platform's path separator (e.g., `os.sep`). The path\n    components are compared case-insensitively and a `*` wildcard can be used\n    in the `match`.\n    \"\"\"\n    from fnmatch import fnmatch\n\n    if not path:\n        return None\n    parts = path.split(os.sep)\n    match_parts = match.split(\"/\")\n    if len(parts) < len(match_parts):\n        return None\n\n    if not all(\n        fnmatch(part, match_part)\n        for part, match_part in zip(reversed(parts), reversed(match_parts))\n    ):\n        return None\n\n    return os.sep.join(parts[: -len(match_parts)])\n\n\ndef _join(path: str | None, *parts: str) -> str | None:\n    if not path:\n        return None\n    return os.path.join(path, *parts)\n\n\ndef _user_scheme() -> str:\n    if sys.version_info >= (3, 10):\n        user_scheme = sysconfig.get_preferred_scheme(\"user\")\n    elif os.name == \"nt\":\n        user_scheme = \"nt_user\"\n    elif sys.platform == \"darwin\" and sys._framework:  # ty: ignore[unresolved-attribute]\n        user_scheme = \"osx_framework_user\"\n    else:\n        user_scheme = \"posix_user\"\n    return user_scheme\n"
  },
  {
    "path": "python/ty/py.typed",
    "content": "\n"
  },
  {
    "path": "scripts/autogenerate_files.sh",
    "content": "#!/usr/bin/env sh\n#\n# Generate files and copy documentation from Ruff.\n#\n# Usage\n#\n#   ./scripts/autogenerate-files.sh\n#\nset -eu\n\nscript_root=\"$(realpath \"$(dirname \"$0\")\")\"\nproject_root=\"$(dirname \"$script_root\")\"\ncd \"$project_root\"\n\necho \"Updating lockfile...\"\nuv lock\n\necho \"Copying reference documentation from Ruff...\"\ncp ./ruff/crates/ty/docs/cli.md ./docs/reference/\ncp ./ruff/crates/ty/docs/configuration.md ./docs/reference/\ncp ./ruff/crates/ty/docs/rules.md ./docs/reference/\ncp ./ruff/crates/ty/docs/environment.md ./docs/reference/\n\necho \"Documentation has been copied from Ruff submodule\"\n"
  },
  {
    "path": "scripts/release.sh",
    "content": "#!/usr/bin/env sh\n#\n# Prepare a release.\n#\n# Usage\n#\n#   ./scripts/release.sh [rooster-args ...]\n#\nset -eu\n\necho \"Checking Ruff submodule status...\"\nif git -C ruff diff --quiet; then\n    echo \"Ruff submodule is clean; continuing...\"\nelse\n    echo \"Ruff submodule has uncommitted changes; aborting!\"\n    exit 1\nfi\n\nruff_head=$(git -C ruff rev-parse --abbrev-ref HEAD)\ncase \"${ruff_head}\" in\n    \"HEAD\")\n        echo \"Ruff submodule has detached HEAD; switching to main...\"\n        git -C ruff checkout main > /dev/null 2>&1\n        ;;\n    \"main\")\n        echo \"Ruff submodule is on main branch; continuing...\"\n        ;;\n    *)\n        echo \"Ruff submodule is on branch ${ruff_head} but must be on main; aborting!\"\n        exit 1\n        ;;\nesac\n\n\n# Save the current typeshed source commit before updating ruff,\n# so we can generate a typeshed diff link for the changelog later.\ntypeshed_commit_file=\"ruff/crates/ty_vendored/vendor/typeshed/source_commit.txt\"\nold_typeshed_commit=\"\"\nif [ -f \"$typeshed_commit_file\" ]; then\n    old_typeshed_commit=$(cat \"$typeshed_commit_file\")\nfi\n\necho \"Updating Ruff to the latest commit...\"\ngit -C ruff pull origin main\ngit add ruff\n\nscript_root=\"$(realpath \"$(dirname \"$0\")\")\"\nproject_root=\"$(dirname \"$script_root\")\"\n\necho \"Running rooster...\"\ncd \"$project_root\"\n\n# Generate the changelog and bump versions\nuv run --isolated --only-group release \\\n    rooster release \"$@\"\n\n# If the typeshed source commit changed and the changelog mentions a typeshed\n# sync, append a link to the typeshed diff so reviewers can see what changed.\nif [ -n \"$old_typeshed_commit\" ] && [ -f \"$typeshed_commit_file\" ]; then\n    new_typeshed_commit=$(cat \"$typeshed_commit_file\")\n    if [ \"$old_typeshed_commit\" != \"$new_typeshed_commit\" ]; then\n        typeshed_diff_link=\"[Typeshed diff](https://github.com/python/typeshed/compare/${old_typeshed_commit}...${new_typeshed_commit})\"\n        # Match lines like \"- Sync vendored typeshed stubs ([#NNNN](...))\".\n        # The pattern anchors on the trailing \"))$\" so it won't match lines\n        # that already have a typeshed diff link appended.\n        # Use a temp file instead of `sed -i` for macOS/Linux portability.\n        sed \"s|\\(- Sync vendored typeshed stubs (.*)\\))$|\\1). ${typeshed_diff_link}|\" CHANGELOG.md > CHANGELOG.md.tmp\n        mv CHANGELOG.md.tmp CHANGELOG.md\n    fi\nfi\n\n\"${script_root}/autogenerate_files.sh\"\ngit add ./docs/reference\n"
  },
  {
    "path": "scripts/transform_readme.py",
    "content": "\"\"\"Transform the README.md to support a specific deployment target.\n\nBy default, we assume that our README.md will be rendered on GitHub. However,\nPyPI includes the README with different rendering.\n\"\"\"\n\nfrom __future__ import annotations\n\nimport re\nimport tomllib\nimport urllib.parse\nfrom pathlib import Path\n\n# The benchmark SVG includes a CSS media query that adapts to light/dark mode.\n# PyPI doesn't support this, so we replace it with a light-only version.\n# See: https://github.com/pypi/warehouse/issues/11251\nBENCHMARK_URL = \"https://raw.githubusercontent.com/astral-sh/ty/main/docs/assets/ty-benchmark-cli.svg\"\nBENCHMARK_URL_LIGHT = \"https://raw.githubusercontent.com/astral-sh/ty/main/docs/assets/ty-benchmark-cli-light.svg\"\n\n\ndef main() -> None:\n    \"\"\"Modify the README.md to support PyPI.\"\"\"\n    # Read the current version from the `dist-workspace.toml`.\n    with Path(\"dist-workspace.toml\").open(mode=\"rb\") as fp:\n        # Parse the TOML.\n        dist_workspace = tomllib.load(fp)\n        if \"workspace\" in dist_workspace and \"version\" in dist_workspace[\"workspace\"]:\n            version = dist_workspace[\"workspace\"][\"version\"]\n        else:\n            raise ValueError(\"Version not found in dist-workspace.toml\")\n\n    content = Path(\"README.md\").read_text(encoding=\"utf8\")\n\n    # Replace the benchmark image URL with the light-only version for PyPI.\n    if BENCHMARK_URL not in content:\n        msg = \"README.md is not in the expected format (benchmark image not found).\"\n        raise ValueError(msg)\n    content = content.replace(BENCHMARK_URL, BENCHMARK_URL_LIGHT)\n\n    # Replace relative src=\"./...\" attributes with absolute GitHub raw URLs.\n    def replace_src(match: re.Match) -> str:\n        path = match.group(1).lstrip(\"./\")\n        return f'src=\"https://raw.githubusercontent.com/astral-sh/ty/{version}/{path}\"'\n\n    content = re.sub(r'src=\"(\\./[^\"]+)\"', replace_src, content)\n\n    # Replace any relative URLs (e.g., `[CONTRIBUTING.md`) with absolute URLs.\n    def replace(match: re.Match) -> str:\n        url = match.group(1)\n        if not url.startswith(\"http\"):\n            url = urllib.parse.urljoin(\n                f\"https://github.com/astral-sh/ty/blob/{version}/README.md\", url\n            )\n        return f\"]({url})\"\n\n    content = re.sub(r\"]\\(([^)]+)\\)\", replace, content)\n\n    # Replace any GitHub admonitions\n    def replace(match: re.Match) -> str:\n        name = match.group(1)\n        return f\"> {name}:\"\n\n    content = re.sub(r\"> \\[\\!(\\w*)\\]\", replace, content)\n\n    with Path(\"README.md\").open(\"w\", encoding=\"utf8\") as fp:\n        fp.write(content)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "scripts/update_schemastore.py",
    "content": "\"\"\"Update ty.json in schemastore.\n\nThis script will clone `astral-sh/schemastore`, update the schema and push the changes\nto a new branch tagged with the ty git hash. You should see a URL to create the PR\nto schemastore in the CLI.\n\nUsage:\n\n    uv run --only-dev scripts/update_schemastore.py\n\"\"\"\n\nfrom __future__ import annotations\n\nimport enum\nimport json\nfrom pathlib import Path\nfrom subprocess import check_call, check_output\nfrom tempfile import TemporaryDirectory\nfrom typing import NamedTuple, assert_never\n\n# The remote URL for the `ty` repository.\nTY_REPO = \"https://github.com/astral-sh/ty\"\n\n# The path to the root of the `ty` repository.\nTY_ROOT = Path(__file__).parent.parent\n\n# The path to the JSON schema in the `ty` repository.\nTY_SCHEMA = TY_ROOT / \"ruff\" / \"ty.schema.json\"\n\n# The path to the JSON schema in the `schemastore` repository.\nTY_JSON = Path(\"schemas/json/ty.json\")\n\n\nclass SchemastoreRepos(NamedTuple):\n    fork: str\n    upstream: str\n\n\nclass GitProtocol(enum.Enum):\n    SSH = \"ssh\"\n    HTTPS = \"https\"\n\n    def schemastore_repos(self) -> SchemastoreRepos:\n        match self:\n            case GitProtocol.SSH:\n                return SchemastoreRepos(\n                    fork=\"git@github.com:astral-sh/schemastore.git\",\n                    upstream=\"git@github.com:SchemaStore/schemastore.git\",\n                )\n            case GitProtocol.HTTPS:\n                return SchemastoreRepos(\n                    fork=\"https://github.com/astral-sh/schemastore.git\",\n                    upstream=\"https://github.com/SchemaStore/schemastore.git\",\n                )\n            case _:\n                assert_never(self)\n\n\ndef update_schemastore(\n    schemastore_path: Path, schemastore_repos: SchemastoreRepos\n) -> None:\n    if not (schemastore_path / \".git\").is_dir():\n        check_call(\n            [\"git\", \"clone\", schemastore_repos.fork, schemastore_path, \"--depth=1\"],\n        )\n        check_call(\n            [\n                \"git\",\n                \"remote\",\n                \"add\",\n                \"upstream\",\n                schemastore_repos.upstream,\n            ],\n            cwd=schemastore_path,\n        )\n\n    # Create a new branch tagged with the current ty commit up to date with the latest\n    # upstream schemastore\n    check_call([\"git\", \"fetch\", \"upstream\"], cwd=schemastore_path)\n    current_sha = check_output(\n        [\"git\", \"rev-parse\", \"HEAD\"], text=True, cwd=TY_ROOT\n    ).strip()\n    branch = f\"update-ty-{current_sha}\"\n    check_call(\n        [\"git\", \"switch\", \"-c\", branch],\n        cwd=schemastore_path,\n    )\n    check_call(\n        [\"git\", \"reset\", \"--hard\", \"upstream/master\"],\n        cwd=schemastore_path,\n    )\n\n    # Run npm ci\n    src = schemastore_path / \"src\"\n    check_call([\"npm\", \"ci\", \"--ignore-scripts\"], cwd=schemastore_path)\n\n    # Update the schema and format appropriately\n    schema = json.loads(TY_SCHEMA.read_text())\n    schema[\"$id\"] = \"https://json.schemastore.org/ty.json\"\n    (src / TY_JSON).write_text(\n        json.dumps(dict(schema.items()), indent=2, ensure_ascii=False),\n    )\n    check_call(\n        [\n            \"../node_modules/prettier/bin/prettier.cjs\",\n            \"--plugin\",\n            \"prettier-plugin-sort-json\",\n            \"--write\",\n            TY_JSON,\n        ],\n        cwd=src,\n    )\n\n    # Check if the schema has changed\n    # https://stackoverflow.com/a/9393642/3549270\n    if check_output([\"git\", \"status\", \"-s\"], cwd=schemastore_path).strip():\n        # Schema has changed, commit and push\n        commit_url = f\"{TY_REPO}/commit/{current_sha}\"\n        commit_body = f\"This updates ty's JSON schema to [{current_sha}]({commit_url})\"\n        # https://stackoverflow.com/a/22909204/3549270\n        check_call([\"git\", \"add\", (src / TY_JSON).as_posix()], cwd=schemastore_path)\n        check_call(\n            [\n                \"git\",\n                \"commit\",\n                \"-m\",\n                \"Update ty's JSON schema\",\n                \"-m\",\n                commit_body,\n            ],\n            cwd=schemastore_path,\n        )\n        # This should show the link to create a PR\n        check_call(\n            [\"git\", \"push\", \"--set-upstream\", \"origin\", branch, \"--force\"],\n            cwd=schemastore_path,\n        )\n    else:\n        print(\"No changes\")\n\n\ndef determine_git_protocol(argv: list[str] | None = None) -> GitProtocol:\n    import argparse\n\n    parser = argparse.ArgumentParser(\n        description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter\n    )\n    parser.add_argument(\n        \"--proto\",\n        choices=[proto.value for proto in GitProtocol],\n        default=\"https\",\n        help=\"Protocol to use for git authentication\",\n    )\n    args = parser.parse_args(argv)\n    return GitProtocol(args.proto)\n\n\ndef main() -> None:\n    expected_ruff_revision = check_output(\n        [\"git\", \"ls-tree\", \"main\", \"--format\", \"%(objectname)\", \"ruff\"], cwd=TY_ROOT\n    ).strip()\n    actual_ruff_revision = check_output(\n        [\"git\", \"-C\", \"ruff\", \"rev-parse\", \"HEAD\"], cwd=TY_ROOT\n    ).strip()\n\n    if expected_ruff_revision != actual_ruff_revision:\n        print(\n            f\"The ruff submodule is at {actual_ruff_revision} but main expects {expected_ruff_revision}\"\n        )\n        match input(\n            \"How do you want to proceed (u=reset submodule, n=abort, y=continue)? \"\n        ):\n            case \"u\":\n                check_call(\n                    [\"git\", \"-C\", \"ruff\", \"reset\", \"--hard\", expected_ruff_revision],\n                    cwd=TY_ROOT,\n                )\n            case \"n\":\n                return\n            case \"y\":\n                ...\n            case command:\n                print(f\"Invalid input '{command}', abort\")\n                return\n\n    schemastore_repos = determine_git_protocol().schemastore_repos()\n    schemastore_existing = TY_ROOT / \"schemastore\"\n    if schemastore_existing.is_dir():\n        update_schemastore(schemastore_existing, schemastore_repos)\n    else:\n        with TemporaryDirectory(prefix=\"ty-schemastore-\") as temp_dir:\n            update_schemastore(Path(temp_dir), schemastore_repos)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  }
]