diff --git a/.github/actionlint.yaml b/.github/actionlint.yaml index 6c85e2cb4124a..8b9e24ce59700 100644 --- a/.github/actionlint.yaml +++ b/.github/actionlint.yaml @@ -13,8 +13,3 @@ self-hosted-runner: - github-windows-2025-x86_64-8 - github-windows-2025-x86_64-16 - codspeed-macro - -paths: - ".github/workflows/mypy_primer.yaml": - ignore: - - 'constant expression "false" in condition. remove the if: section' diff --git a/.github/mypy-primer-ty.toml b/.github/ty-ecosystem.toml similarity index 81% rename from .github/mypy-primer-ty.toml rename to .github/ty-ecosystem.toml index 578712348647c..69c2b83665c43 100644 --- a/.github/mypy-primer-ty.toml +++ b/.github/ty-ecosystem.toml @@ -1,5 +1,5 @@ #:schema ../ty.schema.json -# Configuration overrides for the mypy primer run +# Configuration overrides for ty ecosystem analysis # Enable off-by-default rules. [rules] diff --git a/.github/workflows/memory_report.yaml b/.github/workflows/memory_report.yaml index 438a28e8677b8..a63a5e2552e50 100644 --- a/.github/workflows/memory_report.yaml +++ b/.github/workflows/memory_report.yaml @@ -20,7 +20,7 @@ on: - "!**.md" - "!**.snap" # It's tempting to skip all Python files in every directory, - # but changes to Python files in `ty_vendored` can affect the output of mypy_primer, + # but changes to Python files in `ty_vendored` can affect the output of ecosystem runs, # so we apply a narrow exemption for all files in the corpus directory instead. - "!crates/ty_python_semantic/resources/corpus/**" diff --git a/.github/workflows/mypy_primer.yaml b/.github/workflows/mypy_primer.yaml deleted file mode 100644 index 96e4266789109..0000000000000 --- a/.github/workflows/mypy_primer.yaml +++ /dev/null @@ -1,124 +0,0 @@ -name: Run mypy_primer - -permissions: {} - -on: - pull_request: - # The default for `pull_request` is to trigger on `synchronize`, `opened` and `reopened`. - # We also add `labeled` here so that the workflow triggers when a label is initially added. - types: - - labeled - - synchronize - - opened - - reopened - -concurrency: - group: mypy-primer-${{ github.ref_name }}-${{ github.event.pull_request.number || github.sha }} - cancel-in-progress: ${{ github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'mypy_primer') }} - -defaults: - run: - shell: bash - -env: - CARGO_INCREMENTAL: 0 - CARGO_NET_RETRY: 10 - CARGO_TERM_COLOR: always - RUSTUP_MAX_RETRIES: 10 - RUST_BACKTRACE: 1 - -jobs: - mypy_primer: - name: Run mypy_primer - runs-on: ${{ github.repository == 'astral-sh/ruff' && 'depot-ubuntu-22.04-32' || 'ubuntu-latest' }} - timeout-minutes: 20 - if: contains(github.event.pull_request.labels.*.name, 'mypy_primer') - steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - path: ruff - fetch-depth: 0 - persist-credentials: false - - - name: Install the latest version of uv - uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0 - with: - version: "0.10.10" - - - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 - with: - shared-key: "mypy-primer" - workspaces: "ruff" - - - name: Install Rust toolchain - run: rustup show - - - name: Run mypy_primer - env: - PRIMER_SELECTOR: crates/ty_python_semantic/resources/primer/good.txt - CLICOLOR_FORCE: "1" - DIFF_FILE: mypy_primer.diff - run: | - cd ruff - scripts/mypy_primer.sh - - # NOTE: astral-sh-bot uses this artifact to post comments on PRs. - # Make sure to update the bot if you rename the artifact. - - name: Upload diff - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 - with: - name: mypy_primer_diff - path: mypy_primer.diff - - # Runs mypy twice against the same ty version to catch any non-deterministic behavior (ideally). - # The job is disabled for now because there are some non-deterministic diagnostics. - mypy_primer_same_revision: - name: Run mypy_primer on same revision - runs-on: ${{ github.repository == 'astral-sh/ruff' && 'depot-ubuntu-22.04-32' || 'ubuntu-latest' }} - timeout-minutes: 20 - # TODO: Enable once we fixed the non-deterministic diagnostics - if: false && contains(github.event.pull_request.labels.*.name, 'mypy_primer') - steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - path: ruff - fetch-depth: 0 - persist-credentials: false - - - name: Install the latest version of uv - uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0 - with: - version: "0.10.10" - - - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 - with: - workspaces: "ruff" - shared-key: "mypy-primer" - - - name: Install Rust toolchain - run: rustup show - - - name: Run determinism check - env: - BASE_REVISION: ${{ github.event.pull_request.head.sha }} - PRIMER_SELECTOR: crates/ty_python_semantic/resources/primer/good.txt - CLICOLOR_FORCE: "1" - DIFF_FILE: mypy_primer_determinism.diff - run: | - cd ruff - scripts/mypy_primer.sh - - - name: Check for non-determinism - run: | - # Remove ANSI color codes for checking - sed -e 's/\x1b\[[0-9;]*m//g' mypy_primer_determinism.diff > mypy_primer_determinism_clean.diff - - # Check if there are any differences (non-determinism) - if [ -s mypy_primer_determinism_clean.diff ]; then - echo "ERROR: Non-deterministic output detected!" - echo "The following differences were found when running ty twice on the same commit:" - cat mypy_primer_determinism_clean.diff - exit 1 - else - echo "✓ Output is deterministic" - fi diff --git a/.github/workflows/ty-ecosystem-analyzer.yaml b/.github/workflows/ty-ecosystem-analyzer.yaml index ba21c95446447..c82284d417974 100644 --- a/.github/workflows/ty-ecosystem-analyzer.yaml +++ b/.github/workflows/ty-ecosystem-analyzer.yaml @@ -15,9 +15,8 @@ on: - "crates/ruff_python_ast" - "crates/ruff_python_parser" - ".github/workflows/ty-ecosystem-analyzer.yaml" - - ".github/workflows/mypy_primer.yaml" - - "scripts/mypy_primer.sh" - - "scripts/mypy_primer_selector.py" + - ".github/ty-ecosystem.toml" + - "crates/ty_python_semantic/resources/primer/**" - "Cargo.lock" - "!**.md" - "!**.snap" @@ -69,9 +68,9 @@ jobs: run: | cd ruff - echo "Enabling configuration overloads (see .github/mypy-primer-ty.toml)" + echo "Enabling configuration overloads (see .github/ty-ecosystem.toml)" mkdir -p ~/.config/ty - cp .github/mypy-primer-ty.toml ~/.config/ty/ty.toml + cp .github/ty-ecosystem.toml ~/.config/ty/ty.toml echo "new commit" git checkout -b new_commit "$GITHUB_SHA" diff --git a/.github/workflows/ty-ecosystem-report.yaml b/.github/workflows/ty-ecosystem-report.yaml index bf4705a4e374c..081514b242721 100644 --- a/.github/workflows/ty-ecosystem-report.yaml +++ b/.github/workflows/ty-ecosystem-report.yaml @@ -50,9 +50,9 @@ jobs: run: | cd ruff - echo "Enabling configuration overloads (see .github/mypy-primer-ty.toml)" + echo "Enabling configuration overloads (see .github/ty-ecosystem.toml)" mkdir -p ~/.config/ty - cp .github/mypy-primer-ty.toml ~/.config/ty/ty.toml + cp .github/ty-ecosystem.toml ~/.config/ty/ty.toml cd .. diff --git a/.github/workflows/typing_conformance.yaml b/.github/workflows/typing_conformance.yaml index d362edb514e8f..00938f1046eef 100644 --- a/.github/workflows/typing_conformance.yaml +++ b/.github/workflows/typing_conformance.yaml @@ -19,8 +19,8 @@ on: - "Cargo.lock" - "!**.md" - "!**.snap" - # It's tempting to skip all Python files in every directory, - # but changes to Python files in `ty_vendored` can affect the output of mypy_primer, + # It's tempting to skip all Python files in every directory, but changes to + # Python files in `ty_vendored` can affect the output of the ecosystem analysis, # so we apply a narrow exemption for all files in the corpus directory instead. - "!crates/ty_python_semantic/resources/corpus/**" diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 08ca5a502a2c8..9441658a198da 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -52,14 +52,6 @@ repos: language: system types: [rust] priority: 0 - - id: check-mypy-primer-sha - name: Check mypy-primer SHA is in sync - entry: python3 scripts/check_mypy_primer_sha.py - language: system - pass_filenames: false - files: ^scripts/(mypy_primer\.sh|setup_primer_project\.py)$ - priority: 0 - # Prettier - repo: https://github.com/rbubley/mirrors-prettier rev: v3.8.1 diff --git a/crates/ruff_benchmark/benches/ty_walltime.rs b/crates/ruff_benchmark/benches/ty_walltime.rs index d2f14129c816c..67d40295ab9a5 100644 --- a/crates/ruff_benchmark/benches/ty_walltime.rs +++ b/crates/ruff_benchmark/benches/ty_walltime.rs @@ -224,8 +224,8 @@ static STATIC_FRAME: Benchmark = Benchmark::new( repository: "https://github.com/static-frame/static-frame", commit: "34962b41baca5e7f98f5a758d530bff02748a421", paths: &["static_frame"], - // N.B. `arraykit` is installed as a dependency during mypy_primer runs, - // but it takes much longer to be installed in a Codspeed run than it does in a mypy_primer run + // N.B. `arraykit` is installed as a dependency during ecosystem runs, + // but it takes much longer to be installed in a Codspeed run // (seems to be built from source on the Codspeed CI runners for some reason). dependencies: &["numpy"], max_dep_date: "2025-08-09", diff --git a/crates/ty/CONTRIBUTING.md b/crates/ty/CONTRIBUTING.md index 6633a7a7cf1e5..305c7f2da8c55 100644 --- a/crates/ty/CONTRIBUTING.md +++ b/crates/ty/CONTRIBUTING.md @@ -142,11 +142,11 @@ The property tests do not run in CI on every PR, just once daily. It is advisabl locally after modifying core type relation methods (`is_subtype_of`, `is_equivalent_to`, etc.) to ensure that the changes do not break any of the properties. -## Ecosystem CI (mypy-primer) +## Ecosystem CI (`ecosystem-analyzer`) -GitHub Actions will run your changes against a number of real-world projects from GitHub and -report on any linter or formatter differences. See [`crates/ty/docs/mypy_primer.md`](./docs/mypy_primer.md) -for instructions on running these checks locally. +GitHub Actions will run your changes against a number of real-world projects from GitHub and report +any differences in ty's diagnostic output. You can use [`setup_primer_project.py`](./scripts/setup_primer_project.py) +to reproduce the same testing conditions locally. ## Coding guidelines diff --git a/crates/ty/docs/mypy_primer.md b/crates/ty/docs/mypy_primer.md deleted file mode 100644 index bd14bfaa96f20..0000000000000 --- a/crates/ty/docs/mypy_primer.md +++ /dev/null @@ -1,69 +0,0 @@ -# Running `mypy_primer` - -## Basics - -`mypy_primer` can be run using `uvx --from "…" mypy_primer`. For example, to see the help message, run: - -```sh -uvx --from "git+https://github.com/hauntsaninja/mypy_primer" mypy_primer -h -``` - -Alternatively, you can install the forked version of `mypy_primer` using: - -```sh -uv tool install "git+https://github.com/hauntsaninja/mypy_primer" -``` - -and then run it using `uvx mypy_primer` or just `mypy_primer`, if your `PATH` is set up accordingly (see: [Tool executables]). - -## Showing the diagnostics diff between two Git revisions - -To show the diagnostics diff between two Git revisions (e.g. your feature branch and `main`), run: - -```sh -mypy_primer \ - --type-checker ty \ - --old origin/main \ - --new my/feature \ - --debug \ - --output concise \ - --project-selector '/black$' -``` - -This will show the diagnostics diff for the `black` project between the `main` branch and your `my/feature` branch. To run the -diff for all projects we currently enable in CI, use `--project-selector "$(uv run scripts/mypy_primer_selector.py crates/ty_python_semantic/resources/primer/good.txt)"`. - -You can also take a look at the [full list of ecosystem projects]. Note that some of them might still need a `ty_paths` configuration -option to work correctly. - -## Avoiding recompilation - -If you want to run `mypy_primer` repeatedly, e.g. for different projects, but for the same combination of `--old` and `--new`, you -can use set the `MYPY_PRIMER_NO_REBUILD` environment variable to avoid recompilation of ty: - -```sh -MYPY_PRIMER_NO_REBUILD=1 mypy_primer … -``` - -## Running from a local copy of the repository - -If you are working on a local branch, you can use `mypy_primer`'s `--repo` option to specify the path to your local copy of the `ruff` repository. -This allows `mypy_primer` to check out local branches: - -```sh -mypy_primer --type-checker ty \ - --repo ./ruff \ - --old main \ - --new my/local-branch \ - --project-selector '/beartype$' \ - --debug \ - --output concise -``` - -Notes: - -- You might need to clean up `/tmp/mypy_primer` in order for this to work correctly. -- This must be run from _outside_ the `ruff` repo. - -[full list of ecosystem projects]: https://github.com/hauntsaninja/mypy_primer/blob/master/mypy_primer/projects.py -[tool executables]: https://docs.astral.sh/uv/concepts/tools/#tool-executables diff --git a/crates/ty_python_semantic/src/types/tuple.rs b/crates/ty_python_semantic/src/types/tuple.rs index e197814f3989c..99f8a28c148a4 100644 --- a/crates/ty_python_semantic/src/types/tuple.rs +++ b/crates/ty_python_semantic/src/types/tuple.rs @@ -198,7 +198,7 @@ impl<'db> TupleType<'db> { } // N.B. If this method is not Salsa-tracked, we take 10 minutes to check - // `static-frame` as part of a mypy_primer run! This is because it's called + // `static-frame` as part of the ecosystem analysis. This is because it's called // from `NominalInstanceType::class()`, which is a very hot method. #[salsa::tracked(cycle_initial=to_class_type_cycle_initial, heap_size=ruff_memory_usage::heap_size)] pub(crate) fn to_class_type(self, db: &'db dyn Db) -> ClassType<'db> { diff --git a/scripts/check_mypy_primer_sha.py b/scripts/check_mypy_primer_sha.py deleted file mode 100644 index 06b5287969ba8..0000000000000 --- a/scripts/check_mypy_primer_sha.py +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env python3 -"""Check that the mypy-primer SHA in setup_primer_project.py matches mypy_primer.sh.""" - -from __future__ import annotations - -import re -import sys -from pathlib import Path - -ROOT = Path(__file__).parent.parent - -SH_FILE = ROOT / "scripts" / "mypy_primer.sh" -PY_FILE = ROOT / "scripts" / "setup_primer_project.py" - -SHA_RE = re.compile(r"mypy_primer@([0-9a-f]{40})") -REV_RE = re.compile(r'rev\s*=\s*"([0-9a-f]{40})"') - - -def extract(pattern: re.Pattern[str], path: Path, label: str) -> str: - m = pattern.search(path.read_text()) - if m is None: - print(f"error: could not find {label} in {path}", file=sys.stderr) - sys.exit(1) - return m.group(1) - - -sh_sha = extract(SHA_RE, SH_FILE, "mypy_primer SHA") -py_sha = extract(REV_RE, PY_FILE, "mypy-primer rev") - -if sh_sha != py_sha: - print( - f"error: mypy-primer SHA mismatch\n" - f" {SH_FILE.relative_to(ROOT)}: {sh_sha}\n" - f" {PY_FILE.relative_to(ROOT)}: {py_sha}\n" - f"Update the rev in {PY_FILE.relative_to(ROOT)} to match {SH_FILE.relative_to(ROOT)}.", - file=sys.stderr, - ) - sys.exit(1) - -print(f"ok: mypy-primer SHA is in sync ({sh_sha[:12]}...)") diff --git a/scripts/mypy_primer.sh b/scripts/mypy_primer.sh deleted file mode 100755 index c86b94b230497..0000000000000 --- a/scripts/mypy_primer.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env bash -set -eu - -echo "Enabling mypy primer specific configuration overloads (see .github/mypy-primer-ty.toml)" -mkdir -p ~/.config/ty -cp .github/mypy-primer-ty.toml ~/.config/ty/ty.toml - -PRIMER_SELECTOR="$(uv run scripts/mypy_primer_selector.py "${PRIMER_SELECTOR}")" - -echo "new commit" -git rev-list --format=%s --max-count=1 "${GITHUB_SHA}" - -if [ -z "${BASE_REVISION:-}" ]; then - BASE_REVISION="$(git merge-base "${GITHUB_SHA}" "origin/${GITHUB_BASE_REF}")" -fi -git checkout -b base_commit "${BASE_REVISION}" -echo "base commit" -git rev-list --format=%s --max-count=1 base_commit - -cd .. - -echo "Project selector: ${PRIMER_SELECTOR}" -# Allow the exit code to be 0 or 1, only fail for actual mypy_primer crashes/bugs -uvx \ - --from="git+https://github.com/hauntsaninja/mypy_primer@850d65d9da947ef9e02498b6f07598e7c8401641" \ - mypy_primer \ - --repo ruff \ - --type-checker ty \ - --cargo-profile profiling \ - --old base_commit \ - --new "${GITHUB_SHA}" \ - --project-selector "${PRIMER_SELECTOR}" \ - --output concise \ - --debug > "${DIFF_FILE}" || [ $? -eq 1 ] - -# Output diff with ANSI color codes -cat "${DIFF_FILE}" - -# Remove ANSI color codes before uploading -sed -ie 's/\x1b\[[0-9;]*m//g' "${DIFF_FILE}" diff --git a/scripts/mypy_primer_selector.py b/scripts/mypy_primer_selector.py deleted file mode 100644 index 38c0c6650b80b..0000000000000 --- a/scripts/mypy_primer_selector.py +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env python3 - -from __future__ import annotations - -import argparse -import re -from pathlib import Path - -CPYTHON_PROJECTS = { - "CPython (Argument Clinic)": "cpython", - "CPython (cases_generator)": "cpython", - "CPython (peg_generator)": "cpython", -} - - -def main() -> None: - parser = argparse.ArgumentParser( - description="Build a mypy_primer project-selector regex from a project list." - ) - parser.add_argument("project_list", type=Path) - args = parser.parse_args() - - projects: list[str] = [] - seen: set[str] = set() - - for line in args.project_list.read_text().splitlines(): - project = line.strip() - if not project: - continue - - selector = CPYTHON_PROJECTS.get(project, project) - if selector not in seen: - projects.append(re.escape(selector)) - seen.add(selector) - - print(f"/({'|'.join(projects)})$") - - -if __name__ == "__main__": - main() diff --git a/scripts/setup_primer_project.py b/scripts/setup_primer_project.py old mode 100755 new mode 100644 index c1530f76b96e1..deb9ce21d4b6b --- a/scripts/setup_primer_project.py +++ b/scripts/setup_primer_project.py @@ -5,7 +5,7 @@ # dependencies = ["mypy-primer"] # # [tool.uv.sources] -# mypy-primer = { git = "https://github.com/hauntsaninja/mypy_primer", rev = "850d65d9da947ef9e02498b6f07598e7c8401641" } +# mypy-primer = { git = "https://github.com/hauntsaninja/mypy_primer" } # /// """Clone a mypy-primer project and set up a virtualenv with its dependencies installed.