Compare commits

..

2 Commits

Author SHA1 Message Date
Aria Desires
a9526fe0a5 serde_json is no longer optional 2025-12-08 15:17:28 -05:00
Aria Desires
e733a87bd7 Teach ty check to ask uv to sync the venv of a PEP-723 script 2025-12-08 15:00:37 -05:00
1909 changed files with 26504 additions and 75021 deletions

View File

@@ -5,4 +5,4 @@ rustup component add clippy rustfmt
cargo install cargo-insta cargo install cargo-insta
cargo fetch cargo fetch
pip install maturin prek pip install maturin pre-commit

1
.gitattributes vendored
View File

@@ -22,7 +22,6 @@ crates/ruff_linter/resources/test/fixtures/pyupgrade/UP018_CR.py text eol=cr
crates/ruff_linter/resources/test/fixtures/pyupgrade/UP018_LF.py text eol=lf crates/ruff_linter/resources/test/fixtures/pyupgrade/UP018_LF.py text eol=lf
crates/ruff_python_parser/resources/inline linguist-generated=true crates/ruff_python_parser/resources/inline linguist-generated=true
crates/ty_python_semantic/resources/mdtest/external/*.lock linguist-generated=true
ruff.schema.json -diff linguist-generated=true text=auto eol=lf ruff.schema.json -diff linguist-generated=true text=auto eol=lf
ty.schema.json -diff linguist-generated=true text=auto eol=lf ty.schema.json -diff linguist-generated=true text=auto eol=lf

10
.github/CODEOWNERS vendored
View File

@@ -20,11 +20,9 @@
# ty # ty
/crates/ty* @carljm @MichaReiser @AlexWaygood @sharkdp @dcreager /crates/ty* @carljm @MichaReiser @AlexWaygood @sharkdp @dcreager
/crates/ruff_db/ @carljm @MichaReiser @sharkdp @dcreager /crates/ruff_db/ @carljm @MichaReiser @sharkdp @dcreager
/crates/ty_project/ @carljm @MichaReiser @sharkdp @dcreager @Gankra /crates/ty_project/ @carljm @MichaReiser @sharkdp @dcreager
/crates/ty_ide/ @carljm @MichaReiser @AlexWaygood @sharkdp @dcreager @Gankra /crates/ty_server/ @carljm @MichaReiser @sharkdp @dcreager
/crates/ty_server/ @carljm @MichaReiser @sharkdp @dcreager @Gankra
/crates/ty/ @carljm @MichaReiser @sharkdp @dcreager /crates/ty/ @carljm @MichaReiser @sharkdp @dcreager
/crates/ty_wasm/ @carljm @MichaReiser @sharkdp @dcreager @Gankra /crates/ty_wasm/ @carljm @MichaReiser @sharkdp @dcreager
/scripts/ty_benchmark/ @carljm @MichaReiser @AlexWaygood @sharkdp @dcreager /scripts/ty_benchmark/ @carljm @MichaReiser @AlexWaygood @sharkdp @dcreager
/crates/ty_python_semantic/ @carljm @AlexWaygood @sharkdp @dcreager /crates/ty_python_semantic @carljm @AlexWaygood @sharkdp @dcreager
/crates/ty_module_resolver/ @carljm @MichaReiser @AlexWaygood @Gankra

View File

@@ -1,20 +1,13 @@
# Configuration for the actionlint tool, which we run via prek # Configuration for the actionlint tool, which we run via pre-commit
# to verify the correctness of the syntax in our GitHub Actions workflows. # to verify the correctness of the syntax in our GitHub Actions workflows.
self-hosted-runner: self-hosted-runner:
# Various runners we use that aren't recognized out-of-the-box by actionlint: # Various runners we use that aren't recognized out-of-the-box by actionlint:
labels: labels:
- depot-ubuntu-24.04-4
- depot-ubuntu-latest-8 - depot-ubuntu-latest-8
- depot-ubuntu-22.04-16 - depot-ubuntu-22.04-16
- depot-ubuntu-22.04-32 - depot-ubuntu-22.04-32
- depot-windows-2022-16 - depot-windows-2022-16
- depot-ubuntu-22.04-arm-4
- github-windows-2025-x86_64-8 - github-windows-2025-x86_64-8
- github-windows-2025-x86_64-16 - github-windows-2025-x86_64-16
- codspeed-macro - codspeed-macro
paths:
".github/workflows/mypy_primer.yaml":
ignore:
- 'constant expression "false" in condition. remove the if: section'

View File

@@ -4,6 +4,5 @@
# Enable off-by-default rules. # Enable off-by-default rules.
[rules] [rules]
possibly-unresolved-reference = "warn" possibly-unresolved-reference = "warn"
possibly-missing-import = "warn" unused-ignore-comment = "warn"
division-by-zero = "warn" division-by-zero = "warn"
unsupported-dynamic-base = "warn"

View File

@@ -76,9 +76,9 @@
enabled: false, enabled: false,
}, },
{ {
groupName: "prek dependencies", groupName: "pre-commit dependencies",
matchManagers: ["pre-commit"], matchManagers: ["pre-commit"],
description: "Weekly update of prek dependencies", description: "Weekly update of pre-commit dependencies",
}, },
{ {
groupName: "NPM Development dependencies", groupName: "NPM Development dependencies",

View File

@@ -39,7 +39,7 @@ jobs:
if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-build') }} if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-build') }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with: with:
submodules: recursive submodules: recursive
persist-credentials: false persist-credentials: false
@@ -51,7 +51,6 @@ jobs:
- name: "Build sdist" - name: "Build sdist"
uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # v1.49.4 uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # v1.49.4
with: with:
maturin-version: v1.9.6
command: sdist command: sdist
args: --out dist args: --out dist
- name: "Test sdist" - name: "Test sdist"
@@ -60,7 +59,7 @@ jobs:
"${MODULE_NAME}" --help "${MODULE_NAME}" --help
python -m "${MODULE_NAME}" --help python -m "${MODULE_NAME}" --help
- name: "Upload sdist" - name: "Upload sdist"
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with: with:
name: wheels-sdist name: wheels-sdist
path: dist path: dist
@@ -69,7 +68,7 @@ jobs:
if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-build') }} if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-build') }}
runs-on: macos-14 runs-on: macos-14
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with: with:
submodules: recursive submodules: recursive
persist-credentials: false persist-credentials: false
@@ -82,11 +81,10 @@ jobs:
- name: "Build wheels - x86_64" - name: "Build wheels - x86_64"
uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # v1.49.4 uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # v1.49.4
with: with:
maturin-version: v1.9.6
target: x86_64 target: x86_64
args: --release --locked --out dist args: --release --locked --out dist
- name: "Upload wheels" - name: "Upload wheels"
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with: with:
name: wheels-macos-x86_64 name: wheels-macos-x86_64
path: dist path: dist
@@ -101,7 +99,7 @@ jobs:
tar czvf $ARCHIVE_FILE $ARCHIVE_NAME tar czvf $ARCHIVE_FILE $ARCHIVE_NAME
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256 shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
- name: "Upload binary" - name: "Upload binary"
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with: with:
name: artifacts-macos-x86_64 name: artifacts-macos-x86_64
path: | path: |
@@ -112,7 +110,7 @@ jobs:
if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-build') }} if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-build') }}
runs-on: macos-14 runs-on: macos-14
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with: with:
submodules: recursive submodules: recursive
persist-credentials: false persist-credentials: false
@@ -125,7 +123,6 @@ jobs:
- name: "Build wheels - aarch64" - name: "Build wheels - aarch64"
uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # v1.49.4 uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # v1.49.4
with: with:
maturin-version: v1.9.6
target: aarch64 target: aarch64
args: --release --locked --out dist args: --release --locked --out dist
- name: "Test wheel - aarch64" - name: "Test wheel - aarch64"
@@ -134,7 +131,7 @@ jobs:
ruff --help ruff --help
python -m ruff --help python -m ruff --help
- name: "Upload wheels" - name: "Upload wheels"
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with: with:
name: wheels-aarch64-apple-darwin name: wheels-aarch64-apple-darwin
path: dist path: dist
@@ -149,7 +146,7 @@ jobs:
tar czvf $ARCHIVE_FILE $ARCHIVE_NAME tar czvf $ARCHIVE_FILE $ARCHIVE_NAME
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256 shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
- name: "Upload binary" - name: "Upload binary"
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with: with:
name: artifacts-aarch64-apple-darwin name: artifacts-aarch64-apple-darwin
path: | path: |
@@ -169,7 +166,7 @@ jobs:
- target: aarch64-pc-windows-msvc - target: aarch64-pc-windows-msvc
arch: x64 arch: x64
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with: with:
submodules: recursive submodules: recursive
persist-credentials: false persist-credentials: false
@@ -182,7 +179,6 @@ jobs:
- name: "Build wheels" - name: "Build wheels"
uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # v1.49.4 uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # v1.49.4
with: with:
maturin-version: v1.9.6
target: ${{ matrix.platform.target }} target: ${{ matrix.platform.target }}
args: --release --locked --out dist args: --release --locked --out dist
env: env:
@@ -196,7 +192,7 @@ jobs:
"${MODULE_NAME}" --help "${MODULE_NAME}" --help
python -m "${MODULE_NAME}" --help python -m "${MODULE_NAME}" --help
- name: "Upload wheels" - name: "Upload wheels"
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with: with:
name: wheels-${{ matrix.platform.target }} name: wheels-${{ matrix.platform.target }}
path: dist path: dist
@@ -207,7 +203,7 @@ jobs:
7z a $ARCHIVE_FILE ./target/${{ matrix.platform.target }}/release/ruff.exe 7z a $ARCHIVE_FILE ./target/${{ matrix.platform.target }}/release/ruff.exe
sha256sum $ARCHIVE_FILE > $ARCHIVE_FILE.sha256 sha256sum $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
- name: "Upload binary" - name: "Upload binary"
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with: with:
name: artifacts-${{ matrix.platform.target }} name: artifacts-${{ matrix.platform.target }}
path: | path: |
@@ -223,7 +219,7 @@ jobs:
- x86_64-unknown-linux-gnu - x86_64-unknown-linux-gnu
- i686-unknown-linux-gnu - i686-unknown-linux-gnu
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with: with:
submodules: recursive submodules: recursive
persist-credentials: false persist-credentials: false
@@ -236,7 +232,6 @@ jobs:
- name: "Build wheels" - name: "Build wheels"
uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # v1.49.4 uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # v1.49.4
with: with:
maturin-version: v1.9.6
target: ${{ matrix.target }} target: ${{ matrix.target }}
manylinux: auto manylinux: auto
args: --release --locked --out dist args: --release --locked --out dist
@@ -247,7 +242,7 @@ jobs:
"${MODULE_NAME}" --help "${MODULE_NAME}" --help
python -m "${MODULE_NAME}" --help python -m "${MODULE_NAME}" --help
- name: "Upload wheels" - name: "Upload wheels"
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with: with:
name: wheels-${{ matrix.target }} name: wheels-${{ matrix.target }}
path: dist path: dist
@@ -265,7 +260,7 @@ jobs:
tar czvf $ARCHIVE_FILE $ARCHIVE_NAME tar czvf $ARCHIVE_FILE $ARCHIVE_NAME
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256 shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
- name: "Upload binary" - name: "Upload binary"
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with: with:
name: artifacts-${{ matrix.target }} name: artifacts-${{ matrix.target }}
path: | path: |
@@ -301,7 +296,7 @@ jobs:
arch: riscv64 arch: riscv64
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with: with:
submodules: recursive submodules: recursive
persist-credentials: false persist-credentials: false
@@ -313,7 +308,6 @@ jobs:
- name: "Build wheels" - name: "Build wheels"
uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # v1.49.4 uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # v1.49.4
with: with:
maturin-version: v1.9.6
target: ${{ matrix.platform.target }} target: ${{ matrix.platform.target }}
manylinux: auto manylinux: auto
docker-options: ${{ matrix.platform.maturin_docker_options }} docker-options: ${{ matrix.platform.maturin_docker_options }}
@@ -333,7 +327,7 @@ jobs:
pip3 install ${{ env.PACKAGE_NAME }} --no-index --find-links dist/ --force-reinstall pip3 install ${{ env.PACKAGE_NAME }} --no-index --find-links dist/ --force-reinstall
ruff --help ruff --help
- name: "Upload wheels" - name: "Upload wheels"
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with: with:
name: wheels-${{ matrix.platform.target }} name: wheels-${{ matrix.platform.target }}
path: dist path: dist
@@ -351,7 +345,7 @@ jobs:
tar czvf $ARCHIVE_FILE $ARCHIVE_NAME tar czvf $ARCHIVE_FILE $ARCHIVE_NAME
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256 shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
- name: "Upload binary" - name: "Upload binary"
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with: with:
name: artifacts-${{ matrix.platform.target }} name: artifacts-${{ matrix.platform.target }}
path: | path: |
@@ -367,7 +361,7 @@ jobs:
- x86_64-unknown-linux-musl - x86_64-unknown-linux-musl
- i686-unknown-linux-musl - i686-unknown-linux-musl
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with: with:
submodules: recursive submodules: recursive
persist-credentials: false persist-credentials: false
@@ -380,7 +374,6 @@ jobs:
- name: "Build wheels" - name: "Build wheels"
uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # v1.49.4 uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # v1.49.4
with: with:
maturin-version: v1.9.6
target: ${{ matrix.target }} target: ${{ matrix.target }}
manylinux: musllinux_1_2 manylinux: musllinux_1_2
args: --release --locked --out dist args: --release --locked --out dist
@@ -396,7 +389,7 @@ jobs:
.venv/bin/pip3 install ${{ env.PACKAGE_NAME }} --no-index --find-links dist/ --force-reinstall .venv/bin/pip3 install ${{ env.PACKAGE_NAME }} --no-index --find-links dist/ --force-reinstall
.venv/bin/${{ env.MODULE_NAME }} --help .venv/bin/${{ env.MODULE_NAME }} --help
- name: "Upload wheels" - name: "Upload wheels"
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with: with:
name: wheels-${{ matrix.target }} name: wheels-${{ matrix.target }}
path: dist path: dist
@@ -414,7 +407,7 @@ jobs:
tar czvf $ARCHIVE_FILE $ARCHIVE_NAME tar czvf $ARCHIVE_FILE $ARCHIVE_NAME
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256 shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
- name: "Upload binary" - name: "Upload binary"
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with: with:
name: artifacts-${{ matrix.target }} name: artifacts-${{ matrix.target }}
path: | path: |
@@ -434,7 +427,7 @@ jobs:
arch: armv7 arch: armv7
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with: with:
submodules: recursive submodules: recursive
persist-credentials: false persist-credentials: false
@@ -446,7 +439,6 @@ jobs:
- name: "Build wheels" - name: "Build wheels"
uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # v1.49.4 uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # v1.49.4
with: with:
maturin-version: v1.9.6
target: ${{ matrix.platform.target }} target: ${{ matrix.platform.target }}
manylinux: musllinux_1_2 manylinux: musllinux_1_2
args: --release --locked --out dist args: --release --locked --out dist
@@ -464,7 +456,7 @@ jobs:
.venv/bin/pip3 install ${{ env.PACKAGE_NAME }} --no-index --find-links dist/ --force-reinstall .venv/bin/pip3 install ${{ env.PACKAGE_NAME }} --no-index --find-links dist/ --force-reinstall
.venv/bin/${{ env.MODULE_NAME }} --help .venv/bin/${{ env.MODULE_NAME }} --help
- name: "Upload wheels" - name: "Upload wheels"
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with: with:
name: wheels-${{ matrix.platform.target }} name: wheels-${{ matrix.platform.target }}
path: dist path: dist
@@ -482,7 +474,7 @@ jobs:
tar czvf $ARCHIVE_FILE $ARCHIVE_NAME tar czvf $ARCHIVE_FILE $ARCHIVE_NAME
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256 shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
- name: "Upload binary" - name: "Upload binary"
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with: with:
name: artifacts-${{ matrix.platform.target }} name: artifacts-${{ matrix.platform.target }}
path: | path: |

View File

@@ -20,12 +20,6 @@ on:
env: env:
RUFF_BASE_IMG: ghcr.io/${{ github.repository_owner }}/ruff RUFF_BASE_IMG: ghcr.io/${{ github.repository_owner }}/ruff
permissions:
contents: read
# TODO(zanieb): Ideally, this would be `read` on dry-run but that will require
# significant changes to the workflow.
packages: write # zizmor: ignore[excessive-permissions]
jobs: jobs:
docker-build: docker-build:
name: Build Docker image (ghcr.io/astral-sh/ruff) for ${{ matrix.platform }} name: Build Docker image (ghcr.io/astral-sh/ruff) for ${{ matrix.platform }}
@@ -39,12 +33,12 @@ jobs:
- linux/amd64 - linux/amd64
- linux/arm64 - linux/arm64
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with: with:
submodules: recursive submodules: recursive
persist-credentials: false persist-credentials: false
- uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 - uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
- uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 - uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
with: with:
@@ -69,7 +63,7 @@ jobs:
- name: Extract metadata (tags, labels) for Docker - name: Extract metadata (tags, labels) for Docker
id: meta id: meta
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0 uses: docker/metadata-action@c1e51972afc2121e065aed6d45c65596fe445f3f # v5.8.0
with: with:
images: ${{ env.RUFF_BASE_IMG }} images: ${{ env.RUFF_BASE_IMG }}
# Defining this makes sure the org.opencontainers.image.version OCI label becomes the actual release version and not the branch name # Defining this makes sure the org.opencontainers.image.version OCI label becomes the actual release version and not the branch name
@@ -102,7 +96,7 @@ jobs:
touch "/tmp/digests/${digest#sha256:}" touch "/tmp/digests/${digest#sha256:}"
- name: Upload digests - name: Upload digests
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with: with:
name: digests-${{ env.PLATFORM_TUPLE }} name: digests-${{ env.PLATFORM_TUPLE }}
path: /tmp/digests/* path: /tmp/digests/*
@@ -119,17 +113,17 @@ jobs:
if: ${{ inputs.plan != '' && !fromJson(inputs.plan).announcement_tag_is_implicit }} if: ${{ inputs.plan != '' && !fromJson(inputs.plan).announcement_tag_is_implicit }}
steps: steps:
- name: Download digests - name: Download digests
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
with: with:
path: /tmp/digests path: /tmp/digests
pattern: digests-* pattern: digests-*
merge-multiple: true merge-multiple: true
- uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 - uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
- name: Extract metadata (tags, labels) for Docker - name: Extract metadata (tags, labels) for Docker
id: meta id: meta
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0 uses: docker/metadata-action@c1e51972afc2121e065aed6d45c65596fe445f3f # v5.8.0
with: with:
images: ${{ env.RUFF_BASE_IMG }} images: ${{ env.RUFF_BASE_IMG }}
# Order is on purpose such that the label org.opencontainers.image.version has the first pattern with the full version # Order is on purpose such that the label org.opencontainers.image.version has the first pattern with the full version
@@ -173,7 +167,7 @@ jobs:
- debian:bookworm-slim,bookworm-slim,debian-slim - debian:bookworm-slim,bookworm-slim,debian-slim
- buildpack-deps:bookworm,bookworm,debian - buildpack-deps:bookworm,bookworm,debian
steps: steps:
- uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 - uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
- uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 - uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
with: with:
@@ -225,7 +219,7 @@ jobs:
- name: Extract metadata (tags, labels) for Docker - name: Extract metadata (tags, labels) for Docker
id: meta id: meta
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0 uses: docker/metadata-action@c1e51972afc2121e065aed6d45c65596fe445f3f # v5.8.0
# ghcr.io prefers index level annotations # ghcr.io prefers index level annotations
env: env:
DOCKER_METADATA_ANNOTATIONS_LEVELS: index DOCKER_METADATA_ANNOTATIONS_LEVELS: index
@@ -262,17 +256,17 @@ jobs:
if: ${{ inputs.plan != '' && !fromJson(inputs.plan).announcement_tag_is_implicit }} if: ${{ inputs.plan != '' && !fromJson(inputs.plan).announcement_tag_is_implicit }}
steps: steps:
- name: Download digests - name: Download digests
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
with: with:
path: /tmp/digests path: /tmp/digests
pattern: digests-* pattern: digests-*
merge-multiple: true merge-multiple: true
- uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 - uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
- name: Extract metadata (tags, labels) for Docker - name: Extract metadata (tags, labels) for Docker
id: meta id: meta
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0 uses: docker/metadata-action@c1e51972afc2121e065aed6d45c65596fe445f3f # v5.8.0
env: env:
DOCKER_METADATA_ANNOTATIONS_LEVELS: index DOCKER_METADATA_ANNOTATIONS_LEVELS: index
with: with:

View File

@@ -1,58 +0,0 @@
# Build ruff_wasm for npm.
#
# Assumed to run as a subworkflow of .github/workflows/release.yml; specifically, as a local
# artifacts job within `cargo-dist`.
name: "Build wasm"
on:
workflow_call:
inputs:
plan:
required: true
type: string
pull_request:
paths:
- .github/workflows/build-wasm.yml
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions: {}
env:
CARGO_INCREMENTAL: 0
CARGO_NET_RETRY: 10
CARGO_TERM_COLOR: always
RUSTUP_MAX_RETRIES: 10
jobs:
build:
if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-build') }}
runs-on: ubuntu-latest
strategy:
matrix:
target: [web, bundler, nodejs]
fail-fast: false
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: "Install Rust toolchain"
run: rustup target add wasm32-unknown-unknown
- uses: jetli/wasm-pack-action@0d096b08b4e5a7de8c28de67e11e945404e9eefa # v0.4.0
with:
version: v0.13.1
- uses: jetli/wasm-bindgen-action@20b33e20595891ab1a0ed73145d8a21fc96e7c29 # v0.2.0
- name: "Run wasm-pack build"
run: wasm-pack build --target ${{ matrix.target }} crates/ruff_wasm
- name: "Rename generated package"
run: | # Replace the package name w/ jq
jq '.name="@astral-sh/ruff-wasm-${{ matrix.target }}"' crates/ruff_wasm/pkg/package.json > /tmp/package.json
mv /tmp/package.json crates/ruff_wasm/pkg
- run: cp LICENSE crates/ruff_wasm/pkg # wasm-pack does not put the LICENSE file in the pkg
- name: "Upload wasm artifact"
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: artifacts-wasm-${{ matrix.target }}
path: crates/ruff_wasm/pkg

View File

@@ -49,10 +49,8 @@ jobs:
py-fuzzer: ${{ steps.check_py_fuzzer.outputs.changed }} py-fuzzer: ${{ steps.check_py_fuzzer.outputs.changed }}
# Flag that is set to "true" when code related to the playground changes. # Flag that is set to "true" when code related to the playground changes.
playground: ${{ steps.check_playground.outputs.changed }} playground: ${{ steps.check_playground.outputs.changed }}
# Flag that is set to "true" when code related to the benchmarks changes.
benchmarks: ${{ steps.check_benchmarks.outputs.changed }}
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with: with:
fetch-depth: 0 fetch-depth: 0
persist-credentials: false persist-credentials: false
@@ -97,7 +95,6 @@ jobs:
':!crates/ruff_python_formatter/**' \ ':!crates/ruff_python_formatter/**' \
':!crates/ruff_formatter/**' \ ':!crates/ruff_formatter/**' \
':!crates/ruff_dev/**' \ ':!crates/ruff_dev/**' \
':!crates/ruff_benchmark/**' \
':scripts/*' \ ':scripts/*' \
':python/**' \ ':python/**' \
':.github/workflows/ci.yaml' \ ':.github/workflows/ci.yaml' \
@@ -205,21 +202,6 @@ jobs:
':crates/ruff_python_trivia/**' \ ':crates/ruff_python_trivia/**' \
':crates/ruff_source_file/**' \ ':crates/ruff_source_file/**' \
':crates/ruff_text_size/**' \ ':crates/ruff_text_size/**' \
':.github/workflows/ci.yaml' \
; then
echo "changed=false" >> "$GITHUB_OUTPUT"
else
echo "changed=true" >> "$GITHUB_OUTPUT"
fi
- name: Check if the benchmark code changed
id: check_benchmarks
env:
MERGE_BASE: ${{ steps.merge_base.outputs.sha }}
run: |
if git diff --quiet "${MERGE_BASE}...HEAD" -- \
':Cargo.toml' \
':Cargo.lock' \
':crates/ruff_benchmark/**' \ ':crates/ruff_benchmark/**' \
':.github/workflows/ci.yaml' \ ':.github/workflows/ci.yaml' \
; then ; then
@@ -233,7 +215,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
timeout-minutes: 10 timeout-minutes: 10
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with: with:
persist-credentials: false persist-credentials: false
- name: "Install Rust toolchain" - name: "Install Rust toolchain"
@@ -247,7 +229,7 @@ jobs:
if: ${{ needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main' }} if: ${{ needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main' }}
timeout-minutes: 20 timeout-minutes: 20
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with: with:
persist-credentials: false persist-credentials: false
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
@@ -269,7 +251,7 @@ jobs:
if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-test') && (needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main') }} if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-test') && (needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main') }}
timeout-minutes: 20 timeout-minutes: 20
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with: with:
persist-credentials: false persist-credentials: false
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
@@ -281,15 +263,15 @@ jobs:
- name: "Install mold" - name: "Install mold"
uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1
- name: "Install cargo nextest" - name: "Install cargo nextest"
uses: taiki-e/install-action@0e76c5c569f13f7eb21e8e5b26fe710062b57b62 # v2.65.13 uses: taiki-e/install-action@3575e532701a5fc614b0c842e4119af4cc5fd16d # v2.62.60
with: with:
tool: cargo-nextest tool: cargo-nextest
- name: "Install cargo insta" - name: "Install cargo insta"
uses: taiki-e/install-action@0e76c5c569f13f7eb21e8e5b26fe710062b57b62 # v2.65.13 uses: taiki-e/install-action@3575e532701a5fc614b0c842e4119af4cc5fd16d # v2.62.60
with: with:
tool: cargo-insta tool: cargo-insta
- name: "Install uv" - name: "Install uv"
uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0 uses: astral-sh/setup-uv@1e862dfacbd1d6d858c55d9b792c756523627244 # v7.1.4
with: with:
enable-cache: "true" enable-cache: "true"
- name: ty mdtests (GitHub annotations) - name: ty mdtests (GitHub annotations)
@@ -316,7 +298,7 @@ jobs:
# sync, not just public items. Eventually we should do this for all # sync, not just public items. Eventually we should do this for all
# crates; for now add crates here as they are warning-clean to prevent # crates; for now add crates here as they are warning-clean to prevent
# regression. # regression.
- run: cargo doc --no-deps -p ty_python_semantic -p ty -p ty_test -p ruff_db -p ruff_python_formatter --document-private-items - run: cargo doc --no-deps -p ty_python_semantic -p ty -p ty_test -p ruff_db --document-private-items
env: env:
# Setting RUSTDOCFLAGS because `cargo doc --check` isn't yet implemented (https://github.com/rust-lang/cargo/issues/10025). # Setting RUSTDOCFLAGS because `cargo doc --check` isn't yet implemented (https://github.com/rust-lang/cargo/issues/10025).
RUSTDOCFLAGS: "-D warnings" RUSTDOCFLAGS: "-D warnings"
@@ -332,7 +314,7 @@ jobs:
(needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main') (needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main')
timeout-minutes: 20 timeout-minutes: 20
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with: with:
persist-credentials: false persist-credentials: false
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
@@ -343,11 +325,11 @@ jobs:
- name: "Install mold" - name: "Install mold"
uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1
- name: "Install cargo nextest" - name: "Install cargo nextest"
uses: taiki-e/install-action@0e76c5c569f13f7eb21e8e5b26fe710062b57b62 # v2.65.13 uses: taiki-e/install-action@3575e532701a5fc614b0c842e4119af4cc5fd16d # v2.62.60
with: with:
tool: cargo-nextest tool: cargo-nextest
- name: "Install uv" - name: "Install uv"
uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0 uses: astral-sh/setup-uv@1e862dfacbd1d6d858c55d9b792c756523627244 # v7.1.4
with: with:
enable-cache: "true" enable-cache: "true"
- name: "Run tests" - name: "Run tests"
@@ -367,7 +349,7 @@ jobs:
if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-test') && (needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main') }} if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-test') && (needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main') }}
timeout-minutes: 20 timeout-minutes: 20
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with: with:
persist-credentials: false persist-credentials: false
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
@@ -376,11 +358,11 @@ jobs:
- name: "Install Rust toolchain" - name: "Install Rust toolchain"
run: rustup show run: rustup show
- name: "Install cargo nextest" - name: "Install cargo nextest"
uses: taiki-e/install-action@0e76c5c569f13f7eb21e8e5b26fe710062b57b62 # v2.65.13 uses: taiki-e/install-action@3575e532701a5fc614b0c842e4119af4cc5fd16d # v2.62.60
with: with:
tool: cargo-nextest tool: cargo-nextest
- name: "Install uv" - name: "Install uv"
uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0 uses: astral-sh/setup-uv@1e862dfacbd1d6d858c55d9b792c756523627244 # v7.1.4
with: with:
enable-cache: "true" enable-cache: "true"
- name: "Run tests" - name: "Run tests"
@@ -395,7 +377,7 @@ jobs:
if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-test') && (needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main') }} if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-test') && (needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main') }}
timeout-minutes: 10 timeout-minutes: 10
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with: with:
persist-credentials: false persist-credentials: false
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
@@ -403,9 +385,9 @@ jobs:
save-if: ${{ github.ref == 'refs/heads/main' }} save-if: ${{ github.ref == 'refs/heads/main' }}
- name: "Install Rust toolchain" - name: "Install Rust toolchain"
run: rustup target add wasm32-unknown-unknown run: rustup target add wasm32-unknown-unknown
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with: with:
node-version: 24 node-version: 22
cache: "npm" cache: "npm"
cache-dependency-path: playground/package-lock.json cache-dependency-path: playground/package-lock.json
- uses: jetli/wasm-pack-action@0d096b08b4e5a7de8c28de67e11e945404e9eefa # v0.4.0 - uses: jetli/wasm-pack-action@0d096b08b4e5a7de8c28de67e11e945404e9eefa # v0.4.0
@@ -427,7 +409,7 @@ jobs:
if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-test') && (needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main') }} if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-test') && (needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main') }}
timeout-minutes: 20 timeout-minutes: 20
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with: with:
persist-credentials: false persist-credentials: false
- uses: SebRollen/toml-action@b1b3628f55fc3a28208d4203ada8b737e9687876 # v1.2.0 - uses: SebRollen/toml-action@b1b3628f55fc3a28208d4203ada8b737e9687876 # v1.2.0
@@ -456,7 +438,7 @@ jobs:
if: ${{ github.ref == 'refs/heads/main' || needs.determine_changes.outputs.fuzz == 'true' || needs.determine_changes.outputs.code == 'true' }} if: ${{ github.ref == 'refs/heads/main' || needs.determine_changes.outputs.fuzz == 'true' || needs.determine_changes.outputs.code == 'true' }}
timeout-minutes: 10 timeout-minutes: 10
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with: with:
persist-credentials: false persist-credentials: false
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
@@ -468,7 +450,7 @@ jobs:
- name: "Install mold" - name: "Install mold"
uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1
- name: "Install cargo-binstall" - name: "Install cargo-binstall"
uses: cargo-bins/cargo-binstall@80aaafe04903087c333980fa2686259ddd34b2d9 # v1.16.6 uses: cargo-bins/cargo-binstall@3fc81674af4165a753833a94cae9f91d8849049f # v1.16.2
- name: "Install cargo-fuzz" - name: "Install cargo-fuzz"
# Download the latest version from quick install and not the github releases because github releases only has MUSL targets. # Download the latest version from quick install and not the github releases because github releases only has MUSL targets.
run: cargo binstall cargo-fuzz --force --disable-strategies crate-meta-data --no-confirm run: cargo binstall cargo-fuzz --force --disable-strategies crate-meta-data --no-confirm
@@ -483,10 +465,10 @@ jobs:
env: env:
FORCE_COLOR: 1 FORCE_COLOR: 1
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with: with:
persist-credentials: false persist-credentials: false
- uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0 - uses: astral-sh/setup-uv@1e862dfacbd1d6d858c55d9b792c756523627244 # v7.1.4
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
with: with:
shared-key: ruff-linux-debug shared-key: ruff-linux-debug
@@ -515,13 +497,13 @@ jobs:
if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-test') && (needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main') }} if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-test') && (needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main') }}
timeout-minutes: 5 timeout-minutes: 5
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with: with:
persist-credentials: false persist-credentials: false
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
with: with:
save-if: ${{ github.ref == 'refs/heads/main' }} save-if: ${{ github.ref == 'refs/heads/main' }}
- uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0 - uses: astral-sh/setup-uv@1e862dfacbd1d6d858c55d9b792c756523627244 # v7.1.4
- name: "Install Rust toolchain" - name: "Install Rust toolchain"
run: rustup component add rustfmt run: rustup component add rustfmt
# Run all code generation scripts, and verify that the current output is # Run all code generation scripts, and verify that the current output is
@@ -548,20 +530,15 @@ jobs:
needs: determine_changes needs: determine_changes
# Only runs on pull requests, since that is the only we way we can find the base version for comparison. # Only runs on pull requests, since that is the only we way we can find the base version for comparison.
# Ecosystem check needs linter and/or formatter changes. # Ecosystem check needs linter and/or formatter changes.
if: | if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-test') && github.event_name == 'pull_request' && needs.determine_changes.outputs.code == 'true' }}
!contains(github.event.pull_request.labels.*.name, 'no-test') && github.event_name == 'pull_request' &&
(
needs.determine_changes.outputs.linter == 'true' ||
needs.determine_changes.outputs.formatter == 'true'
)
timeout-minutes: 20 timeout-minutes: 20
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with: with:
ref: ${{ github.event.pull_request.base.ref }} ref: ${{ github.event.pull_request.base.ref }}
persist-credentials: false persist-credentials: false
- uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0 - uses: astral-sh/setup-uv@1e862dfacbd1d6d858c55d9b792c756523627244 # v7.1.4
with: with:
python-version: ${{ env.PYTHON_VERSION }} python-version: ${{ env.PYTHON_VERSION }}
activate-environment: true activate-environment: true
@@ -582,7 +559,7 @@ jobs:
cargo build --bin ruff cargo build --bin ruff
mv target/debug/ruff target/debug/ruff-baseline mv target/debug/ruff target/debug/ruff-baseline
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with: with:
persist-credentials: false persist-credentials: false
clean: false clean: false
@@ -648,7 +625,7 @@ jobs:
# NOTE: astral-sh-bot uses this artifact to post comments on PRs. # NOTE: astral-sh-bot uses this artifact to post comments on PRs.
# Make sure to update the bot if you rename the artifact. # Make sure to update the bot if you rename the artifact.
- uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
name: Upload Results name: Upload Results
with: with:
name: ecosystem-result name: ecosystem-result
@@ -663,11 +640,11 @@ jobs:
if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-test') && github.event_name == 'pull_request' && (needs.determine_changes.outputs.ty == 'true' || needs.determine_changes.outputs.py-fuzzer == 'true') }} if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-test') && github.event_name == 'pull_request' && (needs.determine_changes.outputs.ty == 'true' || needs.determine_changes.outputs.py-fuzzer == 'true') }}
timeout-minutes: ${{ github.repository == 'astral-sh/ruff' && 10 || 20 }} timeout-minutes: ${{ github.repository == 'astral-sh/ruff' && 10 || 20 }}
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with: with:
fetch-depth: 0 fetch-depth: 0
persist-credentials: false persist-credentials: false
- uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0 - uses: astral-sh/setup-uv@1e862dfacbd1d6d858c55d9b792c756523627244 # v7.1.4
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
with: with:
save-if: ${{ github.ref == 'refs/heads/main' }} save-if: ${{ github.ref == 'refs/heads/main' }}
@@ -710,10 +687,10 @@ jobs:
needs: determine_changes needs: determine_changes
if: ${{ needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main' }} if: ${{ needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main' }}
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with: with:
persist-credentials: false persist-credentials: false
- uses: cargo-bins/cargo-binstall@80aaafe04903087c333980fa2686259ddd34b2d9 # v1.16.6 - uses: cargo-bins/cargo-binstall@3fc81674af4165a753833a94cae9f91d8849049f # v1.16.2
- run: cargo binstall --no-confirm cargo-shear - run: cargo binstall --no-confirm cargo-shear
- run: cargo shear - run: cargo shear
@@ -723,10 +700,10 @@ jobs:
needs: determine_changes needs: determine_changes
if: ${{ needs.determine_changes.outputs.ty == 'true' || github.ref == 'refs/heads/main' }} if: ${{ needs.determine_changes.outputs.ty == 'true' || github.ref == 'refs/heads/main' }}
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with: with:
persist-credentials: false persist-credentials: false
- uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0 - uses: astral-sh/setup-uv@1e862dfacbd1d6d858c55d9b792c756523627244 # v7.1.4
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
with: with:
save-if: ${{ github.ref == 'refs/heads/main' }} save-if: ${{ github.ref == 'refs/heads/main' }}
@@ -745,7 +722,7 @@ jobs:
timeout-minutes: 20 timeout-minutes: 20
if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-test') }} if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-test') }}
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with: with:
persist-credentials: false persist-credentials: false
- uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0 - uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0
@@ -769,29 +746,32 @@ jobs:
- name: "Remove wheels from cache" - name: "Remove wheels from cache"
run: rm -rf target/wheels run: rm -rf target/wheels
prek: pre-commit:
name: "prek" name: "pre-commit"
runs-on: ${{ github.repository == 'astral-sh/ruff' && 'depot-ubuntu-22.04-16' || 'ubuntu-latest' }} runs-on: ${{ github.repository == 'astral-sh/ruff' && 'depot-ubuntu-22.04-16' || 'ubuntu-latest' }}
timeout-minutes: 10 timeout-minutes: 10
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with: with:
persist-credentials: false persist-credentials: false
- uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0 - uses: astral-sh/setup-uv@1e862dfacbd1d6d858c55d9b792c756523627244 # v7.1.4
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
with: with:
node-version: 24 save-if: ${{ github.ref == 'refs/heads/main' }}
- name: "Cache prek" - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1
with: with:
path: ~/.cache/prek node-version: 22
key: prek-${{ hashFiles('.pre-commit-config.yaml') }} - name: "Cache pre-commit"
- name: "Run prek" uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: ~/.cache/pre-commit
key: pre-commit-${{ hashFiles('.pre-commit-config.yaml') }}
- name: "Run pre-commit"
run: | run: |
echo '```console' > "$GITHUB_STEP_SUMMARY" echo '```console' > "$GITHUB_STEP_SUMMARY"
# Enable color output for prek and remove it for the summary # Enable color output for pre-commit and remove it for the summary
# Use --hook-stage=manual to enable slower hooks that are skipped by default # Use --hook-stage=manual to enable slower pre-commit hooks that are skipped by default
SKIP=rustfmt uvx prek run --all-files --show-diff-on-failure --color always --hook-stage manual | \ SKIP=cargo-fmt,clippy,dev-generate-all uvx --python="${PYTHON_VERSION}" pre-commit run --all-files --show-diff-on-failure --color=always --hook-stage=manual | \
tee >(sed -E 's/\x1B\[([0-9]{1,2}(;[0-9]{1,2})*)?[mGK]//g' >> "$GITHUB_STEP_SUMMARY") >&1 tee >(sed -E 's/\x1B\[([0-9]{1,2}(;[0-9]{1,2})*)?[mGK]//g' >> "$GITHUB_STEP_SUMMARY") >&1
exit_code="${PIPESTATUS[0]}" exit_code="${PIPESTATUS[0]}"
echo '```' >> "$GITHUB_STEP_SUMMARY" echo '```' >> "$GITHUB_STEP_SUMMARY"
@@ -802,7 +782,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
timeout-minutes: 10 timeout-minutes: 10
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with: with:
persist-credentials: false persist-credentials: false
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
@@ -811,7 +791,7 @@ jobs:
- name: "Install Rust toolchain" - name: "Install Rust toolchain"
run: rustup show run: rustup show
- name: Install uv - name: Install uv
uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0 uses: astral-sh/setup-uv@1e862dfacbd1d6d858c55d9b792c756523627244 # v7.1.4
with: with:
python-version: 3.13 python-version: 3.13
activate-environment: true activate-environment: true
@@ -833,7 +813,7 @@ jobs:
if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-test') && (needs.determine_changes.outputs.formatter == 'true' || github.ref == 'refs/heads/main') }} if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-test') && (needs.determine_changes.outputs.formatter == 'true' || github.ref == 'refs/heads/main') }}
timeout-minutes: 10 timeout-minutes: 10
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with: with:
persist-credentials: false persist-credentials: false
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
@@ -859,7 +839,7 @@ jobs:
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
name: "Checkout ruff source" name: "Checkout ruff source"
with: with:
persist-credentials: false persist-credentials: false
@@ -875,7 +855,7 @@ jobs:
- name: Build Ruff binary - name: Build Ruff binary
run: cargo build -p ruff --bin ruff run: cargo build -p ruff --bin ruff
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
name: "Checkout ruff-lsp source" name: "Checkout ruff-lsp source"
with: with:
persist-credentials: false persist-credentials: false
@@ -910,7 +890,7 @@ jobs:
- determine_changes - determine_changes
if: ${{ (needs.determine_changes.outputs.playground == 'true') }} if: ${{ (needs.determine_changes.outputs.playground == 'true') }}
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with: with:
persist-credentials: false persist-credentials: false
- name: "Install Rust toolchain" - name: "Install Rust toolchain"
@@ -918,9 +898,9 @@ jobs:
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
with: with:
save-if: ${{ github.ref == 'refs/heads/main' }} save-if: ${{ github.ref == 'refs/heads/main' }}
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with: with:
node-version: 24 node-version: 22
cache: "npm" cache: "npm"
cache-dependency-path: playground/package-lock.json cache-dependency-path: playground/package-lock.json
- uses: jetli/wasm-bindgen-action@20b33e20595891ab1a0ed73145d8a21fc96e7c29 # v0.2.0 - uses: jetli/wasm-bindgen-action@20b33e20595891ab1a0ed73145d8a21fc96e7c29 # v0.2.0
@@ -946,9 +926,7 @@ jobs:
( (
github.ref == 'refs/heads/main' || github.ref == 'refs/heads/main' ||
needs.determine_changes.outputs.formatter == 'true' || needs.determine_changes.outputs.formatter == 'true' ||
needs.determine_changes.outputs.linter == 'true' || needs.determine_changes.outputs.linter == 'true'
needs.determine_changes.outputs.parser == 'true' ||
needs.determine_changes.outputs.benchmarks == 'true'
) )
timeout-minutes: 20 timeout-minutes: 20
permissions: permissions:
@@ -956,198 +934,112 @@ jobs:
id-token: write # required for OIDC authentication with CodSpeed id-token: write # required for OIDC authentication with CodSpeed
steps: steps:
- name: "Checkout Branch" - name: "Checkout Branch"
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with: with:
persist-credentials: false persist-credentials: false
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
with: with:
save-if: ${{ github.ref == 'refs/heads/main' }} save-if: ${{ github.ref == 'refs/heads/main' }}
- uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0 - uses: astral-sh/setup-uv@1e862dfacbd1d6d858c55d9b792c756523627244 # v7.1.4
- name: "Install Rust toolchain" - name: "Install Rust toolchain"
run: rustup show run: rustup show
- name: "Install codspeed" - name: "Install codspeed"
uses: taiki-e/install-action@0e76c5c569f13f7eb21e8e5b26fe710062b57b62 # v2.65.13 uses: taiki-e/install-action@3575e532701a5fc614b0c842e4119af4cc5fd16d # v2.62.60
with: with:
tool: cargo-codspeed tool: cargo-codspeed
- name: "Build benchmarks" - name: "Build benchmarks"
run: cargo codspeed build --features "codspeed,ruff_instrumented" --profile profiling --no-default-features -p ruff_benchmark --bench formatter --bench lexer --bench linter --bench parser run: cargo codspeed build --features "codspeed,instrumented" --profile profiling --no-default-features -p ruff_benchmark --bench formatter --bench lexer --bench linter --bench parser
- name: "Run benchmarks" - name: "Run benchmarks"
uses: CodSpeedHQ/action@dbda7111f8ac363564b0c51b992d4ce76bb89f2f # v4.5.2 uses: CodSpeedHQ/action@346a2d8a8d9d38909abd0bc3d23f773110f076ad # v4.4.1
with: with:
mode: simulation mode: simulation
run: cargo codspeed run run: cargo codspeed run
benchmarks-instrumented-ty-build: benchmarks-instrumented-ty:
name: "benchmarks instrumented ty (build)" name: "benchmarks instrumented (ty)"
runs-on: depot-ubuntu-24.04-4 runs-on: ubuntu-24.04
needs: determine_changes needs: determine_changes
if: | if: |
github.repository == 'astral-sh/ruff' && github.repository == 'astral-sh/ruff' &&
( (
github.ref == 'refs/heads/main' || github.ref == 'refs/heads/main' ||
needs.determine_changes.outputs.ty == 'true' || needs.determine_changes.outputs.ty == 'true'
needs.determine_changes.outputs.benchmarks == 'true'
) )
timeout-minutes: 20 timeout-minutes: 20
permissions:
contents: read # required for actions/checkout
id-token: write # required for OIDC authentication with CodSpeed
steps: steps:
- name: "Checkout Branch" - name: "Checkout Branch"
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with: with:
persist-credentials: false persist-credentials: false
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
with: with:
save-if: ${{ github.ref == 'refs/heads/main' }} save-if: ${{ github.ref == 'refs/heads/main' }}
- uses: astral-sh/setup-uv@1e862dfacbd1d6d858c55d9b792c756523627244 # v7.1.4
- name: "Install Rust toolchain" - name: "Install Rust toolchain"
run: rustup show run: rustup show
- name: "Install codspeed" - name: "Install codspeed"
uses: taiki-e/install-action@0e76c5c569f13f7eb21e8e5b26fe710062b57b62 # v2.65.13 uses: taiki-e/install-action@3575e532701a5fc614b0c842e4119af4cc5fd16d # v2.62.60
with: with:
tool: cargo-codspeed tool: cargo-codspeed
- name: "Build benchmarks" - name: "Build benchmarks"
run: cargo codspeed build -m instrumentation --features "codspeed,ty_instrumented" --profile profiling --no-default-features -p ruff_benchmark --bench ty run: cargo codspeed build --features "codspeed,instrumented" --profile profiling --no-default-features -p ruff_benchmark --bench ty
- name: "Upload benchmark binary"
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: benchmarks-instrumented-ty-binary
path: target/codspeed/simulation/ruff_benchmark
retention-days: 1
benchmarks-instrumented-ty-run:
name: "benchmarks instrumented ty (${{ matrix.benchmark }})"
runs-on: ubuntu-24.04
needs: benchmarks-instrumented-ty-build
timeout-minutes: 20
permissions:
contents: read # required for actions/checkout
id-token: write # required for OIDC authentication with CodSpeed
strategy:
fail-fast: false
matrix:
benchmark:
- "check_file|micro|anyio"
- "attrs|hydra|datetype"
steps:
- name: "Checkout Branch"
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0
- name: "Install codspeed"
uses: taiki-e/install-action@0e76c5c569f13f7eb21e8e5b26fe710062b57b62 # v2.65.13
with:
tool: cargo-codspeed
- name: "Download benchmark binary"
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
name: benchmarks-instrumented-ty-binary
path: target/codspeed/simulation/ruff_benchmark
- name: "Restore binary permissions"
run: chmod +x target/codspeed/simulation/ruff_benchmark/ty
- name: "Run benchmarks" - name: "Run benchmarks"
uses: CodSpeedHQ/action@dbda7111f8ac363564b0c51b992d4ce76bb89f2f # v4.5.2 uses: CodSpeedHQ/action@346a2d8a8d9d38909abd0bc3d23f773110f076ad # v4.4.1
with: with:
mode: simulation mode: simulation
run: cargo codspeed run --bench ty "${{ matrix.benchmark }}" run: cargo codspeed run
benchmarks-walltime-build: benchmarks-walltime:
name: "benchmarks walltime (build)" name: "benchmarks walltime (${{ matrix.benchmarks }})"
# We only run this job if `github.repository == 'astral-sh/ruff'`,
# so hardcoding depot here is fine
runs-on: depot-ubuntu-22.04-arm-4
needs: determine_changes
if: |
github.repository == 'astral-sh/ruff' &&
(
!contains(github.event.pull_request.labels.*.name, 'no-test') &&
(
needs.determine_changes.outputs.ty == 'true' ||
needs.determine_changes.outputs.benchmarks == 'true' ||
github.ref == 'refs/heads/main'
)
)
timeout-minutes: 20
steps:
- name: "Checkout Branch"
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
with:
save-if: ${{ github.ref == 'refs/heads/main' }}
- uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0
- name: "Install Rust toolchain"
run: rustup show
- name: "Install codspeed"
uses: taiki-e/install-action@0e76c5c569f13f7eb21e8e5b26fe710062b57b62 # v2.65.13
with:
tool: cargo-codspeed
- name: "Build benchmarks"
run: cargo codspeed build -m walltime --features "codspeed,ty_walltime" --profile profiling --no-default-features -p ruff_benchmark
- name: "Upload benchmark binary"
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: benchmarks-walltime-binary
path: target/codspeed/walltime/ruff_benchmark
retention-days: 1
benchmarks-walltime-run:
name: "benchmarks walltime (${{ matrix.benchmark }})"
runs-on: codspeed-macro runs-on: codspeed-macro
needs: benchmarks-walltime-build needs: determine_changes
if: ${{ github.repository == 'astral-sh/ruff' && !contains(github.event.pull_request.labels.*.name, 'no-test') && (needs.determine_changes.outputs.ty == 'true' || github.ref == 'refs/heads/main') }}
timeout-minutes: 20 timeout-minutes: 20
permissions: permissions:
contents: read # required for actions/checkout contents: read # required for actions/checkout
id-token: write # required for OIDC authentication with CodSpeed id-token: write # required for OIDC authentication with CodSpeed
strategy: strategy:
matrix: matrix:
benchmark: benchmarks:
- colour_science - "medium|multithreaded"
- "pandas|tanjun|altair" - "small|large"
- "static_frame|sympy"
- "pydantic|multithreaded|freqtrade"
steps: steps:
- name: "Checkout Branch" - name: "Checkout Branch"
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with: with:
persist-credentials: false persist-credentials: false
- uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0 - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
with:
save-if: ${{ github.ref == 'refs/heads/main' }}
- uses: astral-sh/setup-uv@1e862dfacbd1d6d858c55d9b792c756523627244 # v7.1.4
- name: "Install Rust toolchain"
run: rustup show
- name: "Install codspeed" - name: "Install codspeed"
uses: taiki-e/install-action@0e76c5c569f13f7eb21e8e5b26fe710062b57b62 # v2.65.13 uses: taiki-e/install-action@3575e532701a5fc614b0c842e4119af4cc5fd16d # v2.62.60
with: with:
tool: cargo-codspeed tool: cargo-codspeed
- name: "Download benchmark binary" - name: "Build benchmarks"
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 run: cargo codspeed build --features "codspeed,walltime" --profile profiling --no-default-features -p ruff_benchmark
with:
name: benchmarks-walltime-binary
path: target/codspeed/walltime/ruff_benchmark
- name: "Restore binary permissions"
run: chmod +x target/codspeed/walltime/ruff_benchmark/ty_walltime
- name: "Run benchmarks" - name: "Run benchmarks"
uses: CodSpeedHQ/action@dbda7111f8ac363564b0c51b992d4ce76bb89f2f # v4.5.2 uses: CodSpeedHQ/action@346a2d8a8d9d38909abd0bc3d23f773110f076ad # v4.4.1
env: env:
# enabling walltime flamegraphs adds ~6 minutes to the CI time, and they don't # enabling walltime flamegraphs adds ~6 minutes to the CI time, and they don't
# appear to provide much useful insight for our walltime benchmarks right now # appear to provide much useful insight for our walltime benchmarks right now
@@ -1155,4 +1047,4 @@ jobs:
CODSPEED_PERF_ENABLED: false CODSPEED_PERF_ENABLED: false
with: with:
mode: walltime mode: walltime
run: cargo codspeed run --bench ty_walltime -m walltime "${{ matrix.benchmark }}" run: cargo codspeed run --bench ty_walltime "${{ matrix.benchmarks }}"

View File

@@ -31,10 +31,10 @@ jobs:
# Don't run the cron job on forks: # Don't run the cron job on forks:
if: ${{ github.repository == 'astral-sh/ruff' || github.event_name != 'schedule' }} if: ${{ github.repository == 'astral-sh/ruff' || github.event_name != 'schedule' }}
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with: with:
persist-credentials: false persist-credentials: false
- uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0 - uses: astral-sh/setup-uv@1e862dfacbd1d6d858c55d9b792c756523627244 # v7.1.4
- name: "Install Rust toolchain" - name: "Install Rust toolchain"
run: rustup show run: rustup show
- name: "Install mold" - name: "Install mold"
@@ -62,7 +62,7 @@ jobs:
name: Create an issue if the daily fuzz surfaced any bugs name: Create an issue if the daily fuzz surfaced any bugs
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: fuzz needs: fuzz
if: ${{ github.repository == 'astral-sh/ruff' && always() && github.event_name == 'schedule' && needs.fuzz.result != 'success' }} if: ${{ github.repository == 'astral-sh/ruff' && always() && github.event_name == 'schedule' && needs.fuzz.result == 'failure' }}
permissions: permissions:
issues: write issues: write
steps: steps:

View File

@@ -6,11 +6,6 @@ on:
pull_request: pull_request:
paths: paths:
- "crates/ty*/**" - "crates/ty*/**"
- "!crates/ty_ide/**"
- "!crates/ty_server/**"
- "!crates/ty_test/**"
- "!crates/ty_completion_eval/**"
- "!crates/ty_wasm/**"
- "crates/ruff_db" - "crates/ruff_db"
- "crates/ruff_python_ast" - "crates/ruff_python_ast"
- "crates/ruff_python_parser" - "crates/ruff_python_parser"
@@ -41,18 +36,17 @@ jobs:
runs-on: ${{ github.repository == 'astral-sh/ruff' && 'depot-ubuntu-22.04-32' || 'ubuntu-latest' }} runs-on: ${{ github.repository == 'astral-sh/ruff' && 'depot-ubuntu-22.04-32' || 'ubuntu-latest' }}
timeout-minutes: 20 timeout-minutes: 20
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with: with:
path: ruff path: ruff
fetch-depth: 0 fetch-depth: 0
persist-credentials: false persist-credentials: false
- name: Install the latest version of uv - name: Install the latest version of uv
uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0 uses: astral-sh/setup-uv@1e862dfacbd1d6d858c55d9b792c756523627244 # v7.1.4
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
with: with:
shared-key: "mypy-primer"
workspaces: "ruff" workspaces: "ruff"
- name: Install Rust toolchain - name: Install Rust toolchain
@@ -70,7 +64,7 @@ jobs:
# NOTE: astral-sh-bot uses this artifact to post comments on PRs. # NOTE: astral-sh-bot uses this artifact to post comments on PRs.
# Make sure to update the bot if you rename the artifact. # Make sure to update the bot if you rename the artifact.
- name: Upload diff - name: Upload diff
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with: with:
name: mypy_primer_diff name: mypy_primer_diff
path: mypy_primer.diff path: mypy_primer.diff
@@ -80,19 +74,18 @@ jobs:
runs-on: ${{ github.repository == 'astral-sh/ruff' && 'depot-ubuntu-22.04-32' || 'ubuntu-latest' }} runs-on: ${{ github.repository == 'astral-sh/ruff' && 'depot-ubuntu-22.04-32' || 'ubuntu-latest' }}
timeout-minutes: 20 timeout-minutes: 20
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with: with:
path: ruff path: ruff
fetch-depth: 0 fetch-depth: 0
persist-credentials: false persist-credentials: false
- name: Install the latest version of uv - name: Install the latest version of uv
uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0 uses: astral-sh/setup-uv@1e862dfacbd1d6d858c55d9b792c756523627244 # v7.1.4
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
with: with:
workspaces: "ruff" workspaces: "ruff"
shared-key: "mypy-primer"
- name: Install Rust toolchain - name: Install Rust toolchain
run: rustup show run: rustup show
@@ -108,58 +101,7 @@ jobs:
scripts/mypy_primer.sh scripts/mypy_primer.sh
- name: Upload diff - name: Upload diff
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with: with:
name: mypy_primer_memory_diff name: mypy_primer_memory_diff
path: mypy_primer_memory.diff path: mypy_primer_memory.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
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
path: ruff
fetch-depth: 0
persist-credentials: false
- name: Install the latest version of uv
uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0
- 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

View File

@@ -17,14 +17,11 @@ on:
required: true required: true
type: string type: string
permissions:
contents: read
jobs: jobs:
mkdocs: mkdocs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with: with:
ref: ${{ inputs.ref }} ref: ${{ inputs.ref }}
persist-credentials: true persist-credentials: true

View File

@@ -26,14 +26,14 @@ jobs:
env: env:
CF_API_TOKEN_EXISTS: ${{ secrets.CF_API_TOKEN != '' }} CF_API_TOKEN_EXISTS: ${{ secrets.CF_API_TOKEN != '' }}
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with: with:
persist-credentials: false persist-credentials: false
- name: "Install Rust toolchain" - name: "Install Rust toolchain"
run: rustup target add wasm32-unknown-unknown run: rustup target add wasm32-unknown-unknown
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with: with:
node-version: 24 node-version: 22
package-manager-cache: false package-manager-cache: false
- uses: jetli/wasm-bindgen-action@20b33e20595891ab1a0ed73145d8a21fc96e7c29 # v0.2.0 - uses: jetli/wasm-bindgen-action@20b33e20595891ab1a0ed73145d8a21fc96e7c29 # v0.2.0
- name: "Install Node dependencies" - name: "Install Node dependencies"

View File

@@ -22,8 +22,8 @@ jobs:
id-token: write id-token: write
steps: steps:
- name: "Install uv" - name: "Install uv"
uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0 uses: astral-sh/setup-uv@1e862dfacbd1d6d858c55d9b792c756523627244 # v7.1.4
- uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
with: with:
pattern: wheels-* pattern: wheels-*
path: wheels path: wheels

View File

@@ -30,14 +30,14 @@ jobs:
env: env:
CF_API_TOKEN_EXISTS: ${{ secrets.CF_API_TOKEN != '' }} CF_API_TOKEN_EXISTS: ${{ secrets.CF_API_TOKEN != '' }}
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with: with:
persist-credentials: false persist-credentials: false
- name: "Install Rust toolchain" - name: "Install Rust toolchain"
run: rustup target add wasm32-unknown-unknown run: rustup target add wasm32-unknown-unknown
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with: with:
node-version: 24 node-version: 22
package-manager-cache: false package-manager-cache: false
- uses: jetli/wasm-bindgen-action@20b33e20595891ab1a0ed73145d8a21fc96e7c29 # v0.2.0 - uses: jetli/wasm-bindgen-action@20b33e20595891ab1a0ed73145d8a21fc96e7c29 # v0.2.0
- name: "Install Node dependencies" - name: "Install Node dependencies"

View File

@@ -1,18 +1,25 @@
# Publish ruff_wasm to npm. # Build and publish ruff-api for wasm.
# #
# Assumed to run as a subworkflow of .github/workflows/release.yml; specifically, as a publish # Assumed to run as a subworkflow of .github/workflows/release.yml; specifically, as a publish
# job within `cargo-dist`. # job within `cargo-dist`.
name: "Publish wasm" name: "Build and publish wasm"
on: on:
workflow_dispatch:
workflow_call: workflow_call:
inputs: inputs:
plan: plan:
required: true required: true
type: string type: string
env:
CARGO_INCREMENTAL: 0
CARGO_NET_RETRY: 10
CARGO_TERM_COLOR: always
RUSTUP_MAX_RETRIES: 10
jobs: jobs:
publish: ruff_wasm:
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: permissions:
contents: read contents: read
@@ -22,19 +29,31 @@ jobs:
target: [web, bundler, nodejs] target: [web, bundler, nodejs]
fail-fast: false fail-fast: false
steps: steps:
- uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with: with:
name: artifacts-wasm-${{ matrix.target }} persist-credentials: false
path: pkg - name: "Install Rust toolchain"
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 run: rustup target add wasm32-unknown-unknown
- uses: jetli/wasm-pack-action@0d096b08b4e5a7de8c28de67e11e945404e9eefa # v0.4.0
with: with:
node-version: 24 version: v0.13.1
- uses: jetli/wasm-bindgen-action@20b33e20595891ab1a0ed73145d8a21fc96e7c29 # v0.2.0
- name: "Run wasm-pack build"
run: wasm-pack build --target ${{ matrix.target }} crates/ruff_wasm
- name: "Rename generated package"
run: | # Replace the package name w/ jq
jq '.name="@astral-sh/ruff-wasm-${{ matrix.target }}"' crates/ruff_wasm/pkg/package.json > /tmp/package.json
mv /tmp/package.json crates/ruff_wasm/pkg
- run: cp LICENSE crates/ruff_wasm/pkg # wasm-pack does not put the LICENSE file in the pkg
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with:
node-version: 22
registry-url: "https://registry.npmjs.org" registry-url: "https://registry.npmjs.org"
- name: "Publish (dry-run)" - name: "Publish (dry-run)"
if: ${{ inputs.plan == '' || fromJson(inputs.plan).announcement_tag_is_implicit }} if: ${{ inputs.plan == '' || fromJson(inputs.plan).announcement_tag_is_implicit }}
run: npm publish --dry-run pkg run: npm publish --dry-run crates/ruff_wasm/pkg
- name: "Publish" - name: "Publish"
if: ${{ inputs.plan != '' && !fromJson(inputs.plan).announcement_tag_is_implicit }} if: ${{ inputs.plan != '' && !fromJson(inputs.plan).announcement_tag_is_implicit }}
run: npm publish --provenance --access public pkg run: npm publish --provenance --access public crates/ruff_wasm/pkg
env: env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

View File

@@ -60,7 +60,7 @@ jobs:
env: env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps: steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3
with: with:
persist-credentials: false persist-credentials: false
submodules: recursive submodules: recursive
@@ -70,7 +70,7 @@ jobs:
shell: bash shell: bash
run: "curl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/cargo-dist/releases/download/v0.30.2/cargo-dist-installer.sh | sh" run: "curl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/cargo-dist/releases/download/v0.30.2/cargo-dist-installer.sh | sh"
- name: Cache dist - name: Cache dist
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4
with: with:
name: cargo-dist-cache name: cargo-dist-cache
path: ~/.cargo/bin/dist path: ~/.cargo/bin/dist
@@ -86,7 +86,7 @@ jobs:
cat plan-dist-manifest.json cat plan-dist-manifest.json
echo "manifest=$(jq -c "." plan-dist-manifest.json)" >> "$GITHUB_OUTPUT" echo "manifest=$(jq -c "." plan-dist-manifest.json)" >> "$GITHUB_OUTPUT"
- name: "Upload dist-manifest.json" - name: "Upload dist-manifest.json"
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4
with: with:
name: artifacts-plan-dist-manifest name: artifacts-plan-dist-manifest
path: plan-dist-manifest.json path: plan-dist-manifest.json
@@ -112,40 +112,30 @@ jobs:
"contents": "read" "contents": "read"
"packages": "write" "packages": "write"
custom-build-wasm:
needs:
- plan
if: ${{ needs.plan.outputs.publishing == 'true' || fromJson(needs.plan.outputs.val).ci.github.pr_run_mode == 'upload' || inputs.tag == 'dry-run' }}
uses: ./.github/workflows/build-wasm.yml
with:
plan: ${{ needs.plan.outputs.val }}
secrets: inherit
# Build and package all the platform-agnostic(ish) things # Build and package all the platform-agnostic(ish) things
build-global-artifacts: build-global-artifacts:
needs: needs:
- plan - plan
- custom-build-binaries - custom-build-binaries
- custom-build-docker - custom-build-docker
- custom-build-wasm
runs-on: "depot-ubuntu-latest-4" runs-on: "depot-ubuntu-latest-4"
env: env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BUILD_MANIFEST_NAME: target/distrib/global-dist-manifest.json BUILD_MANIFEST_NAME: target/distrib/global-dist-manifest.json
steps: steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3
with: with:
persist-credentials: false persist-credentials: false
submodules: recursive submodules: recursive
- name: Install cached dist - name: Install cached dist
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53
with: with:
name: cargo-dist-cache name: cargo-dist-cache
path: ~/.cargo/bin/ path: ~/.cargo/bin/
- run: chmod +x ~/.cargo/bin/dist - run: chmod +x ~/.cargo/bin/dist
# Get all the local artifacts for the global tasks to use (for e.g. checksums) # Get all the local artifacts for the global tasks to use (for e.g. checksums)
- name: Fetch local artifacts - name: Fetch local artifacts
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53
with: with:
pattern: artifacts-* pattern: artifacts-*
path: target/distrib/ path: target/distrib/
@@ -163,7 +153,7 @@ jobs:
cp dist-manifest.json "$BUILD_MANIFEST_NAME" cp dist-manifest.json "$BUILD_MANIFEST_NAME"
- name: "Upload artifacts" - name: "Upload artifacts"
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4
with: with:
name: artifacts-build-global name: artifacts-build-global
path: | path: |
@@ -175,29 +165,28 @@ jobs:
- plan - plan
- custom-build-binaries - custom-build-binaries
- custom-build-docker - custom-build-docker
- custom-build-wasm
- build-global-artifacts - build-global-artifacts
# Only run if we're "publishing", and only if plan, local and global didn't fail (skipped is fine) # Only run if we're "publishing", and only if plan, local and global didn't fail (skipped is fine)
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') && (needs.custom-build-wasm.result == 'skipped' || needs.custom-build-wasm.result == 'success') }} 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') }}
env: env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
runs-on: "depot-ubuntu-latest-4" runs-on: "depot-ubuntu-latest-4"
outputs: outputs:
val: ${{ steps.host.outputs.manifest }} val: ${{ steps.host.outputs.manifest }}
steps: steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3
with: with:
persist-credentials: false persist-credentials: false
submodules: recursive submodules: recursive
- name: Install cached dist - name: Install cached dist
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53
with: with:
name: cargo-dist-cache name: cargo-dist-cache
path: ~/.cargo/bin/ path: ~/.cargo/bin/
- run: chmod +x ~/.cargo/bin/dist - run: chmod +x ~/.cargo/bin/dist
# Fetch artifacts from scratch-storage # Fetch artifacts from scratch-storage
- name: Fetch artifacts - name: Fetch artifacts
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53
with: with:
pattern: artifacts-* pattern: artifacts-*
path: target/distrib/ path: target/distrib/
@@ -211,7 +200,7 @@ jobs:
cat dist-manifest.json cat dist-manifest.json
echo "manifest=$(jq -c "." dist-manifest.json)" >> "$GITHUB_OUTPUT" echo "manifest=$(jq -c "." dist-manifest.json)" >> "$GITHUB_OUTPUT"
- name: "Upload dist-manifest.json" - name: "Upload dist-manifest.json"
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4
with: with:
# Overwrite the previous copy # Overwrite the previous copy
name: artifacts-dist-manifest name: artifacts-dist-manifest
@@ -261,13 +250,13 @@ jobs:
env: env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps: steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3
with: with:
persist-credentials: false persist-credentials: false
submodules: recursive submodules: recursive
# Create a GitHub Release while uploading all files to it # Create a GitHub Release while uploading all files to it
- name: "Download GitHub Artifacts" - name: "Download GitHub Artifacts"
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53
with: with:
pattern: artifacts-* pattern: artifacts-*
path: artifacts path: artifacts

View File

@@ -16,7 +16,8 @@ name: Sync typeshed
# 3. Once the Windows worker is done, a MacOS worker: # 3. Once the Windows worker is done, a MacOS worker:
# a. Checks out the branch created by the Linux worker # a. Checks out the branch created by the Linux worker
# b. Syncs all docstrings available on MacOS that are not available on Linux or Windows # b. Syncs all docstrings available on MacOS that are not available on Linux or Windows
# c. Formats the code again # c. Attempts to update any snapshots that might have changed
# (this sub-step is allowed to fail)
# d. Commits the changes and pushes them to the same upstream branch # d. Commits the changes and pushes them to the same upstream branch
# e. Creates a PR against the `main` branch using the branch all three workers have pushed to # e. Creates a PR against the `main` branch using the branch all three workers have pushed to
# 4. If any of steps 1-3 failed, an issue is created in the `astral-sh/ruff` repository # 4. If any of steps 1-3 failed, an issue is created in the `astral-sh/ruff` repository
@@ -61,12 +62,12 @@ jobs:
permissions: permissions:
contents: write contents: write
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
name: Checkout Ruff name: Checkout Ruff
with: with:
path: ruff path: ruff
persist-credentials: true persist-credentials: true
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
name: Checkout typeshed name: Checkout typeshed
with: with:
repository: python/typeshed repository: python/typeshed
@@ -76,7 +77,7 @@ jobs:
run: | run: |
git config --global user.name typeshedbot git config --global user.name typeshedbot
git config --global user.email '<>' git config --global user.email '<>'
- uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0 - uses: astral-sh/setup-uv@1e862dfacbd1d6d858c55d9b792c756523627244 # v7.1.4
- name: Sync typeshed stubs - name: Sync typeshed stubs
run: | run: |
rm -rf "ruff/${VENDORED_TYPESHED}" rm -rf "ruff/${VENDORED_TYPESHED}"
@@ -125,12 +126,12 @@ jobs:
permissions: permissions:
contents: write contents: write
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
name: Checkout Ruff name: Checkout Ruff
with: with:
persist-credentials: true persist-credentials: true
ref: ${{ env.UPSTREAM_BRANCH}} ref: ${{ env.UPSTREAM_BRANCH}}
- uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0 - uses: astral-sh/setup-uv@1e862dfacbd1d6d858c55d9b792c756523627244 # v7.1.4
- name: Setup git - name: Setup git
run: | run: |
git config --global user.name typeshedbot git config --global user.name typeshedbot
@@ -164,12 +165,12 @@ jobs:
contents: write contents: write
pull-requests: write pull-requests: write
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
name: Checkout Ruff name: Checkout Ruff
with: with:
persist-credentials: true persist-credentials: true
ref: ${{ env.UPSTREAM_BRANCH}} ref: ${{ env.UPSTREAM_BRANCH}}
- uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0 - uses: astral-sh/setup-uv@1e862dfacbd1d6d858c55d9b792c756523627244 # v7.1.4
- name: Setup git - name: Setup git
run: | run: |
git config --global user.name typeshedbot git config --global user.name typeshedbot
@@ -197,6 +198,42 @@ jobs:
run: | run: |
rm "${VENDORED_TYPESHED}/pyproject.toml" rm "${VENDORED_TYPESHED}/pyproject.toml"
git commit -am "Remove pyproject.toml file" git commit -am "Remove pyproject.toml file"
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
- name: "Install Rust toolchain"
if: ${{ success() }}
run: rustup show
- name: "Install mold"
if: ${{ success() }}
uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1
- name: "Install cargo nextest"
if: ${{ success() }}
uses: taiki-e/install-action@3575e532701a5fc614b0c842e4119af4cc5fd16d # v2.62.60
with:
tool: cargo-nextest
- name: "Install cargo insta"
if: ${{ success() }}
uses: taiki-e/install-action@3575e532701a5fc614b0c842e4119af4cc5fd16d # v2.62.60
with:
tool: cargo-insta
- name: Update snapshots
if: ${{ success() }}
run: |
cargo r \
--profile=profiling \
-p ty_completion_eval \
-- all --tasks ./crates/ty_completion_eval/completion-evaluation-tasks.csv
# The `cargo insta` docs indicate that `--unreferenced=delete` might be a good option,
# but from local testing it appears to just revert all changes made by `cargo insta test --accept`.
#
# If there were only snapshot-related failures, `cargo insta test --accept` will have exit code 0,
# but if there were also other mdtest failures (for example), it will return a nonzero exit code.
# We don't care about other tests failing here, we just want snapshots updated where possible,
# so we use `|| true` here to ignore the exit code.
cargo insta test --accept --color=always --all-features --test-runner=nextest || true
- name: Commit snapshot changes
if: ${{ success() }}
run: git commit -am "Update snapshots" || echo "No snapshot changes to commit"
- name: Push changes upstream and create a PR - name: Push changes upstream and create a PR
if: ${{ success() }} if: ${{ success() }}
run: | run: |
@@ -208,7 +245,7 @@ jobs:
name: Create an issue if the typeshed sync failed name: Create an issue if the typeshed sync failed
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [sync, docstrings-windows, docstrings-macos-and-pr] needs: [sync, docstrings-windows, docstrings-macos-and-pr]
if: ${{ github.repository == 'astral-sh/ruff' && always() && github.event_name == 'schedule' && (needs.sync.result != 'success' || needs.docstrings-windows.result != 'success' || needs.docstrings-macos-and-pr.result != 'success') }} if: ${{ github.repository == 'astral-sh/ruff' && always() && github.event_name == 'schedule' && (needs.sync.result == 'failure' || needs.docstrings-windows.result == 'failure' || needs.docstrings-macos-and-pr.result == 'failure') }}
permissions: permissions:
issues: write issues: write
steps: steps:

View File

@@ -4,13 +4,7 @@ permissions: {}
on: on:
pull_request: pull_request:
# The default for `pull_request` is to trigger on `synchronize`, `opened` and `reopened`. types: [labeled]
# We also add `labeled` here so that the workflow triggers when a label is initially added.
types:
- labeled
- synchronize
- opened
- reopened
concurrency: concurrency:
group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.event.pull_request.number || github.sha }} group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.event.pull_request.number || github.sha }}
@@ -23,29 +17,30 @@ env:
RUSTUP_MAX_RETRIES: 10 RUSTUP_MAX_RETRIES: 10
RUST_BACKTRACE: 1 RUST_BACKTRACE: 1
REF_NAME: ${{ github.ref_name }} REF_NAME: ${{ github.ref_name }}
CF_API_TOKEN_EXISTS: ${{ secrets.CF_API_TOKEN != '' }}
jobs: jobs:
ty-ecosystem-analyzer: ty-ecosystem-analyzer:
name: Compute diagnostic diff name: Compute diagnostic diff
runs-on: ${{ github.repository == 'astral-sh/ruff' && 'depot-ubuntu-22.04-32' || 'ubuntu-latest' }} runs-on: ${{ github.repository == 'astral-sh/ruff' && 'depot-ubuntu-22.04-32' || 'ubuntu-latest' }}
timeout-minutes: 20 timeout-minutes: 20
if: contains( github.event.pull_request.labels.*.name, 'ecosystem-analyzer') if: contains(github.event.label.name, 'ecosystem-analyzer')
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with: with:
path: ruff path: ruff
fetch-depth: 0 fetch-depth: 0
persist-credentials: false persist-credentials: false
- name: Install the latest version of uv - name: Install the latest version of uv
uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0 uses: astral-sh/setup-uv@1e862dfacbd1d6d858c55d9b792c756523627244 # v7.1.4
with: with:
enable-cache: true enable-cache: true # zizmor: ignore[cache-poisoning] acceptable risk for CloudFlare pages artifact
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
with: with:
workspaces: "ruff" workspaces: "ruff"
lookup-only: false lookup-only: false # zizmor: ignore[cache-poisoning] acceptable risk for CloudFlare pages artifact
- name: Install Rust toolchain - name: Install Rust toolchain
run: rustup show run: rustup show
@@ -72,7 +67,7 @@ jobs:
cd .. cd ..
uv tool install "git+https://github.com/astral-sh/ecosystem-analyzer@2e1816eac09c90140b1ba51d19afc5f59da460f5" uv tool install "git+https://github.com/astral-sh/ecosystem-analyzer@55df3c868f3fa9ab34cff0498dd6106722aac205"
ecosystem-analyzer \ ecosystem-analyzer \
--repository ruff \ --repository ruff \
@@ -117,30 +112,39 @@ jobs:
cat diff-statistics.md >> "$GITHUB_STEP_SUMMARY" cat diff-statistics.md >> "$GITHUB_STEP_SUMMARY"
# NOTE: astral-sh-bot uses this artifact to post comments on PRs. - name: "Deploy to Cloudflare Pages"
# Make sure to update the bot if you rename the artifact. if: ${{ env.CF_API_TOKEN_EXISTS == 'true' }}
- name: "Upload full report" id: deploy
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 uses: cloudflare/wrangler-action@da0e0dfe58b7a431659754fdf3f186c529afbe65 # v3.14.1
with: with:
name: full-report apiToken: ${{ secrets.CF_API_TOKEN }}
path: dist/ accountId: ${{ secrets.CF_ACCOUNT_ID }}
command: pages deploy dist --project-name=ty-ecosystem --branch ${{ github.head_ref }} --commit-hash ${GITHUB_SHA}
- name: "Append deployment URL"
if: ${{ env.CF_API_TOKEN_EXISTS == 'true' }}
env:
DEPLOYMENT_URL: ${{ steps.deploy.outputs.pages-deployment-alias-url }}
run: |
echo >> comment.md
echo "**[Full report with detailed diff]($DEPLOYMENT_URL/diff)** ([timing results]($DEPLOYMENT_URL/timing))" >> comment.md
# NOTE: astral-sh-bot uses this artifact to post comments on PRs. # NOTE: astral-sh-bot uses this artifact to post comments on PRs.
# Make sure to update the bot if you rename the artifact. # Make sure to update the bot if you rename the artifact.
- name: Upload comment - name: Upload comment
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with: with:
name: comment.md name: comment.md
path: comment.md path: comment.md
- name: Upload diagnostics diff - name: Upload diagnostics diff
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with: with:
name: diff.html name: diff.html
path: dist/diff.html path: dist/diff.html
- name: Upload timing diff - name: Upload timing diff
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with: with:
name: timing.html name: timing.html
path: dist/timing.html path: dist/timing.html

View File

@@ -1,7 +1,3 @@
# This workflow is a cron job that generates a report describing
# all diagnostics ty emits across the whole ecosystem. The report
# is uploaded to https://ty-ecosystem-ext.pages.dev/ on a weekly basis.
name: ty ecosystem-report name: ty ecosystem-report
permissions: {} permissions: {}
@@ -18,6 +14,7 @@ env:
CARGO_TERM_COLOR: always CARGO_TERM_COLOR: always
RUSTUP_MAX_RETRIES: 10 RUSTUP_MAX_RETRIES: 10
RUST_BACKTRACE: 1 RUST_BACKTRACE: 1
CF_API_TOKEN_EXISTS: ${{ secrets.CF_API_TOKEN != '' }}
jobs: jobs:
ty-ecosystem-report: ty-ecosystem-report:
@@ -25,21 +22,21 @@ jobs:
runs-on: ${{ github.repository == 'astral-sh/ruff' && 'depot-ubuntu-22.04-32' || 'ubuntu-latest' }} runs-on: ${{ github.repository == 'astral-sh/ruff' && 'depot-ubuntu-22.04-32' || 'ubuntu-latest' }}
timeout-minutes: 20 timeout-minutes: 20
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with: with:
path: ruff path: ruff
fetch-depth: 0 fetch-depth: 0
persist-credentials: false persist-credentials: false
- name: Install the latest version of uv - name: Install the latest version of uv
uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0 uses: astral-sh/setup-uv@1e862dfacbd1d6d858c55d9b792c756523627244 # v7.1.4
with: with:
enable-cache: true enable-cache: true # zizmor: ignore[cache-poisoning] acceptable risk for CloudFlare pages artifact
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
with: with:
workspaces: "ruff" workspaces: "ruff"
lookup-only: false lookup-only: false # zizmor: ignore[cache-poisoning] acceptable risk for CloudFlare pages artifact
- name: Install Rust toolchain - name: Install Rust toolchain
run: rustup show run: rustup show
@@ -55,7 +52,7 @@ jobs:
cd .. cd ..
uv tool install "git+https://github.com/astral-sh/ecosystem-analyzer@2e1816eac09c90140b1ba51d19afc5f59da460f5" uv tool install "git+https://github.com/astral-sh/ecosystem-analyzer@55df3c868f3fa9ab34cff0498dd6106722aac205"
ecosystem-analyzer \ ecosystem-analyzer \
--verbose \ --verbose \
@@ -73,10 +70,11 @@ jobs:
ecosystem-diagnostics.json \ ecosystem-diagnostics.json \
--output dist/index.html --output dist/index.html
# NOTE: astral-sh-bot uses this artifact to publish the ecosystem report. - name: "Deploy to Cloudflare Pages"
# Make sure to update the bot if you rename the artifact. if: ${{ env.CF_API_TOKEN_EXISTS == 'true' }}
- name: "Upload ecosystem report" id: deploy
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 uses: cloudflare/wrangler-action@da0e0dfe58b7a431659754fdf3f186c529afbe65 # v3.14.1
with: with:
name: full-report apiToken: ${{ secrets.CF_API_TOKEN }}
path: dist/ accountId: ${{ secrets.CF_ACCOUNT_ID }}
command: pages deploy dist --project-name=ty-ecosystem --branch main --commit-hash ${GITHUB_SHA}

View File

@@ -6,11 +6,6 @@ on:
pull_request: pull_request:
paths: paths:
- "crates/ty*/**" - "crates/ty*/**"
- "!crates/ty_ide/**"
- "!crates/ty_server/**"
- "!crates/ty_test/**"
- "!crates/ty_completion_eval/**"
- "!crates/ty_wasm/**"
- "crates/ruff_db" - "crates/ruff_db"
- "crates/ruff_python_ast" - "crates/ruff_python_ast"
- "crates/ruff_python_parser" - "crates/ruff_python_parser"
@@ -37,13 +32,13 @@ jobs:
runs-on: ${{ github.repository == 'astral-sh/ruff' && 'depot-ubuntu-22.04-32' || 'ubuntu-latest' }} runs-on: ${{ github.repository == 'astral-sh/ruff' && 'depot-ubuntu-22.04-32' || 'ubuntu-latest' }}
timeout-minutes: 10 timeout-minutes: 10
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with: with:
path: ruff path: ruff
fetch-depth: 0 fetch-depth: 0
persist-credentials: false persist-credentials: false
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with: with:
repository: python/typing repository: python/typing
ref: ${{ env.CONFORMANCE_SUITE_COMMIT }} ref: ${{ env.CONFORMANCE_SUITE_COMMIT }}
@@ -59,6 +54,9 @@ jobs:
- name: Compute diagnostic diff - name: Compute diagnostic diff
shell: bash shell: bash
env:
# TODO: Remove this once we fixed the remaining panics in the conformance suite.
TY_MAX_PARALLELISM: 1
run: | run: |
RUFF_DIR="$GITHUB_WORKSPACE/ruff" RUFF_DIR="$GITHUB_WORKSPACE/ruff"
@@ -101,7 +99,7 @@ jobs:
# NOTE: astral-sh-bot uses this artifact to post comments on PRs. # NOTE: astral-sh-bot uses this artifact to post comments on PRs.
# Make sure to update the bot if you rename the artifact. # Make sure to update the bot if you rename the artifact.
- name: Upload diff - name: Upload diff
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with: with:
name: typing_conformance_diagnostics_diff name: typing_conformance_diagnostics_diff
path: typing_conformance_diagnostics.diff path: typing_conformance_diagnostics.diff
@@ -109,7 +107,7 @@ jobs:
# NOTE: astral-sh-bot uses this artifact to post comments on PRs. # NOTE: astral-sh-bot uses this artifact to post comments on PRs.
# Make sure to update the bot if you rename the artifact. # Make sure to update the bot if you rename the artifact.
- name: Upload conformance suite commit - name: Upload conformance suite commit
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with: with:
name: conformance-suite-commit name: conformance-suite-commit
path: conformance-suite-commit path: conformance-suite-commit

23
.github/zizmor.yml vendored Normal file
View File

@@ -0,0 +1,23 @@
# Configuration for the zizmor static analysis tool, run via pre-commit in CI
# https://docs.zizmor.sh/configuration/
#
# TODO: can we remove the ignores here so that our workflows are more secure?
rules:
cache-poisoning:
ignore:
- build-docker.yml
excessive-permissions:
# it's hard to test what the impact of removing these ignores would be
# without actually running the release workflow...
ignore:
- build-docker.yml
- publish-docs.yml
secrets-inherit:
# `cargo dist` makes extensive use of `secrets: inherit`,
# and we can't easily fix that until an upstream release changes that.
disable: true
template-injection:
ignore:
# like with `secrets-inherit`, `cargo dist` introduces some
# template injections. We've manually audited these usages for safety.
- release.yml

View File

@@ -21,91 +21,32 @@ exclude: |
)$ )$
repos: repos:
# Priority 0: Read-only hooks; hooks that modify disjoint file types.
- repo: https://github.com/pre-commit/pre-commit-hooks - repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0 rev: v5.0.0
hooks: hooks:
- id: check-merge-conflict - id: check-merge-conflict
priority: 0
- repo: https://github.com/abravalheri/validate-pyproject - repo: https://github.com/abravalheri/validate-pyproject
rev: v0.24.1 rev: v0.24.1
hooks: hooks:
- id: validate-pyproject - id: validate-pyproject
priority: 0
- repo: https://github.com/crate-ci/typos
rev: v1.41.0
hooks:
- id: typos
priority: 0
- repo: local
hooks:
- id: rustfmt
name: rustfmt
entry: rustfmt
language: system
types: [rust]
priority: 0
# Prettier
- repo: https://github.com/rbubley/mirrors-prettier
rev: v3.7.4
hooks:
- id: prettier
types: [yaml]
priority: 0
# zizmor detects security vulnerabilities in GitHub Actions workflows.
# Additional configuration for the tool is found in `.github/zizmor.yml`
- repo: https://github.com/zizmorcore/zizmor-pre-commit
rev: v1.19.0
hooks:
- id: zizmor
priority: 0
- repo: https://github.com/python-jsonschema/check-jsonschema
rev: 0.36.0
hooks:
- id: check-github-workflows
priority: 0
- repo: https://github.com/shellcheck-py/shellcheck-py
rev: v0.11.0.1
hooks:
- id: shellcheck
priority: 0
- repo: https://github.com/executablebooks/mdformat - repo: https://github.com/executablebooks/mdformat
rev: 1.0.0 rev: 0.7.22
hooks: hooks:
- id: mdformat - id: mdformat
language: python # means renovate will also update `additional_dependencies` language: python # means renovate will also update `additional_dependencies`
additional_dependencies: additional_dependencies:
- mdformat-mkdocs==5.0.0 - mdformat-mkdocs==4.0.0
- mdformat-footnote==0.1.2 - mdformat-footnote==0.1.1
exclude: | exclude: |
(?x)^( (?x)^(
docs/formatter/black\.md docs/formatter/black\.md
| docs/\w+\.md | docs/\w+\.md
)$ )$
priority: 0
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.14.10
hooks:
- id: ruff-format
priority: 0
- id: ruff-check
args: [--fix, --exit-non-zero-on-fix]
types_or: [python, pyi]
require_serial: true
priority: 1
# Priority 1: Second-pass fixers (e.g., markdownlint-fix runs after mdformat).
- repo: https://github.com/igorshubovych/markdownlint-cli - repo: https://github.com/igorshubovych/markdownlint-cli
rev: v0.47.0 rev: v0.45.0
hooks: hooks:
- id: markdownlint-fix - id: markdownlint-fix
exclude: | exclude: |
@@ -113,11 +54,9 @@ repos:
docs/formatter/black\.md docs/formatter/black\.md
| docs/\w+\.md | docs/\w+\.md
)$ )$
priority: 1
# Priority 2: blacken-docs runs after markdownlint-fix (both modify markdown).
- repo: https://github.com/adamchainz/blacken-docs - repo: https://github.com/adamchainz/blacken-docs
rev: 1.20.0 rev: 1.19.1
hooks: hooks:
- id: blacken-docs - id: blacken-docs
language: python # means renovate will also update `additional_dependencies` language: python # means renovate will also update `additional_dependencies`
@@ -128,27 +67,74 @@ repos:
.*?invalid(_.+)*_syntax\.md .*?invalid(_.+)*_syntax\.md
)$ )$
additional_dependencies: additional_dependencies:
- black==25.12.0 - black==25.1.0
priority: 2
- repo: https://github.com/crate-ci/typos
rev: v1.34.0
hooks:
- id: typos
- repo: local
hooks:
- id: cargo-fmt
name: cargo fmt
entry: cargo fmt --
language: system
types: [rust]
pass_filenames: false # This makes it a lot faster
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.12.7
hooks:
- id: ruff-format
- id: ruff-check
args: [--fix, --exit-non-zero-on-fix]
types_or: [python, pyi]
require_serial: true
# Prettier
- repo: https://github.com/rbubley/mirrors-prettier
rev: v3.6.2
hooks:
- id: prettier
types: [yaml]
# zizmor detects security vulnerabilities in GitHub Actions workflows.
# Additional configuration for the tool is found in `.github/zizmor.yml`
- repo: https://github.com/zizmorcore/zizmor-pre-commit
rev: v1.16.0
hooks:
- id: zizmor
- repo: https://github.com/python-jsonschema/check-jsonschema
rev: 0.33.2
hooks:
- id: check-github-workflows
# `actionlint` hook, for verifying correct syntax in GitHub Actions workflows. # `actionlint` hook, for verifying correct syntax in GitHub Actions workflows.
# Some additional configuration for `actionlint` can be found in `.github/actionlint.yaml`. # Some additional configuration for `actionlint` can be found in `.github/actionlint.yaml`.
- repo: https://github.com/rhysd/actionlint - repo: https://github.com/rhysd/actionlint
rev: v1.7.10 rev: v1.7.7
hooks: hooks:
- id: actionlint - id: actionlint
stages: stages:
# This hook is disabled by default, since it's quite slow. # This hook is disabled by default, since it's quite slow.
# To run all hooks *including* this hook, use `uvx prek run -a --hook-stage=manual`. # To run all hooks *including* this hook, use `uvx pre-commit run -a --hook-stage=manual`.
# To run *just* this hook, use `uvx prek run -a actionlint --hook-stage=manual`. # To run *just* this hook, use `uvx pre-commit run -a actionlint --hook-stage=manual`.
- manual - manual
args: args:
- "-ignore=SC2129" # ignorable stylistic lint from shellcheck - "-ignore=SC2129" # ignorable stylistic lint from shellcheck
- "-ignore=SC2016" # another shellcheck lint: seems to have false positives? - "-ignore=SC2016" # another shellcheck lint: seems to have false positives?
language: golang # means renovate will also update `additional_dependencies`
additional_dependencies: additional_dependencies:
# actionlint has a shellcheck integration which extracts shell scripts in `run:` steps from GitHub Actions # actionlint has a shellcheck integration which extracts shell scripts in `run:` steps from GitHub Actions
# and checks these with shellcheck. This is arguably its most useful feature, # and checks these with shellcheck. This is arguably its most useful feature,
# but the integration only works if shellcheck is installed # but the integration only works if shellcheck is installed
- "github.com/wasilibs/go-shellcheck/cmd/shellcheck@v0.11.1" - "github.com/wasilibs/go-shellcheck/cmd/shellcheck@v0.10.0"
priority: 0
- repo: https://github.com/shellcheck-py/shellcheck-py
rev: v0.10.0.1
hooks:
- id: shellcheck
ci:
skip: [cargo-fmt, dev-generate-all]

View File

@@ -1,154 +1,5 @@
# Changelog # Changelog
## 0.14.11
Released on 2026-01-08.
### Preview features
- Consolidate diagnostics for matched disable/enable suppression comments ([#22099](https://github.com/astral-sh/ruff/pull/22099))
- Report diagnostics for invalid/unmatched range suppression comments ([#21908](https://github.com/astral-sh/ruff/pull/21908))
- \[`airflow`\] Passing positional argument into `airflow.lineage.hook.HookLineageCollector.create_asset` is not allowed (`AIR303`) ([#22046](https://github.com/astral-sh/ruff/pull/22046))
- \[`refurb`\] Mark `FURB192` fix as always unsafe ([#22210](https://github.com/astral-sh/ruff/pull/22210))
- \[`ruff`\] Add `non-empty-init-module` (`RUF067`) ([#22143](https://github.com/astral-sh/ruff/pull/22143))
### Bug fixes
- Fix GitHub format for multi-line diagnostics ([#22108](https://github.com/astral-sh/ruff/pull/22108))
- \[`flake8-unused-arguments`\] Mark `**kwargs` in `TypeVar` as used (`ARG001`) ([#22214](https://github.com/astral-sh/ruff/pull/22214))
### Rule changes
- Add `help:` subdiagnostics for several Ruff rules that can sometimes appear to disagree with `ty` ([#22331](https://github.com/astral-sh/ruff/pull/22331))
- \[`pylint`\] Demote `PLW1510` fix to display-only ([#22318](https://github.com/astral-sh/ruff/pull/22318))
- \[`pylint`\] Ignore identical members (`PLR1714`) ([#22220](https://github.com/astral-sh/ruff/pull/22220))
- \[`pylint`\] Improve diagnostic range for `PLC0206` ([#22312](https://github.com/astral-sh/ruff/pull/22312))
- \[`ruff`\] Improve fix title for `RUF102` invalid rule code ([#22100](https://github.com/astral-sh/ruff/pull/22100))
- \[`flake8-simplify`\]: Avoid unnecessary builtins import for `SIM105` ([#22358](https://github.com/astral-sh/ruff/pull/22358))
### Configuration
- Allow Python 3.15 as valid `target-version` value in preview ([#22419](https://github.com/astral-sh/ruff/pull/22419))
- Check `required-version` before parsing rules ([#22410](https://github.com/astral-sh/ruff/pull/22410))
- Include configured `src` directories when resolving graphs ([#22451](https://github.com/astral-sh/ruff/pull/22451))
### Documentation
- Update `T201` suggestion to not use root logger to satisfy `LOG015` ([#22059](https://github.com/astral-sh/ruff/pull/22059))
- Fix `iter` example in unsafe fixes doc ([#22118](https://github.com/astral-sh/ruff/pull/22118))
- \[`flake8_print`\] better suggestion for `basicConfig` in `T201` docs ([#22101](https://github.com/astral-sh/ruff/pull/22101))
- \[`pylint`\] Restore the fix safety docs for `PLW0133` ([#22211](https://github.com/astral-sh/ruff/pull/22211))
- Fix Jupyter notebook discovery info for editors ([#22447](https://github.com/astral-sh/ruff/pull/22447))
### Contributors
- [@charliermarsh](https://github.com/charliermarsh)
- [@ntBre](https://github.com/ntBre)
- [@cenviity](https://github.com/cenviity)
- [@njhearp](https://github.com/njhearp)
- [@cbachhuber](https://github.com/cbachhuber)
- [@jelle-openai](https://github.com/jelle-openai)
- [@AlexWaygood](https://github.com/AlexWaygood)
- [@ValdonVitija](https://github.com/ValdonVitija)
- [@BurntSushi](https://github.com/BurntSushi)
- [@Jkhall81](https://github.com/Jkhall81)
- [@PeterJCLaw](https://github.com/PeterJCLaw)
- [@harupy](https://github.com/harupy)
- [@amyreese](https://github.com/amyreese)
- [@sjyangkevin](https://github.com/sjyangkevin)
- [@woodruffw](https://github.com/woodruffw)
## 0.14.10
Released on 2025-12-18.
### Preview features
- [formatter] Fluent formatting of method chains ([#21369](https://github.com/astral-sh/ruff/pull/21369))
- [formatter] Keep lambda parameters on one line and parenthesize the body if it expands ([#21385](https://github.com/astral-sh/ruff/pull/21385))
- \[`flake8-implicit-str-concat`\] New rule to prevent implicit string concatenation in collections (`ISC004`) ([#21972](https://github.com/astral-sh/ruff/pull/21972))
- \[`flake8-use-pathlib`\] Make fixes unsafe when types change in compound statements (`PTH104`, `PTH105`, `PTH109`, `PTH115`) ([#22009](https://github.com/astral-sh/ruff/pull/22009))
- \[`refurb`\] Extend support for `Path.open` (`FURB101`, `FURB103`) ([#21080](https://github.com/astral-sh/ruff/pull/21080))
### Bug fixes
- \[`pyupgrade`\] Fix parsing named Unicode escape sequences (`UP032`) ([#21901](https://github.com/astral-sh/ruff/pull/21901))
### Rule changes
- \[`eradicate`\] Ignore `ruff:disable` and `ruff:enable` comments in `ERA001` ([#22038](https://github.com/astral-sh/ruff/pull/22038))
- \[`flake8-pytest-style`\] Allow `match` and `check` keyword arguments without an expected exception type (`PT010`) ([#21964](https://github.com/astral-sh/ruff/pull/21964))
- [syntax-errors] Annotated name cannot be global ([#20868](https://github.com/astral-sh/ruff/pull/20868))
### Documentation
- Add `uv` and `ty` to the Ruff README ([#21996](https://github.com/astral-sh/ruff/pull/21996))
- Document known lambda formatting deviations from Black ([#21954](https://github.com/astral-sh/ruff/pull/21954))
- Update `setup.md` ([#22024](https://github.com/astral-sh/ruff/pull/22024))
- \[`flake8-bandit`\] Fix broken link (`S704`) ([#22039](https://github.com/astral-sh/ruff/pull/22039))
### Other changes
- Fix playground Share button showing "Copied!" before clipboard copy completes ([#21942](https://github.com/astral-sh/ruff/pull/21942))
### Contributors
- [@dylwil3](https://github.com/dylwil3)
- [@charliecloudberry](https://github.com/charliecloudberry)
- [@charliermarsh](https://github.com/charliermarsh)
- [@chirizxc](https://github.com/chirizxc)
- [@ntBre](https://github.com/ntBre)
- [@zanieb](https://github.com/zanieb)
- [@amyreese](https://github.com/amyreese)
- [@hauntsaninja](https://github.com/hauntsaninja)
- [@11happy](https://github.com/11happy)
- [@mahiro72](https://github.com/mahiro72)
- [@MichaReiser](https://github.com/MichaReiser)
- [@phongddo](https://github.com/phongddo)
- [@PeterJCLaw](https://github.com/PeterJCLaw)
## 0.14.9
Released on 2025-12-11.
### Preview features
- \[`ruff`\] New `RUF100` diagnostics for unused range suppressions ([#21783](https://github.com/astral-sh/ruff/pull/21783))
- \[`pylint`\] Detect subclasses of builtin exceptions (`PLW0133`) ([#21382](https://github.com/astral-sh/ruff/pull/21382))
### Bug fixes
- Fix comment placement in lambda parameters ([#21868](https://github.com/astral-sh/ruff/pull/21868))
- Skip over trivia tokens after re-lexing ([#21895](https://github.com/astral-sh/ruff/pull/21895))
- \[`flake8-bandit`\] Fix false positive when using non-standard `CSafeLoader` path (S506). ([#21830](https://github.com/astral-sh/ruff/pull/21830))
- \[`flake8-bugbear`\] Accept immutable slice default arguments (`B008`) ([#21823](https://github.com/astral-sh/ruff/pull/21823))
### Rule changes
- \[`pydocstyle`\] Suppress `D417` for parameters with `Unpack` annotations ([#21816](https://github.com/astral-sh/ruff/pull/21816))
### Performance
- Use `memchr` for computing line indexes ([#21838](https://github.com/astral-sh/ruff/pull/21838))
### Documentation
- Document `*.pyw` is included by default in preview ([#21885](https://github.com/astral-sh/ruff/pull/21885))
- Document range suppressions, reorganize suppression docs ([#21884](https://github.com/astral-sh/ruff/pull/21884))
- Update mkdocs-material to 9.7.0 (Insiders now free) ([#21797](https://github.com/astral-sh/ruff/pull/21797))
### Contributors
- [@Avasam](https://github.com/Avasam)
- [@MichaReiser](https://github.com/MichaReiser)
- [@charliermarsh](https://github.com/charliermarsh)
- [@amyreese](https://github.com/amyreese)
- [@phongddo](https://github.com/phongddo)
- [@prakhar1144](https://github.com/prakhar1144)
- [@mahiro72](https://github.com/mahiro72)
- [@ntBre](https://github.com/ntBre)
- [@LoicRiegel](https://github.com/LoicRiegel)
## 0.14.8 ## 0.14.8
Released on 2025-12-04. Released on 2025-12-04.

View File

@@ -1,71 +0,0 @@
# Ruff Repository
This repository contains both Ruff (a Python linter and formatter) and ty (a Python type checker). The crates follow a naming convention: `ruff_*` for Ruff-specific code and `ty_*` for ty-specific code. ty reuses several Ruff crates, including the Python parser (`ruff_python_parser`) and AST definitions (`ruff_python_ast`).
## Running Tests
Run all tests (using `nextest` for faster execution):
```sh
cargo nextest run
```
For faster test execution, use the `fast-test` profile which enables optimizations while retaining debug info:
```sh
cargo nextest run --cargo-profile fast-test
```
Run tests for a specific crate:
```sh
cargo nextest run -p ty_python_semantic
```
Run a specific mdtest (use a substring of the test name):
```sh
MDTEST_TEST_FILTER="<filter>" cargo nextest run -p ty_python_semantic mdtest
```
Update snapshots after running tests:
```sh
cargo insta accept
```
## Running Clippy
```sh
cargo clippy --workspace --all-targets --all-features -- -D warnings
```
## Running Debug Builds
Use debug builds (not `--release`) when developing, as release builds lack debug assertions and have slower compile times.
Run Ruff:
```sh
cargo run --bin ruff -- check path/to/file.py
```
Run ty:
```sh
cargo run --bin ty -- check path/to/file.py
```
## Pull Requests
When working on ty, PR titles should start with `[ty]` and be tagged with the `ty` GitHub label.
## Development Guidelines
- All changes must be tested. If you're not testing your changes, you're not done.
- Get your tests to pass. If you didn't run the tests, your code does not work.
- Follow existing code style. Check neighboring files for patterns.
- Always run `uvx prek run -a` at the end of a task.
- Avoid writing significant amounts of new code. This is often a sign that we're missing an existing method or mechanism that could help solve the problem. Look for existing utilities first.
- Avoid falling back to patterns that require `panic!`, `unreachable!`, or `.unwrap()`. Instead, try to encode those constraints in the type system.
- Prefer let chains (`if let` combined with `&&`) over nested `if let` statements to reduce indentation and improve readability.

View File

@@ -53,12 +53,12 @@ cargo install cargo-insta
You'll need [uv](https://docs.astral.sh/uv/getting-started/installation/) (or `pipx` and `pip`) to You'll need [uv](https://docs.astral.sh/uv/getting-started/installation/) (or `pipx` and `pip`) to
run Python utility commands. run Python utility commands.
You can optionally install hooks to automatically run the validation checks You can optionally install pre-commit hooks to automatically run the validation checks
when making a commit: when making a commit:
```shell ```shell
uv tool install prek uv tool install pre-commit
prek install pre-commit install
``` ```
We recommend [nextest](https://nexte.st/) to run Ruff's test suite (via `cargo nextest run`), We recommend [nextest](https://nexte.st/) to run Ruff's test suite (via `cargo nextest run`),
@@ -85,7 +85,7 @@ and that it passes both the lint and test validation checks:
```shell ```shell
cargo clippy --workspace --all-targets --all-features -- -D warnings # Rust linting cargo clippy --workspace --all-targets --all-features -- -D warnings # Rust linting
RUFF_UPDATE_SCHEMA=1 cargo test # Rust testing and updating ruff.schema.json RUFF_UPDATE_SCHEMA=1 cargo test # Rust testing and updating ruff.schema.json
uvx prek run -a # Rust and Python formatting, Markdown and Python linting, etc. uvx pre-commit run --all-files --show-diff-on-failure # Rust and Python formatting, Markdown and Python linting, etc.
``` ```
These checks will run on GitHub Actions when you open your pull request, but running them locally These checks will run on GitHub Actions when you open your pull request, but running them locally
@@ -381,7 +381,7 @@ Commit each step of this process separately for easier review.
- Often labels will be missing from pull requests they will need to be manually organized into the proper section - Often labels will be missing from pull requests they will need to be manually organized into the proper section
- Changes should be edited to be user-facing descriptions, avoiding internal details - Changes should be edited to be user-facing descriptions, avoiding internal details
- Square brackets (eg, `[ruff]` project name) will be automatically escaped by `prek` - Square brackets (eg, `[ruff]` project name) will be automatically escaped by `pre-commit`
Additionally, for minor releases: Additionally, for minor releases:

419
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -5,7 +5,7 @@ resolver = "2"
[workspace.package] [workspace.package]
# Please update rustfmt.toml when bumping the Rust edition # Please update rustfmt.toml when bumping the Rust edition
edition = "2024" edition = "2024"
rust-version = "1.90" rust-version = "1.89"
homepage = "https://docs.astral.sh/ruff" homepage = "https://docs.astral.sh/ruff"
documentation = "https://docs.astral.sh/ruff" documentation = "https://docs.astral.sh/ruff"
repository = "https://github.com/astral-sh/ruff" repository = "https://github.com/astral-sh/ruff"
@@ -45,7 +45,6 @@ ty = { path = "crates/ty" }
ty_combine = { path = "crates/ty_combine" } ty_combine = { path = "crates/ty_combine" }
ty_completion_eval = { path = "crates/ty_completion_eval" } ty_completion_eval = { path = "crates/ty_completion_eval" }
ty_ide = { path = "crates/ty_ide" } ty_ide = { path = "crates/ty_ide" }
ty_module_resolver = { path = "crates/ty_module_resolver" }
ty_project = { path = "crates/ty_project", default-features = false } ty_project = { path = "crates/ty_project", default-features = false }
ty_python_semantic = { path = "crates/ty_python_semantic" } ty_python_semantic = { path = "crates/ty_python_semantic" }
ty_server = { path = "crates/ty_server" } ty_server = { path = "crates/ty_server" }
@@ -58,8 +57,8 @@ anstream = { version = "0.6.18" }
anstyle = { version = "1.0.10" } anstyle = { version = "1.0.10" }
anyhow = { version = "1.0.80" } anyhow = { version = "1.0.80" }
arc-swap = { version = "1.7.1" } arc-swap = { version = "1.7.1" }
argfile = { version = "0.2.0" }
assert_fs = { version = "1.1.0" } assert_fs = { version = "1.1.0" }
argfile = { version = "0.2.0" }
bincode = { version = "2.0.0" } bincode = { version = "2.0.0" }
bitflags = { version = "2.5.0" } bitflags = { version = "2.5.0" }
bitvec = { version = "1.0.1", default-features = false, features = [ bitvec = { version = "1.0.1", default-features = false, features = [
@@ -71,31 +70,30 @@ camino = { version = "1.1.7" }
clap = { version = "4.5.3", features = ["derive"] } clap = { version = "4.5.3", features = ["derive"] }
clap_complete_command = { version = "0.6.0" } clap_complete_command = { version = "0.6.0" }
clearscreen = { version = "4.0.0" } clearscreen = { version = "4.0.0" }
csv = { version = "1.3.1" }
divan = { package = "codspeed-divan-compat", version = "4.0.4" }
codspeed-criterion-compat = { version = "4.0.4", default-features = false } codspeed-criterion-compat = { version = "4.0.4", default-features = false }
colored = { version = "3.0.0" } colored = { version = "3.0.0" }
compact_str = "0.9.0"
console_error_panic_hook = { version = "0.1.7" } console_error_panic_hook = { version = "0.1.7" }
console_log = { version = "1.0.0" } console_log = { version = "1.0.0" }
countme = { version = "3.0.1" } countme = { version = "3.0.1" }
criterion = { version = "0.8.0", default-features = false } compact_str = "0.9.0"
criterion = { version = "0.7.0", default-features = false }
crossbeam = { version = "0.8.4" } crossbeam = { version = "0.8.4" }
csv = { version = "1.3.1" }
dashmap = { version = "6.0.1" } dashmap = { version = "6.0.1" }
datatest-stable = { version = "0.3.3" } dir-test = { version = "0.4.0" }
divan = { package = "codspeed-divan-compat", version = "4.0.4" }
drop_bomb = { version = "0.1.5" }
dunce = { version = "1.0.5" } dunce = { version = "1.0.5" }
drop_bomb = { version = "0.1.5" }
etcetera = { version = "0.11.0" } etcetera = { version = "0.11.0" }
fern = { version = "0.7.0" } fern = { version = "0.7.0" }
filetime = { version = "0.2.23" } filetime = { version = "0.2.23" }
get-size2 = { version = "0.7.3", features = [ getrandom = { version = "0.3.1" }
get-size2 = { version = "0.7.0", features = [
"derive", "derive",
"smallvec", "smallvec",
"hashbrown", "hashbrown",
"compact-str", "compact-str",
"ordermap"
] } ] }
getrandom = { version = "0.3.1" }
glob = { version = "0.3.1" } glob = { version = "0.3.1" }
globset = { version = "0.4.14" } globset = { version = "0.4.14" }
globwalk = { version = "0.9.1" } globwalk = { version = "0.9.1" }
@@ -117,8 +115,8 @@ is-macro = { version = "0.3.5" }
is-wsl = { version = "0.4.0" } is-wsl = { version = "0.4.0" }
itertools = { version = "0.14.0" } itertools = { version = "0.14.0" }
jiff = { version = "0.2.0" } jiff = { version = "0.2.0" }
jod-thread = { version = "1.0.0" }
js-sys = { version = "0.3.69" } js-sys = { version = "0.3.69" }
jod-thread = { version = "1.0.0" }
libc = { version = "0.2.153" } libc = { version = "0.2.153" }
libcst = { version = "1.8.4", default-features = false } libcst = { version = "1.8.4", default-features = false }
log = { version = "0.4.17" } log = { version = "0.4.17" }
@@ -131,7 +129,7 @@ memchr = { version = "2.7.1" }
mimalloc = { version = "0.1.39" } mimalloc = { version = "0.1.39" }
natord = { version = "1.0.9" } natord = { version = "1.0.9" }
notify = { version = "8.0.0" } notify = { version = "8.0.0" }
ordermap = { version = "1.0.0" } ordermap = { version = "0.5.0" }
path-absolutize = { version = "3.1.1" } path-absolutize = { version = "3.1.1" }
path-slash = { version = "0.2.1" } path-slash = { version = "0.2.1" }
pathdiff = { version = "0.2.1" } pathdiff = { version = "0.2.1" }
@@ -140,8 +138,6 @@ pretty_assertions = "1.3.0"
proc-macro2 = { version = "1.0.79" } proc-macro2 = { version = "1.0.79" }
pyproject-toml = { version = "0.13.4" } pyproject-toml = { version = "0.13.4" }
quick-junit = { version = "0.5.0" } quick-junit = { version = "0.5.0" }
quickcheck = { version = "1.0.3", default-features = false }
quickcheck_macros = { version = "1.0.0" }
quote = { version = "1.0.23" } quote = { version = "1.0.23" }
rand = { version = "0.9.0" } rand = { version = "0.9.0" }
rayon = { version = "1.10.0" } rayon = { version = "1.10.0" }
@@ -150,7 +146,7 @@ regex-automata = { version = "0.4.9" }
rustc-hash = { version = "2.0.0" } rustc-hash = { version = "2.0.0" }
rustc-stable-hash = { version = "0.1.2" } rustc-stable-hash = { version = "0.1.2" }
# When updating salsa, make sure to also update the revision in `fuzz/Cargo.toml` # When updating salsa, make sure to also update the revision in `fuzz/Cargo.toml`
salsa = { git = "https://github.com/salsa-rs/salsa.git", rev = "9860ff6ca0f1f8f3a8d6b832020002790b501254", default-features = false, features = [ salsa = { git = "https://github.com/salsa-rs/salsa.git", rev = "59aa1075e837f5deb0d6ffb24b68fedc0f4bc5e0", default-features = false, features = [
"compact_str", "compact_str",
"macros", "macros",
"salsa_unstable", "salsa_unstable",
@@ -198,9 +194,9 @@ tryfn = { version = "0.2.1" }
typed-arena = { version = "2.0.2" } typed-arena = { version = "2.0.2" }
unic-ucd-category = { version = "0.9" } unic-ucd-category = { version = "0.9" }
unicode-ident = { version = "1.0.12" } unicode-ident = { version = "1.0.12" }
unicode-normalization = { version = "0.1.23" }
unicode-width = { version = "0.2.0" } unicode-width = { version = "0.2.0" }
unicode_names2 = { version = "1.2.2" } unicode_names2 = { version = "1.2.2" }
unicode-normalization = { version = "0.1.23" }
url = { version = "2.5.0" } url = { version = "2.5.0" }
uuid = { version = "1.6.1", features = ["v4", "fast-rng", "macro-diagnostics"] } uuid = { version = "1.6.1", features = ["v4", "fast-rng", "macro-diagnostics"] }
walkdir = { version = "2.3.2" } walkdir = { version = "2.3.2" }
@@ -210,13 +206,8 @@ wild = { version = "2" }
zip = { version = "0.6.6", default-features = false } zip = { version = "0.6.6", default-features = false }
[workspace.metadata.cargo-shear] [workspace.metadata.cargo-shear]
ignored = [ ignored = ["getrandom", "ruff_options_metadata", "uuid", "get-size2", "ty_completion_eval"]
"getrandom",
"ruff_options_metadata",
"uuid",
"get-size2",
"ty_completion_eval",
]
[workspace.lints.rust] [workspace.lints.rust]
unsafe_code = "warn" unsafe_code = "warn"
@@ -276,10 +267,17 @@ if_not_else = "allow"
# Diagnostics are not actionable: Enable once https://github.com/rust-lang/rust-clippy/issues/13774 is resolved. # Diagnostics are not actionable: Enable once https://github.com/rust-lang/rust-clippy/issues/13774 is resolved.
large_stack_arrays = "allow" large_stack_arrays = "allow"
[profile.release] [profile.release]
lto = "fat" lto = "fat"
codegen-units = 16 codegen-units = 16
# Profile to build a minimally sized binary for ruff/ty
[profile.minimal-size]
inherits = "release"
opt-level = "z"
codegen-units = 1
# Some crates don't change as much but benefit more from # Some crates don't change as much but benefit more from
# more expensive optimization passes, so we selectively # more expensive optimization passes, so we selectively
# decrease codegen-units in some cases. # decrease codegen-units in some cases.
@@ -290,12 +288,6 @@ codegen-units = 1
[profile.release.package.salsa] [profile.release.package.salsa]
codegen-units = 1 codegen-units = 1
# Profile to build a minimally sized binary for ruff/ty
[profile.minimal-size]
inherits = "release"
opt-level = "z"
codegen-units = 1
[profile.dev.package.insta] [profile.dev.package.insta]
opt-level = 3 opt-level = 3
@@ -335,11 +327,6 @@ strip = false
debug = "full" debug = "full"
lto = false lto = false
# Profile for faster iteration: applies minimal optimizations for faster tests.
[profile.fast-test]
inherits = "dev"
opt-level = 1
# The profile that 'cargo dist' will build with. # The profile that 'cargo dist' will build with.
[profile.dist] [profile.dist]
inherits = "release" inherits = "release"

View File

@@ -57,11 +57,8 @@ Ruff is extremely actively developed and used in major open-source projects like
...and [many more](#whos-using-ruff). ...and [many more](#whos-using-ruff).
Ruff is backed by [Astral](https://astral.sh), the creators of Ruff is backed by [Astral](https://astral.sh). Read the [launch post](https://astral.sh/blog/announcing-astral-the-company-behind-ruff),
[uv](https://github.com/astral-sh/uv) and [ty](https://github.com/astral-sh/ty). or the original [project announcement](https://notes.crmarsh.com/python-tooling-could-be-much-much-faster).
Read the [launch post](https://astral.sh/blog/announcing-astral-the-company-behind-ruff), or the
original [project announcement](https://notes.crmarsh.com/python-tooling-could-be-much-much-faster).
## Testimonials ## Testimonials
@@ -150,8 +147,8 @@ curl -LsSf https://astral.sh/ruff/install.sh | sh
powershell -c "irm https://astral.sh/ruff/install.ps1 | iex" powershell -c "irm https://astral.sh/ruff/install.ps1 | iex"
# For a specific version. # For a specific version.
curl -LsSf https://astral.sh/ruff/0.14.11/install.sh | sh curl -LsSf https://astral.sh/ruff/0.14.8/install.sh | sh
powershell -c "irm https://astral.sh/ruff/0.14.11/install.ps1 | iex" powershell -c "irm https://astral.sh/ruff/0.14.8/install.ps1 | iex"
``` ```
You can also install Ruff via [Homebrew](https://formulae.brew.sh/formula/ruff), [Conda](https://anaconda.org/conda-forge/ruff), You can also install Ruff via [Homebrew](https://formulae.brew.sh/formula/ruff), [Conda](https://anaconda.org/conda-forge/ruff),
@@ -184,7 +181,7 @@ Ruff can also be used as a [pre-commit](https://pre-commit.com/) hook via [`ruff
```yaml ```yaml
- repo: https://github.com/astral-sh/ruff-pre-commit - repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version. # Ruff version.
rev: v0.14.11 rev: v0.14.8
hooks: hooks:
# Run the linter. # Run the linter.
- id: ruff-check - id: ruff-check

View File

@@ -4,7 +4,6 @@ extend-exclude = [
"crates/ty_vendored/vendor/**/*", "crates/ty_vendored/vendor/**/*",
"**/resources/**/*", "**/resources/**/*",
"**/snapshots/**/*", "**/snapshots/**/*",
"crates/ruff_linter/src/rules/flake8_implicit_str_concat/rules/collection_literal.rs",
# Completion tests tend to have a lot of incomplete # Completion tests tend to have a lot of incomplete
# words naturally. It's annoying to have to make all # words naturally. It's annoying to have to make all
# of them actually words. So just ignore typos here. # of them actually words. So just ignore typos here.

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "ruff" name = "ruff"
version = "0.14.11" version = "0.14.8"
publish = true publish = true
authors = { workspace = true } authors = { workspace = true }
edition = { workspace = true } edition = { workspace = true }
@@ -12,13 +12,6 @@ license = { workspace = true }
readme = "../../README.md" readme = "../../README.md"
default-run = "ruff" default-run = "ruff"
[package.metadata.cargo-shear]
# Used via macro expansion.
ignored = ["jiff"]
[package.metadata.dist]
dist = true
[dependencies] [dependencies]
ruff_cache = { workspace = true } ruff_cache = { workspace = true }
ruff_db = { workspace = true, default-features = false, features = ["os"] } ruff_db = { workspace = true, default-features = false, features = ["os"] }
@@ -48,7 +41,6 @@ colored = { workspace = true }
filetime = { workspace = true } filetime = { workspace = true }
globwalk = { workspace = true } globwalk = { workspace = true }
ignore = { workspace = true } ignore = { workspace = true }
indexmap = { workspace = true }
is-macro = { workspace = true } is-macro = { workspace = true }
itertools = { workspace = true } itertools = { workspace = true }
jiff = { workspace = true } jiff = { workspace = true }
@@ -69,12 +61,6 @@ tracing = { workspace = true, features = ["log"] }
walkdir = { workspace = true } walkdir = { workspace = true }
wild = { workspace = true } wild = { workspace = true }
[target.'cfg(all(not(target_os = "windows"), not(target_os = "openbsd"), not(target_os = "aix"), not(target_os = "android"), any(target_arch = "x86_64", target_arch = "aarch64", target_arch = "powerpc64", target_arch = "riscv64")))'.dependencies]
tikv-jemallocator = { workspace = true }
[target.'cfg(target_os = "windows")'.dependencies]
mimalloc = { workspace = true }
[dev-dependencies] [dev-dependencies]
# Enable test rules during development # Enable test rules during development
ruff_linter = { workspace = true, features = ["clap", "test-rules"] } ruff_linter = { workspace = true, features = ["clap", "test-rules"] }
@@ -90,5 +76,18 @@ ruff_python_trivia = { workspace = true }
tempfile = { workspace = true } tempfile = { workspace = true }
test-case = { workspace = true } test-case = { workspace = true }
[package.metadata.cargo-shear]
# Used via macro expansion.
ignored = ["jiff"]
[package.metadata.dist]
dist = true
[target.'cfg(target_os = "windows")'.dependencies]
mimalloc = { workspace = true }
[target.'cfg(all(not(target_os = "windows"), not(target_os = "openbsd"), not(target_os = "aix"), not(target_os = "android"), any(target_arch = "x86_64", target_arch = "aarch64", target_arch = "powerpc64", target_arch = "riscv64")))'.dependencies]
tikv-jemallocator = { workspace = true }
[lints] [lints]
workspace = true workspace = true

View File

@@ -10,7 +10,7 @@ use anyhow::bail;
use clap::builder::Styles; use clap::builder::Styles;
use clap::builder::styling::{AnsiColor, Effects}; use clap::builder::styling::{AnsiColor, Effects};
use clap::builder::{TypedValueParser, ValueParserFactory}; use clap::builder::{TypedValueParser, ValueParserFactory};
use clap::{Parser, Subcommand}; use clap::{Parser, Subcommand, command};
use colored::Colorize; use colored::Colorize;
use itertools::Itertools; use itertools::Itertools;
use path_absolutize::path_dedot; use path_absolutize::path_dedot;

View File

@@ -2,7 +2,6 @@ use crate::args::{AnalyzeGraphArgs, ConfigArguments};
use crate::resolve::resolve; use crate::resolve::resolve;
use crate::{ExitStatus, resolve_default_files}; use crate::{ExitStatus, resolve_default_files};
use anyhow::Result; use anyhow::Result;
use indexmap::IndexSet;
use log::{debug, warn}; use log::{debug, warn};
use path_absolutize::CWD; use path_absolutize::CWD;
use ruff_db::system::{SystemPath, SystemPathBuf}; use ruff_db::system::{SystemPath, SystemPathBuf};
@@ -12,7 +11,7 @@ use ruff_linter::source_kind::SourceKind;
use ruff_linter::{warn_user, warn_user_once}; use ruff_linter::{warn_user, warn_user_once};
use ruff_python_ast::{PySourceType, SourceType}; use ruff_python_ast::{PySourceType, SourceType};
use ruff_workspace::resolver::{ResolvedFile, match_exclusion, python_files_in_path}; use ruff_workspace::resolver::{ResolvedFile, match_exclusion, python_files_in_path};
use rustc_hash::{FxBuildHasher, FxHashMap}; use rustc_hash::FxHashMap;
use std::io::Write; use std::io::Write;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
@@ -60,34 +59,17 @@ pub(crate) fn analyze_graph(
}) })
.collect::<FxHashMap<_, _>>(); .collect::<FxHashMap<_, _>>();
// Create a database from the source roots, combining configured `src` paths with detected // Create a database from the source roots.
// package roots. Configured paths are added first so they take precedence, and duplicates let src_roots = package_roots
// are removed.
let mut src_roots: IndexSet<SystemPathBuf, FxBuildHasher> = IndexSet::default();
// Add configured `src` paths first (for precedence), filtering to only include existing
// directories.
src_roots.extend(
pyproject_config
.settings
.linter
.src
.iter()
.filter(|path| path.is_dir())
.filter_map(|path| SystemPathBuf::from_path_buf(path.clone()).ok()),
);
// Add detected package roots.
src_roots.extend(
package_roots
.values() .values()
.filter_map(|package| package.as_deref()) .filter_map(|package| package.as_deref())
.filter_map(|path| path.parent()) .filter_map(|package| package.parent())
.filter_map(|path| SystemPathBuf::from_path_buf(path.to_path_buf()).ok()), .map(Path::to_path_buf)
); .filter_map(|path| SystemPathBuf::from_path_buf(path).ok())
.collect();
let db = ModuleDb::from_src_roots( let db = ModuleDb::from_src_roots(
src_roots.into_iter().collect(), src_roots,
pyproject_config pyproject_config
.settings .settings
.analyze .analyze

View File

@@ -1305,7 +1305,7 @@ mod tests {
settings.add_filter(r"(Panicked at) [^:]+:\d+:\d+", "$1 <location>"); settings.add_filter(r"(Panicked at) [^:]+:\d+:\d+", "$1 <location>");
let _s = settings.bind_to_scope(); let _s = settings.bind_to_scope();
assert_snapshot!(str::from_utf8(&buf)?, @" assert_snapshot!(str::from_utf8(&buf)?, @r"
io: test.py: Permission denied io: test.py: Permission denied
--> test.py:1:1 --> test.py:1:1

View File

@@ -29,10 +29,10 @@ pub(crate) fn show_settings(
bail!("No files found under the given path"); bail!("No files found under the given path");
}; };
let (settings, config_path) = resolver.resolve_with_path(&path); let settings = resolver.resolve(&path);
writeln!(writer, "Resolved settings for: \"{}\"", path.display())?; writeln!(writer, "Resolved settings for: \"{}\"", path.display())?;
if let Some(settings_path) = config_path { if let Some(settings_path) = pyproject_config.path.as_ref() {
writeln!(writer, "Settings path: \"{}\"", settings_path.display())?; writeln!(writer, "Settings path: \"{}\"", settings_path.display())?;
} }
write!(writer, "{settings}")?; write!(writer, "{settings}")?;

View File

@@ -4,3 +4,4 @@ source: crates/ruff/src/commands/check.rs
/home/ferris/project/code.py:1:1: E902 Permission denied (os error 13) /home/ferris/project/code.py:1:1: E902 Permission denied (os error 13)
/home/ferris/project/notebook.ipynb:1:1: E902 Permission denied (os error 13) /home/ferris/project/notebook.ipynb:1:1: E902 Permission denied (os error 13)
/home/ferris/project/pyproject.toml:1:1: E902 Permission denied (os error 13) /home/ferris/project/pyproject.toml:1:1: E902 Permission denied (os error 13)

View File

@@ -9,7 +9,7 @@ use std::sync::mpsc::channel;
use anyhow::Result; use anyhow::Result;
use clap::CommandFactory; use clap::CommandFactory;
use colored::Colorize; use colored::Colorize;
use log::error; use log::{error, warn};
use notify::{RecursiveMode, Watcher, recommended_watcher}; use notify::{RecursiveMode, Watcher, recommended_watcher};
use args::{GlobalConfigArgs, ServerCommand}; use args::{GlobalConfigArgs, ServerCommand};

View File

@@ -1,5 +1,6 @@
--- ---
source: crates/ruff/src/version.rs source: crates/ruff/src/version.rs
expression: version expression: version
snapshot_kind: text
--- ---
0.0.0 0.0.0

View File

@@ -1,5 +1,6 @@
--- ---
source: crates/ruff/src/version.rs source: crates/ruff/src/version.rs
expression: version expression: version
snapshot_kind: text
--- ---
0.0.0 (53b0f5d92 2023-10-19) 0.0.0 (53b0f5d92 2023-10-19)

View File

@@ -1,5 +1,6 @@
--- ---
source: crates/ruff/src/version.rs source: crates/ruff/src/version.rs
expression: version expression: version
snapshot_kind: text
--- ---
0.0.0+24 (53b0f5d92 2023-10-19) 0.0.0+24 (53b0f5d92 2023-10-19)

View File

@@ -1,6 +1,7 @@
--- ---
source: crates/ruff/src/version.rs source: crates/ruff/src/version.rs
expression: version expression: version
snapshot_kind: text
--- ---
{ {
"version": "0.0.0", "version": "0.0.0",

View File

@@ -132,7 +132,7 @@ fn dependents() -> Result<()> {
insta::with_settings!({ insta::with_settings!({
filters => INSTA_FILTERS.to_vec(), filters => INSTA_FILTERS.to_vec(),
}, { }, {
assert_cmd_snapshot!(command().arg("--direction").arg("dependents").current_dir(&root), @r#" assert_cmd_snapshot!(command().arg("--direction").arg("dependents").current_dir(&root), @r###"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -154,7 +154,7 @@ fn dependents() -> Result<()> {
} }
----- stderr ----- ----- stderr -----
"#); "###);
}); });
Ok(()) Ok(())
@@ -184,7 +184,7 @@ fn string_detection() -> Result<()> {
insta::with_settings!({ insta::with_settings!({
filters => INSTA_FILTERS.to_vec(), filters => INSTA_FILTERS.to_vec(),
}, { }, {
assert_cmd_snapshot!(command().current_dir(&root), @r#" assert_cmd_snapshot!(command().current_dir(&root), @r###"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -198,7 +198,7 @@ fn string_detection() -> Result<()> {
} }
----- stderr ----- ----- stderr -----
"#); "###);
}); });
insta::with_settings!({ insta::with_settings!({
@@ -319,7 +319,7 @@ fn globs() -> Result<()> {
insta::with_settings!({ insta::with_settings!({
filters => INSTA_FILTERS.to_vec(), filters => INSTA_FILTERS.to_vec(),
}, { }, {
assert_cmd_snapshot!(command().current_dir(&root), @r#" assert_cmd_snapshot!(command().current_dir(&root), @r###"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -340,7 +340,7 @@ fn globs() -> Result<()> {
} }
----- stderr ----- ----- stderr -----
"#); "###);
}); });
Ok(()) Ok(())
@@ -368,7 +368,7 @@ fn exclude() -> Result<()> {
insta::with_settings!({ insta::with_settings!({
filters => INSTA_FILTERS.to_vec(), filters => INSTA_FILTERS.to_vec(),
}, { }, {
assert_cmd_snapshot!(command().current_dir(&root), @r#" assert_cmd_snapshot!(command().current_dir(&root), @r###"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -381,7 +381,7 @@ fn exclude() -> Result<()> {
} }
----- stderr ----- ----- stderr -----
"#); "###);
}); });
Ok(()) Ok(())
@@ -421,7 +421,7 @@ fn wildcard() -> Result<()> {
insta::with_settings!({ insta::with_settings!({
filters => INSTA_FILTERS.to_vec(), filters => INSTA_FILTERS.to_vec(),
}, { }, {
assert_cmd_snapshot!(command().current_dir(&root), @r#" assert_cmd_snapshot!(command().current_dir(&root), @r###"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -443,7 +443,7 @@ fn wildcard() -> Result<()> {
} }
----- stderr ----- ----- stderr -----
"#); "###);
}); });
Ok(()) Ok(())
@@ -639,7 +639,7 @@ fn venv() -> Result<()> {
}, { }, {
assert_cmd_snapshot!( assert_cmd_snapshot!(
command().args(["--python", "none"]).arg("packages/albatross").current_dir(&root), command().args(["--python", "none"]).arg("packages/albatross").current_dir(&root),
@" @r"
success: false success: false
exit_code: 2 exit_code: 2
----- stdout ----- ----- stdout -----
@@ -695,7 +695,7 @@ fn notebook_basic() -> Result<()> {
insta::with_settings!({ insta::with_settings!({
filters => INSTA_FILTERS.to_vec(), filters => INSTA_FILTERS.to_vec(),
}, { }, {
assert_cmd_snapshot!(command().current_dir(&root), @r#" assert_cmd_snapshot!(command().current_dir(&root), @r###"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -708,122 +708,7 @@ fn notebook_basic() -> Result<()> {
} }
----- stderr ----- ----- stderr -----
"#); "###);
});
Ok(())
}
/// Test that the `src` configuration option is respected.
///
/// This is useful for monorepos where there are multiple source directories that need to be
/// included in the module resolution search path.
#[test]
fn src_option() -> Result<()> {
let tempdir = TempDir::new()?;
let root = ChildPath::new(tempdir.path());
// Create a lib directory with a package.
root.child("lib")
.child("mylib")
.child("__init__.py")
.write_str("def helper(): pass")?;
// Create an app directory with a file that imports from mylib.
root.child("app").child("__init__.py").write_str("")?;
root.child("app")
.child("main.py")
.write_str("from mylib import helper")?;
// Without src configured, the import from mylib won't resolve.
insta::with_settings!({
filters => INSTA_FILTERS.to_vec(),
}, {
assert_cmd_snapshot!(command().arg("app").current_dir(&root), @r#"
success: true
exit_code: 0
----- stdout -----
{
"app/__init__.py": [],
"app/main.py": []
}
----- stderr -----
"#);
});
// With src = ["lib"], the import should resolve.
root.child("ruff.toml").write_str(indoc::indoc! {r#"
src = ["lib"]
"#})?;
insta::with_settings!({
filters => INSTA_FILTERS.to_vec(),
}, {
assert_cmd_snapshot!(command().arg("app").current_dir(&root), @r#"
success: true
exit_code: 0
----- stdout -----
{
"app/__init__.py": [],
"app/main.py": [
"lib/mylib/__init__.py"
]
}
----- stderr -----
"#);
});
Ok(())
}
/// Test that glob patterns in `src` are expanded.
#[test]
fn src_glob_expansion() -> Result<()> {
let tempdir = TempDir::new()?;
let root = ChildPath::new(tempdir.path());
// Create multiple lib directories with packages.
root.child("libs")
.child("lib_a")
.child("pkg_a")
.child("__init__.py")
.write_str("def func_a(): pass")?;
root.child("libs")
.child("lib_b")
.child("pkg_b")
.child("__init__.py")
.write_str("def func_b(): pass")?;
// Create an app that imports from both packages.
root.child("app").child("__init__.py").write_str("")?;
root.child("app")
.child("main.py")
.write_str("from pkg_a import func_a\nfrom pkg_b import func_b")?;
// Use a glob pattern to include all lib directories.
root.child("ruff.toml").write_str(indoc::indoc! {r#"
src = ["libs/*"]
"#})?;
insta::with_settings!({
filters => INSTA_FILTERS.to_vec(),
}, {
assert_cmd_snapshot!(command().arg("app").current_dir(&root), @r#"
success: true
exit_code: 0
----- stdout -----
{
"app/__init__.py": [],
"app/main.py": [
"libs/lib_a/pkg_a/__init__.py",
"libs/lib_b/pkg_b/__init__.py"
]
}
----- stderr -----
"#);
}); });
Ok(()) Ok(())
@@ -880,7 +765,7 @@ fn notebook_with_magic() -> Result<()> {
insta::with_settings!({ insta::with_settings!({
filters => INSTA_FILTERS.to_vec(), filters => INSTA_FILTERS.to_vec(),
}, { }, {
assert_cmd_snapshot!(command().current_dir(&root), @r#" assert_cmd_snapshot!(command().current_dir(&root), @r###"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -893,7 +778,7 @@ fn notebook_with_magic() -> Result<()> {
} }
----- stderr ----- ----- stderr -----
"#); "###);
}); });
Ok(()) Ok(())

View File

@@ -29,7 +29,7 @@ fn type_checking_imports() -> anyhow::Result<()> {
("ruff/c.py", ""), ("ruff/c.py", ""),
])?; ])?;
assert_cmd_snapshot!(test.command(), @r#" assert_cmd_snapshot!(test.command(), @r###"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -46,12 +46,12 @@ fn type_checking_imports() -> anyhow::Result<()> {
} }
----- stderr ----- ----- stderr -----
"#); "###);
assert_cmd_snapshot!( assert_cmd_snapshot!(
test.command() test.command()
.arg("--no-type-checking-imports"), .arg("--no-type-checking-imports"),
@r#" @r###"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -65,7 +65,7 @@ fn type_checking_imports() -> anyhow::Result<()> {
} }
----- stderr ----- ----- stderr -----
"# "###
); );
Ok(()) Ok(())
@@ -103,7 +103,7 @@ fn type_checking_imports_from_config() -> anyhow::Result<()> {
), ),
])?; ])?;
assert_cmd_snapshot!(test.command(), @r#" assert_cmd_snapshot!(test.command(), @r###"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -117,7 +117,7 @@ fn type_checking_imports_from_config() -> anyhow::Result<()> {
} }
----- stderr ----- ----- stderr -----
"#); "###);
test.write_file( test.write_file(
"ruff.toml", "ruff.toml",
@@ -127,7 +127,7 @@ fn type_checking_imports_from_config() -> anyhow::Result<()> {
"#, "#,
)?; )?;
assert_cmd_snapshot!(test.command(), @r#" assert_cmd_snapshot!(test.command(), @r###"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -144,7 +144,7 @@ fn type_checking_imports_from_config() -> anyhow::Result<()> {
} }
----- stderr ----- ----- stderr -----
"# "###
); );
Ok(()) Ok(())

View File

@@ -51,7 +51,7 @@ fn default_files() -> Result<()> {
assert_cmd_snapshot!(test.format_command() assert_cmd_snapshot!(test.format_command()
.arg("--isolated") .arg("--isolated")
.arg("--check"), @" .arg("--check"), @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -71,7 +71,7 @@ fn format_warn_stdin_filename_with_files() -> Result<()> {
assert_cmd_snapshot!(test.format_command() assert_cmd_snapshot!(test.format_command()
.args(["--isolated", "--stdin-filename", "foo.py"]) .args(["--isolated", "--stdin-filename", "foo.py"])
.arg("foo.py") .arg("foo.py")
.pass_stdin("foo = 1"), @" .pass_stdin("foo = 1"), @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -87,7 +87,7 @@ fn format_warn_stdin_filename_with_files() -> Result<()> {
fn nonexistent_config_file() -> Result<()> { fn nonexistent_config_file() -> Result<()> {
let test = CliTest::new()?; let test = CliTest::new()?;
assert_cmd_snapshot!(test.format_command() assert_cmd_snapshot!(test.format_command()
.args(["--config", "foo.toml", "."]), @" .args(["--config", "foo.toml", "."]), @r"
success: false success: false
exit_code: 2 exit_code: 2
----- stdout ----- ----- stdout -----
@@ -111,7 +111,7 @@ fn nonexistent_config_file() -> Result<()> {
fn config_override_rejected_if_invalid_toml() -> Result<()> { fn config_override_rejected_if_invalid_toml() -> Result<()> {
let test = CliTest::new()?; let test = CliTest::new()?;
assert_cmd_snapshot!(test.format_command() assert_cmd_snapshot!(test.format_command()
.args(["--config", "foo = bar", "."]), @" .args(["--config", "foo = bar", "."]), @r"
success: false success: false
exit_code: 2 exit_code: 2
----- stdout ----- ----- stdout -----
@@ -145,7 +145,7 @@ fn too_many_config_files() -> Result<()> {
.arg("ruff.toml") .arg("ruff.toml")
.arg("--config") .arg("--config")
.arg("ruff2.toml") .arg("ruff2.toml")
.arg("."), @" .arg("."), @r"
success: false success: false
exit_code: 2 exit_code: 2
----- stdout ----- ----- stdout -----
@@ -168,7 +168,7 @@ fn config_file_and_isolated() -> Result<()> {
.arg("--isolated") .arg("--isolated")
.arg("--config") .arg("--config")
.arg("ruff.toml") .arg("ruff.toml")
.arg("."), @" .arg("."), @r"
success: false success: false
exit_code: 2 exit_code: 2
----- stdout ----- ----- stdout -----
@@ -390,7 +390,7 @@ fn mixed_line_endings() -> Result<()> {
assert_cmd_snapshot!(test.format_command() assert_cmd_snapshot!(test.format_command()
.arg("--diff") .arg("--diff")
.arg("--isolated") .arg("--isolated")
.arg("."), @" .arg("."), @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -446,7 +446,7 @@ OTHER = "OTHER"
// Explicitly pass test.py, should be formatted regardless of it being excluded by format.exclude // Explicitly pass test.py, should be formatted regardless of it being excluded by format.exclude
.arg("test.py") .arg("test.py")
// Format all other files in the directory, should respect the `exclude` and `format.exclude` options // Format all other files in the directory, should respect the `exclude` and `format.exclude` options
.arg("."), @" .arg("."), @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -469,7 +469,7 @@ fn deduplicate_directory_and_explicit_file() -> Result<()> {
.arg("--check") .arg("--check")
.arg(".") .arg(".")
.arg("main.py"), .arg("main.py"),
@" @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -495,7 +495,7 @@ from module import =
assert_cmd_snapshot!(test.format_command() assert_cmd_snapshot!(test.format_command()
.arg("--check") .arg("--check")
.arg("--isolated") .arg("--isolated")
.arg("main.py"), @" .arg("main.py"), @r"
success: false success: false
exit_code: 2 exit_code: 2
----- stdout ----- ----- stdout -----
@@ -522,7 +522,7 @@ if __name__ == "__main__":
assert_cmd_snapshot!(test.format_command() assert_cmd_snapshot!(test.format_command()
.arg("--isolated") .arg("--isolated")
.arg("--check") .arg("--check")
.arg("main.py"), @" .arg("main.py"), @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -534,7 +534,7 @@ if __name__ == "__main__":
assert_cmd_snapshot!(test.format_command() assert_cmd_snapshot!(test.format_command()
.arg("--isolated") .arg("--isolated")
.arg("main.py"), @" .arg("main.py"), @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -545,7 +545,7 @@ if __name__ == "__main__":
assert_cmd_snapshot!(test.format_command() assert_cmd_snapshot!(test.format_command()
.arg("--isolated") .arg("--isolated")
.arg("main.py"), @" .arg("main.py"), @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -614,7 +614,7 @@ fn output_format_notebook() -> Result<()> {
assert_cmd_snapshot!( assert_cmd_snapshot!(
test.format_command().args(["--isolated", "--preview", "--check"]).arg(path), test.format_command().args(["--isolated", "--preview", "--check"]).arg(path),
@" @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -672,7 +672,7 @@ if __name__ == "__main__":
assert_cmd_snapshot!(test.format_command() assert_cmd_snapshot!(test.format_command()
.arg("--isolated") .arg("--isolated")
.arg("--exit-non-zero-on-format") .arg("--exit-non-zero-on-format")
.arg("main.py"), @" .arg("main.py"), @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -685,7 +685,7 @@ if __name__ == "__main__":
assert_cmd_snapshot!(test.format_command() assert_cmd_snapshot!(test.format_command()
.arg("--isolated") .arg("--isolated")
.arg("--exit-non-zero-on-format") .arg("--exit-non-zero-on-format")
.arg("main.py"), @" .arg("main.py"), @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -701,7 +701,7 @@ if __name__ == "__main__":
assert_cmd_snapshot!(test.format_command() assert_cmd_snapshot!(test.format_command()
.arg("--isolated") .arg("--isolated")
.arg("--exit-non-zero-on-fix") .arg("--exit-non-zero-on-fix")
.arg("main.py"), @" .arg("main.py"), @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -714,7 +714,7 @@ if __name__ == "__main__":
assert_cmd_snapshot!(test.format_command() assert_cmd_snapshot!(test.format_command()
.arg("--isolated") .arg("--isolated")
.arg("--exit-non-zero-on-fix") .arg("--exit-non-zero-on-fix")
.arg("main.py"), @" .arg("main.py"), @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -771,7 +771,7 @@ OTHER = "OTHER"
// Explicitly pass test.py, should not be formatted because of --force-exclude // Explicitly pass test.py, should not be formatted because of --force-exclude
.arg("test.py") .arg("test.py")
// Format all other files in the directory, should respect the `exclude` and `format.exclude` options // Format all other files in the directory, should respect the `exclude` and `format.exclude` options
.arg("."), @" .arg("."), @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -931,7 +931,7 @@ tab-size = 2
.pass_stdin(r" .pass_stdin(r"
if True: if True:
pass pass
"), @" "), @r"
success: false success: false
exit_code: 2 exit_code: 2
----- stdout ----- ----- stdout -----
@@ -1144,7 +1144,7 @@ def say_hy(name: str):
assert_cmd_snapshot!(test.format_command() assert_cmd_snapshot!(test.format_command()
.arg("--config") .arg("--config")
.arg("ruff.toml") .arg("ruff.toml")
.arg("test.py"), @" .arg("test.py"), @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -1184,7 +1184,7 @@ def say_hy(name: str):
assert_cmd_snapshot!(test.format_command() assert_cmd_snapshot!(test.format_command()
.arg("--config") .arg("--config")
.arg("ruff.toml") .arg("ruff.toml")
.arg("test.py"), @" .arg("test.py"), @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -1216,7 +1216,7 @@ def say_hy(name: str):
assert_cmd_snapshot!(test.format_command() assert_cmd_snapshot!(test.format_command()
.arg("--config") .arg("--config")
.arg("ruff.toml") .arg("ruff.toml")
.arg("test.py"), @" .arg("test.py"), @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -1246,7 +1246,7 @@ fn test_diff() -> Result<()> {
assert_cmd_snapshot!( assert_cmd_snapshot!(
test.format_command().args(["--isolated", "--diff"]).args(paths), test.format_command().args(["--isolated", "--diff"]).args(paths),
@" @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -1311,7 +1311,7 @@ fn test_diff_no_change() -> Result<()> {
let paths = [fixtures.join("unformatted.py")]; let paths = [fixtures.join("unformatted.py")];
assert_cmd_snapshot!( assert_cmd_snapshot!(
test.format_command().args(["--isolated", "--diff"]).args(paths), test.format_command().args(["--isolated", "--diff"]).args(paths),
@" @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -1341,7 +1341,7 @@ fn test_diff_stdin_unformatted() -> Result<()> {
test.format_command() test.format_command()
.args(["--isolated", "--diff", "-", "--stdin-filename", "unformatted.py"]) .args(["--isolated", "--diff", "-", "--stdin-filename", "unformatted.py"])
.pass_stdin(unformatted), .pass_stdin(unformatted),
@" @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -1366,7 +1366,7 @@ fn test_diff_stdin_formatted() -> Result<()> {
let unformatted = fs::read(fixtures.join("formatted.py")).unwrap(); let unformatted = fs::read(fixtures.join("formatted.py")).unwrap();
assert_cmd_snapshot!( assert_cmd_snapshot!(
test.format_command().args(["--isolated", "--diff", "-"]).pass_stdin(unformatted), test.format_command().args(["--isolated", "--diff", "-"]).pass_stdin(unformatted),
@" @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -1873,7 +1873,7 @@ include = ["*.ipy"]
assert_cmd_snapshot!(test.format_command() assert_cmd_snapshot!(test.format_command()
.args(["--config", "ruff.toml"]) .args(["--config", "ruff.toml"])
.args(["--extension", "ipy:ipynb"]) .args(["--extension", "ipy:ipynb"])
.arg("."), @" .arg("."), @r"
success: false success: false
exit_code: 2 exit_code: 2
----- stdout ----- ----- stdout -----
@@ -1938,7 +1938,7 @@ include = ["*.ipy"]
assert_cmd_snapshot!(test.format_command() assert_cmd_snapshot!(test.format_command()
.args(["--config", "ruff.toml"]) .args(["--config", "ruff.toml"])
.args(["--extension", "ipy:ipynb"]) .args(["--extension", "ipy:ipynb"])
.arg("."), @" .arg("."), @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -2021,7 +2021,7 @@ def file2(arg1, arg2,):
assert_cmd_snapshot!(test.format_command() assert_cmd_snapshot!(test.format_command()
.args(["--isolated", "--range=1:8-1:15"]) .args(["--isolated", "--range=1:8-1:15"])
.arg("file1.py") .arg("file1.py")
.arg("file2.py"), @" .arg("file2.py"), @r"
success: false success: false
exit_code: 2 exit_code: 2
----- stdout ----- ----- stdout -----
@@ -2068,7 +2068,7 @@ fn range_start_larger_than_end() -> Result<()> {
def foo(arg1, arg2,): def foo(arg1, arg2,):
print("Shouldn't format this" ) print("Shouldn't format this" )
"#), @" "#), @r"
success: false success: false
exit_code: 2 exit_code: 2
----- stdout ----- ----- stdout -----
@@ -2168,7 +2168,7 @@ fn range_missing_line() -> Result<()> {
def foo(arg1, arg2,): def foo(arg1, arg2,):
print("Should format this" ) print("Should format this" )
"#), @" "#), @r"
success: false success: false
exit_code: 2 exit_code: 2
----- stdout ----- ----- stdout -----
@@ -2192,7 +2192,7 @@ fn zero_line_number() -> Result<()> {
def foo(arg1, arg2,): def foo(arg1, arg2,):
print("Should format this" ) print("Should format this" )
"#), @" "#), @r"
success: false success: false
exit_code: 2 exit_code: 2
----- stdout ----- ----- stdout -----
@@ -2217,7 +2217,7 @@ fn column_and_line_zero() -> Result<()> {
def foo(arg1, arg2,): def foo(arg1, arg2,):
print("Should format this" ) print("Should format this" )
"#), @" "#), @r"
success: false success: false
exit_code: 2 exit_code: 2
----- stdout ----- ----- stdout -----
@@ -2274,7 +2274,7 @@ fn range_formatting_notebook() -> Result<()> {
"nbformat": 4, "nbformat": 4,
"nbformat_minor": 5 "nbformat_minor": 5
} }
"#), @" "#), @r"
success: false success: false
exit_code: 2 exit_code: 2
----- stdout ----- ----- stdout -----
@@ -2355,7 +2355,7 @@ fn cookiecutter_globbing() -> Result<()> {
])?; ])?;
assert_cmd_snapshot!(test.format_command() assert_cmd_snapshot!(test.format_command()
.args(["--isolated", "--diff", "."]), @" .args(["--isolated", "--diff", "."]), @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -2374,7 +2374,7 @@ fn stable_output_format_warning() -> Result<()> {
test.format_command() test.format_command()
.args(["--output-format=full", "-"]) .args(["--output-format=full", "-"])
.pass_stdin(""), .pass_stdin(""),
@" @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----

File diff suppressed because it is too large Load Diff

View File

@@ -14,6 +14,6 @@ info:
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
::error title=Ruff (unformatted),file=[TMP]/input.py,line=1,endLine=2::input.py:1:1: unformatted: File would be reformatted ::error title=Ruff (unformatted),file=[TMP]/input.py,line=1,col=1,endLine=2,endColumn=1::input.py:1:1: unformatted: File would be reformatted
----- stderr ----- ----- stderr -----

View File

@@ -1,5 +1,5 @@
--- ---
source: crates/ruff/tests/cli/lint.rs source: crates/ruff/tests/lint.rs
info: info:
program: ruff program: ruff
args: args:
@@ -17,6 +17,7 @@ info:
- "--fix" - "--fix"
- "-" - "-"
stdin: "1" stdin: "1"
snapshot_kind: text
--- ---
success: false success: false
exit_code: 2 exit_code: 2

View File

@@ -1,5 +1,5 @@
--- ---
source: crates/ruff/tests/cli/lint.rs source: crates/ruff/tests/lint.rs
info: info:
program: ruff program: ruff
args: args:

View File

@@ -1,5 +1,5 @@
--- ---
source: crates/ruff/tests/cli/lint.rs source: crates/ruff/tests/lint.rs
info: info:
program: ruff program: ruff
args: args:

View File

@@ -1,5 +1,5 @@
--- ---
source: crates/ruff/tests/cli/lint.rs source: crates/ruff/tests/lint.rs
info: info:
program: ruff program: ruff
args: args:

View File

@@ -1,5 +1,5 @@
--- ---
source: crates/ruff/tests/cli/lint.rs source: crates/ruff/tests/lint.rs
info: info:
program: ruff program: ruff
args: args:

View File

@@ -1,5 +1,5 @@
--- ---
source: crates/ruff/tests/cli/lint.rs source: crates/ruff/tests/lint.rs
info: info:
program: ruff program: ruff
args: args:

View File

@@ -1,5 +1,5 @@
--- ---
source: crates/ruff/tests/cli/lint.rs source: crates/ruff/tests/lint.rs
info: info:
program: ruff program: ruff
args: args:

View File

@@ -1,5 +1,5 @@
--- ---
source: crates/ruff/tests/cli/lint.rs source: crates/ruff/tests/lint.rs
info: info:
program: ruff program: ruff
args: args:

View File

@@ -1,5 +1,5 @@
--- ---
source: crates/ruff/tests/cli/lint.rs source: crates/ruff/tests/lint.rs
info: info:
program: ruff program: ruff
args: args:

View File

@@ -1,5 +1,5 @@
--- ---
source: crates/ruff/tests/cli/lint.rs source: crates/ruff/tests/lint.rs
info: info:
program: ruff program: ruff
args: args:

View File

@@ -1,5 +1,5 @@
--- ---
source: crates/ruff/tests/cli/lint.rs source: crates/ruff/tests/lint.rs
info: info:
program: ruff program: ruff
args: args:

View File

@@ -1,5 +1,5 @@
--- ---
source: crates/ruff/tests/cli/lint.rs source: crates/ruff/tests/lint.rs
info: info:
program: ruff program: ruff
args: args:

View File

@@ -1,5 +1,5 @@
--- ---
source: crates/ruff/tests/cli/lint.rs source: crates/ruff/tests/lint.rs
info: info:
program: ruff program: ruff
args: args:

View File

@@ -12,6 +12,7 @@ info:
- "--target-version" - "--target-version"
- py39 - py39
- input.py - input.py
snapshot_kind: text
--- ---
success: false success: false
exit_code: 1 exit_code: 1

View File

@@ -1,5 +1,5 @@
--- ---
source: crates/ruff/tests/cli/lint.rs source: crates/ruff/tests/lint.rs
info: info:
program: ruff program: ruff
args: args:

View File

@@ -1,5 +1,5 @@
--- ---
source: crates/ruff/tests/cli/lint.rs source: crates/ruff/tests/lint.rs
info: info:
program: ruff program: ruff
args: args:

View File

@@ -1,5 +1,5 @@
--- ---
source: crates/ruff/tests/cli/lint.rs source: crates/ruff/tests/lint.rs
info: info:
program: ruff program: ruff
args: args:

View File

@@ -125,7 +125,7 @@ linter.flake8_copyright.notice_rgx = (?i)Copyright\s+((?:\(C\)|©)\s+)?\d{4}((-|
linter.flake8_copyright.author = none linter.flake8_copyright.author = none
linter.flake8_copyright.min_file_size = 0 linter.flake8_copyright.min_file_size = 0
linter.flake8_errmsg.max_string_length = 0 linter.flake8_errmsg.max_string_length = 0
linter.flake8_gettext.function_names = [ linter.flake8_gettext.functions_names = [
_, _,
gettext, gettext,
ngettext, ngettext,
@@ -261,7 +261,6 @@ linter.pylint.max_locals = 15
linter.pylint.max_nested_blocks = 5 linter.pylint.max_nested_blocks = 5
linter.pyupgrade.keep_runtime_typing = false linter.pyupgrade.keep_runtime_typing = false
linter.ruff.parenthesize_tuple_in_subscript = false linter.ruff.parenthesize_tuple_in_subscript = false
linter.ruff.strictly_empty_init_modules = false
# Formatter Settings # Formatter Settings
formatter.exclude = [] formatter.exclude = []

View File

@@ -127,7 +127,7 @@ linter.flake8_copyright.notice_rgx = (?i)Copyright\s+((?:\(C\)|©)\s+)?\d{4}((-|
linter.flake8_copyright.author = none linter.flake8_copyright.author = none
linter.flake8_copyright.min_file_size = 0 linter.flake8_copyright.min_file_size = 0
linter.flake8_errmsg.max_string_length = 0 linter.flake8_errmsg.max_string_length = 0
linter.flake8_gettext.function_names = [ linter.flake8_gettext.functions_names = [
_, _,
gettext, gettext,
ngettext, ngettext,
@@ -263,7 +263,6 @@ linter.pylint.max_locals = 15
linter.pylint.max_nested_blocks = 5 linter.pylint.max_nested_blocks = 5
linter.pyupgrade.keep_runtime_typing = false linter.pyupgrade.keep_runtime_typing = false
linter.ruff.parenthesize_tuple_in_subscript = false linter.ruff.parenthesize_tuple_in_subscript = false
linter.ruff.strictly_empty_init_modules = false
# Formatter Settings # Formatter Settings
formatter.exclude = [] formatter.exclude = []

View File

@@ -129,7 +129,7 @@ linter.flake8_copyright.notice_rgx = (?i)Copyright\s+((?:\(C\)|©)\s+)?\d{4}((-|
linter.flake8_copyright.author = none linter.flake8_copyright.author = none
linter.flake8_copyright.min_file_size = 0 linter.flake8_copyright.min_file_size = 0
linter.flake8_errmsg.max_string_length = 0 linter.flake8_errmsg.max_string_length = 0
linter.flake8_gettext.function_names = [ linter.flake8_gettext.functions_names = [
_, _,
gettext, gettext,
ngettext, ngettext,
@@ -265,7 +265,6 @@ linter.pylint.max_locals = 15
linter.pylint.max_nested_blocks = 5 linter.pylint.max_nested_blocks = 5
linter.pyupgrade.keep_runtime_typing = false linter.pyupgrade.keep_runtime_typing = false
linter.ruff.parenthesize_tuple_in_subscript = false linter.ruff.parenthesize_tuple_in_subscript = false
linter.ruff.strictly_empty_init_modules = false
# Formatter Settings # Formatter Settings
formatter.exclude = [] formatter.exclude = []

View File

@@ -129,7 +129,7 @@ linter.flake8_copyright.notice_rgx = (?i)Copyright\s+((?:\(C\)|©)\s+)?\d{4}((-|
linter.flake8_copyright.author = none linter.flake8_copyright.author = none
linter.flake8_copyright.min_file_size = 0 linter.flake8_copyright.min_file_size = 0
linter.flake8_errmsg.max_string_length = 0 linter.flake8_errmsg.max_string_length = 0
linter.flake8_gettext.function_names = [ linter.flake8_gettext.functions_names = [
_, _,
gettext, gettext,
ngettext, ngettext,
@@ -265,7 +265,6 @@ linter.pylint.max_locals = 15
linter.pylint.max_nested_blocks = 5 linter.pylint.max_nested_blocks = 5
linter.pyupgrade.keep_runtime_typing = false linter.pyupgrade.keep_runtime_typing = false
linter.ruff.parenthesize_tuple_in_subscript = false linter.ruff.parenthesize_tuple_in_subscript = false
linter.ruff.strictly_empty_init_modules = false
# Formatter Settings # Formatter Settings
formatter.exclude = [] formatter.exclude = []

View File

@@ -126,7 +126,7 @@ linter.flake8_copyright.notice_rgx = (?i)Copyright\s+((?:\(C\)|©)\s+)?\d{4}((-|
linter.flake8_copyright.author = none linter.flake8_copyright.author = none
linter.flake8_copyright.min_file_size = 0 linter.flake8_copyright.min_file_size = 0
linter.flake8_errmsg.max_string_length = 0 linter.flake8_errmsg.max_string_length = 0
linter.flake8_gettext.function_names = [ linter.flake8_gettext.functions_names = [
_, _,
gettext, gettext,
ngettext, ngettext,
@@ -262,7 +262,6 @@ linter.pylint.max_locals = 15
linter.pylint.max_nested_blocks = 5 linter.pylint.max_nested_blocks = 5
linter.pyupgrade.keep_runtime_typing = false linter.pyupgrade.keep_runtime_typing = false
linter.ruff.parenthesize_tuple_in_subscript = false linter.ruff.parenthesize_tuple_in_subscript = false
linter.ruff.strictly_empty_init_modules = false
# Formatter Settings # Formatter Settings
formatter.exclude = [] formatter.exclude = []

View File

@@ -16,7 +16,6 @@ success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
Resolved settings for: "[TMP]/foo/test.py" Resolved settings for: "[TMP]/foo/test.py"
Settings path: "[TMP]/foo/pyproject.toml"
# General Settings # General Settings
cache_dir = "[TMP]/foo/.ruff_cache" cache_dir = "[TMP]/foo/.ruff_cache"
@@ -127,7 +126,7 @@ linter.flake8_copyright.notice_rgx = (?i)Copyright\s+((?:\(C\)|©)\s+)?\d{4}((-|
linter.flake8_copyright.author = none linter.flake8_copyright.author = none
linter.flake8_copyright.min_file_size = 0 linter.flake8_copyright.min_file_size = 0
linter.flake8_errmsg.max_string_length = 0 linter.flake8_errmsg.max_string_length = 0
linter.flake8_gettext.function_names = [ linter.flake8_gettext.functions_names = [
_, _,
gettext, gettext,
ngettext, ngettext,
@@ -263,7 +262,6 @@ linter.pylint.max_locals = 15
linter.pylint.max_nested_blocks = 5 linter.pylint.max_nested_blocks = 5
linter.pyupgrade.keep_runtime_typing = false linter.pyupgrade.keep_runtime_typing = false
linter.ruff.parenthesize_tuple_in_subscript = false linter.ruff.parenthesize_tuple_in_subscript = false
linter.ruff.strictly_empty_init_modules = false
# Formatter Settings # Formatter Settings
formatter.exclude = [] formatter.exclude = []

View File

@@ -125,7 +125,7 @@ linter.flake8_copyright.notice_rgx = (?i)Copyright\s+((?:\(C\)|©)\s+)?\d{4}((-|
linter.flake8_copyright.author = none linter.flake8_copyright.author = none
linter.flake8_copyright.min_file_size = 0 linter.flake8_copyright.min_file_size = 0
linter.flake8_errmsg.max_string_length = 0 linter.flake8_errmsg.max_string_length = 0
linter.flake8_gettext.function_names = [ linter.flake8_gettext.functions_names = [
_, _,
gettext, gettext,
ngettext, ngettext,
@@ -261,7 +261,6 @@ linter.pylint.max_locals = 15
linter.pylint.max_nested_blocks = 5 linter.pylint.max_nested_blocks = 5
linter.pyupgrade.keep_runtime_typing = false linter.pyupgrade.keep_runtime_typing = false
linter.ruff.parenthesize_tuple_in_subscript = false linter.ruff.parenthesize_tuple_in_subscript = false
linter.ruff.strictly_empty_init_modules = false
# Formatter Settings # Formatter Settings
formatter.exclude = [] formatter.exclude = []

View File

@@ -125,7 +125,7 @@ linter.flake8_copyright.notice_rgx = (?i)Copyright\s+((?:\(C\)|©)\s+)?\d{4}((-|
linter.flake8_copyright.author = none linter.flake8_copyright.author = none
linter.flake8_copyright.min_file_size = 0 linter.flake8_copyright.min_file_size = 0
linter.flake8_errmsg.max_string_length = 0 linter.flake8_errmsg.max_string_length = 0
linter.flake8_gettext.function_names = [ linter.flake8_gettext.functions_names = [
_, _,
gettext, gettext,
ngettext, ngettext,
@@ -261,7 +261,6 @@ linter.pylint.max_locals = 15
linter.pylint.max_nested_blocks = 5 linter.pylint.max_nested_blocks = 5
linter.pyupgrade.keep_runtime_typing = false linter.pyupgrade.keep_runtime_typing = false
linter.ruff.parenthesize_tuple_in_subscript = false linter.ruff.parenthesize_tuple_in_subscript = false
linter.ruff.strictly_empty_init_modules = false
# Formatter Settings # Formatter Settings
formatter.exclude = [] formatter.exclude = []

View File

@@ -125,7 +125,7 @@ linter.flake8_copyright.notice_rgx = (?i)Copyright\s+((?:\(C\)|©)\s+)?\d{4}((-|
linter.flake8_copyright.author = none linter.flake8_copyright.author = none
linter.flake8_copyright.min_file_size = 0 linter.flake8_copyright.min_file_size = 0
linter.flake8_errmsg.max_string_length = 0 linter.flake8_errmsg.max_string_length = 0
linter.flake8_gettext.function_names = [ linter.flake8_gettext.functions_names = [
_, _,
gettext, gettext,
ngettext, ngettext,
@@ -261,7 +261,6 @@ linter.pylint.max_locals = 15
linter.pylint.max_nested_blocks = 5 linter.pylint.max_nested_blocks = 5
linter.pyupgrade.keep_runtime_typing = false linter.pyupgrade.keep_runtime_typing = false
linter.ruff.parenthesize_tuple_in_subscript = false linter.ruff.parenthesize_tuple_in_subscript = false
linter.ruff.strictly_empty_init_modules = false
# Formatter Settings # Formatter Settings
formatter.exclude = [] formatter.exclude = []

View File

@@ -1,5 +1,5 @@
--- ---
source: crates/ruff/tests/cli/lint.rs source: crates/ruff/tests/lint.rs
info: info:
program: ruff program: ruff
args: args:

View File

@@ -18,7 +18,7 @@ fn check_in_deleted_directory_errors() {
set_current_dir(&temp_path).unwrap(); set_current_dir(&temp_path).unwrap();
drop(temp_dir); drop(temp_dir);
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)).arg("check"), @" assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)).arg("check"), @r###"
success: false success: false
exit_code: 2 exit_code: 2
----- stdout ----- ----- stdout -----
@@ -26,5 +26,5 @@ fn check_in_deleted_directory_errors() {
----- stderr ----- ----- stderr -----
ruff failed ruff failed
Cause: Working directory does not exist Cause: Working directory does not exist
"); "###);
} }

View File

@@ -97,7 +97,7 @@ impl<'a> RuffCheck<'a> {
fn stdin_success() { fn stdin_success() {
let mut cmd = RuffCheck::default().args([]).build(); let mut cmd = RuffCheck::default().args([]).build();
assert_cmd_snapshot!(cmd assert_cmd_snapshot!(cmd
.pass_stdin(""), @" .pass_stdin(""), @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -111,7 +111,7 @@ fn stdin_success() {
fn stdin_error() { fn stdin_error() {
let mut cmd = RuffCheck::default().args([]).build(); let mut cmd = RuffCheck::default().args([]).build();
assert_cmd_snapshot!(cmd assert_cmd_snapshot!(cmd
.pass_stdin("import os\n"), @" .pass_stdin("import os\n"), @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -136,7 +136,7 @@ fn stdin_filename() {
.args(["--stdin-filename", "F401.py"]) .args(["--stdin-filename", "F401.py"])
.build(); .build();
assert_cmd_snapshot!(cmd assert_cmd_snapshot!(cmd
.pass_stdin("import os\n"), @" .pass_stdin("import os\n"), @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -172,7 +172,7 @@ import bar # unused import
)?; )?;
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
.args(["check", "--isolated", "--no-cache", "--select", "F401"]).current_dir(tempdir.path()), @" .args(["check", "--isolated", "--no-cache", "--select", "F401"]).current_dir(tempdir.path()), @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -208,7 +208,7 @@ fn check_warn_stdin_filename_with_files() {
.filename("foo.py") .filename("foo.py")
.build(); .build();
assert_cmd_snapshot!(cmd assert_cmd_snapshot!(cmd
.pass_stdin("import os\n"), @" .pass_stdin("import os\n"), @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -235,7 +235,7 @@ fn stdin_source_type_py() {
.args(["--stdin-filename", "TCH.py"]) .args(["--stdin-filename", "TCH.py"])
.build(); .build();
assert_cmd_snapshot!(cmd assert_cmd_snapshot!(cmd
.pass_stdin("import os\n"), @" .pass_stdin("import os\n"), @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -261,7 +261,7 @@ fn stdin_source_type_pyi() {
.args(["--stdin-filename", "TCH.pyi", "--select", "TCH"]) .args(["--stdin-filename", "TCH.pyi", "--select", "TCH"])
.build(); .build();
assert_cmd_snapshot!(cmd assert_cmd_snapshot!(cmd
.pass_stdin("import os\n"), @" .pass_stdin("import os\n"), @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -294,7 +294,7 @@ fn stdin_json() {
fn stdin_fix_py() { fn stdin_fix_py() {
let mut cmd = RuffCheck::default().args(["--fix"]).build(); let mut cmd = RuffCheck::default().args(["--fix"]).build();
assert_cmd_snapshot!(cmd assert_cmd_snapshot!(cmd
.pass_stdin("import os\nimport sys\n\nprint(sys.version)\n"), @" .pass_stdin("import os\nimport sys\n\nprint(sys.version)\n"), @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -572,7 +572,7 @@ fn stdin_override_parser_ipynb() {
}, },
"nbformat": 4, "nbformat": 4,
"nbformat_minor": 5 "nbformat_minor": 5
}"#), @" }"#), @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -610,7 +610,7 @@ fn stdin_override_parser_py() {
]) ])
.build(); .build();
assert_cmd_snapshot!(cmd assert_cmd_snapshot!(cmd
.pass_stdin("import os\n"), @" .pass_stdin("import os\n"), @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -633,7 +633,7 @@ fn stdin_override_parser_py() {
fn stdin_fix_when_not_fixable_should_still_print_contents() { fn stdin_fix_when_not_fixable_should_still_print_contents() {
let mut cmd = RuffCheck::default().args(["--fix"]).build(); let mut cmd = RuffCheck::default().args(["--fix"]).build();
assert_cmd_snapshot!(cmd assert_cmd_snapshot!(cmd
.pass_stdin("import os\nimport sys\n\nif (1, 2):\n print(sys.version)\n"), @" .pass_stdin("import os\nimport sys\n\nif (1, 2):\n print(sys.version)\n"), @r###"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -654,14 +654,14 @@ fn stdin_fix_when_not_fixable_should_still_print_contents() {
| |
Found 2 errors (1 fixed, 1 remaining). Found 2 errors (1 fixed, 1 remaining).
"); "###);
} }
#[test] #[test]
fn stdin_fix_when_no_issues_should_still_print_contents() { fn stdin_fix_when_no_issues_should_still_print_contents() {
let mut cmd = RuffCheck::default().args(["--fix"]).build(); let mut cmd = RuffCheck::default().args(["--fix"]).build();
assert_cmd_snapshot!(cmd assert_cmd_snapshot!(cmd
.pass_stdin("import sys\n\nprint(sys.version)\n"), @" .pass_stdin("import sys\n\nprint(sys.version)\n"), @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -805,7 +805,7 @@ fn stdin_format_jupyter() {
fn stdin_parse_error() { fn stdin_parse_error() {
let mut cmd = RuffCheck::default().build(); let mut cmd = RuffCheck::default().build();
assert_cmd_snapshot!(cmd assert_cmd_snapshot!(cmd
.pass_stdin("from foo import\n"), @" .pass_stdin("from foo import\n"), @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -826,7 +826,7 @@ fn stdin_parse_error() {
fn stdin_multiple_parse_error() { fn stdin_multiple_parse_error() {
let mut cmd = RuffCheck::default().build(); let mut cmd = RuffCheck::default().build();
assert_cmd_snapshot!(cmd assert_cmd_snapshot!(cmd
.pass_stdin("from foo import\nbar =\n"), @" .pass_stdin("from foo import\nbar =\n"), @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -857,7 +857,7 @@ fn parse_error_not_included() {
// Parse errors are always shown // Parse errors are always shown
let mut cmd = RuffCheck::default().args(["--select=I"]).build(); let mut cmd = RuffCheck::default().args(["--select=I"]).build();
assert_cmd_snapshot!(cmd assert_cmd_snapshot!(cmd
.pass_stdin("foo =\n"), @" .pass_stdin("foo =\n"), @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -878,7 +878,7 @@ fn parse_error_not_included() {
fn full_output_preview() { fn full_output_preview() {
let mut cmd = RuffCheck::default().args(["--preview"]).build(); let mut cmd = RuffCheck::default().args(["--preview"]).build();
assert_cmd_snapshot!(cmd assert_cmd_snapshot!(cmd
.pass_stdin("l = 1"), @" .pass_stdin("l = 1"), @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -907,7 +907,7 @@ preview = true
", ",
)?; )?;
let mut cmd = RuffCheck::default().config(&pyproject_toml).build(); let mut cmd = RuffCheck::default().config(&pyproject_toml).build();
assert_cmd_snapshot!(cmd.pass_stdin("l = 1"), @" assert_cmd_snapshot!(cmd.pass_stdin("l = 1"), @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -929,7 +929,7 @@ preview = true
fn full_output_format() { fn full_output_format() {
let mut cmd = RuffCheck::default().output_format("full").build(); let mut cmd = RuffCheck::default().output_format("full").build();
assert_cmd_snapshot!(cmd assert_cmd_snapshot!(cmd
.pass_stdin("l = 1"), @" .pass_stdin("l = 1"), @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -967,7 +967,7 @@ fn rule_f401_output_text() {
#[test] #[test]
fn rule_invalid_rule_name() { fn rule_invalid_rule_name() {
assert_cmd_snapshot!(ruff_cmd().args(["rule", "RUF404"]), @" assert_cmd_snapshot!(ruff_cmd().args(["rule", "RUF404"]), @r"
success: false success: false
exit_code: 2 exit_code: 2
----- stdout ----- ----- stdout -----
@@ -981,7 +981,7 @@ fn rule_invalid_rule_name() {
#[test] #[test]
fn rule_invalid_rule_name_output_json() { fn rule_invalid_rule_name_output_json() {
assert_cmd_snapshot!(ruff_cmd().args(["rule", "RUF404", "--output-format", "json"]), @" assert_cmd_snapshot!(ruff_cmd().args(["rule", "RUF404", "--output-format", "json"]), @r"
success: false success: false
exit_code: 2 exit_code: 2
----- stdout ----- ----- stdout -----
@@ -995,7 +995,7 @@ fn rule_invalid_rule_name_output_json() {
#[test] #[test]
fn rule_invalid_rule_name_output_text() { fn rule_invalid_rule_name_output_text() {
assert_cmd_snapshot!(ruff_cmd().args(["rule", "RUF404", "--output-format", "text"]), @" assert_cmd_snapshot!(ruff_cmd().args(["rule", "RUF404", "--output-format", "text"]), @r"
success: false success: false
exit_code: 2 exit_code: 2
----- stdout ----- ----- stdout -----
@@ -1016,7 +1016,7 @@ fn show_statistics() {
.pass_stdin(r#" .pass_stdin(r#"
def mvce(keys, values): def mvce(keys, values):
return {key: value for key, value in zip(keys, values)} return {key: value for key, value in zip(keys, values)}
"#), @" "#), @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -1037,7 +1037,7 @@ fn show_statistics_unsafe_fixes() {
.pass_stdin(r#" .pass_stdin(r#"
def mvce(keys, values): def mvce(keys, values):
return {key: value for key, value in zip(keys, values)} return {key: value for key, value in zip(keys, values)}
"#), @" "#), @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -1152,7 +1152,7 @@ fn show_statistics_partial_fix() {
.args(["--select", "UP035", "--statistics"]) .args(["--select", "UP035", "--statistics"])
.build(); .build();
assert_cmd_snapshot!(cmd assert_cmd_snapshot!(cmd
.pass_stdin("from typing import List, AsyncGenerator"), @" .pass_stdin("from typing import List, AsyncGenerator"), @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -1173,7 +1173,7 @@ fn show_statistics_syntax_errors() {
// ParseError // ParseError
assert_cmd_snapshot!( assert_cmd_snapshot!(
cmd.pass_stdin("x ="), cmd.pass_stdin("x ="),
@" @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -1186,7 +1186,7 @@ fn show_statistics_syntax_errors() {
// match before 3.10, UnsupportedSyntaxError // match before 3.10, UnsupportedSyntaxError
assert_cmd_snapshot!( assert_cmd_snapshot!(
cmd.pass_stdin("match 2:\n case 1: ..."), cmd.pass_stdin("match 2:\n case 1: ..."),
@" @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -1199,7 +1199,7 @@ fn show_statistics_syntax_errors() {
// rebound comprehension variable, SemanticSyntaxError // rebound comprehension variable, SemanticSyntaxError
assert_cmd_snapshot!( assert_cmd_snapshot!(
cmd.pass_stdin("[x := 1 for x in range(0)]"), cmd.pass_stdin("[x := 1 for x in range(0)]"),
@" @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -1216,7 +1216,7 @@ fn preview_enabled_prefix() {
let mut cmd = RuffCheck::default() let mut cmd = RuffCheck::default()
.args(["--select", "RUF9", "--output-format=concise", "--preview"]) .args(["--select", "RUF9", "--output-format=concise", "--preview"])
.build(); .build();
assert_cmd_snapshot!(cmd, @" assert_cmd_snapshot!(cmd, @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -1238,7 +1238,7 @@ fn preview_enabled_all() {
let mut cmd = RuffCheck::default() let mut cmd = RuffCheck::default()
.args(["--select", "ALL", "--output-format=concise", "--preview"]) .args(["--select", "ALL", "--output-format=concise", "--preview"])
.build(); .build();
assert_cmd_snapshot!(cmd, @" assert_cmd_snapshot!(cmd, @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -1265,7 +1265,7 @@ fn preview_enabled_direct() {
let mut cmd = RuffCheck::default() let mut cmd = RuffCheck::default()
.args(["--select", "RUF911", "--output-format=concise", "--preview"]) .args(["--select", "RUF911", "--output-format=concise", "--preview"])
.build(); .build();
assert_cmd_snapshot!(cmd, @" assert_cmd_snapshot!(cmd, @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -1282,7 +1282,7 @@ fn preview_disabled_direct() {
let mut cmd = RuffCheck::default() let mut cmd = RuffCheck::default()
.args(["--select", "RUF911", "--output-format=concise"]) .args(["--select", "RUF911", "--output-format=concise"])
.build(); .build();
assert_cmd_snapshot!(cmd, @" assert_cmd_snapshot!(cmd, @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -1299,7 +1299,7 @@ fn preview_disabled_prefix_empty() {
let mut cmd = RuffCheck::default() let mut cmd = RuffCheck::default()
.args(["--select", "RUF91", "--output-format=concise"]) .args(["--select", "RUF91", "--output-format=concise"])
.build(); .build();
assert_cmd_snapshot!(cmd, @" assert_cmd_snapshot!(cmd, @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -1316,7 +1316,7 @@ fn preview_disabled_does_not_warn_for_empty_ignore_selections() {
let mut cmd = RuffCheck::default() let mut cmd = RuffCheck::default()
.args(["--ignore", "RUF9", "--output-format=concise"]) .args(["--ignore", "RUF9", "--output-format=concise"])
.build(); .build();
assert_cmd_snapshot!(cmd, @" assert_cmd_snapshot!(cmd, @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -1332,7 +1332,7 @@ fn preview_disabled_does_not_warn_for_empty_fixable_selections() {
let mut cmd = RuffCheck::default() let mut cmd = RuffCheck::default()
.args(["--fixable", "RUF9", "--output-format=concise"]) .args(["--fixable", "RUF9", "--output-format=concise"])
.build(); .build();
assert_cmd_snapshot!(cmd, @" assert_cmd_snapshot!(cmd, @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -1354,7 +1354,7 @@ fn preview_group_selector() {
]) ])
.build(); .build();
assert_cmd_snapshot!(cmd assert_cmd_snapshot!(cmd
.pass_stdin("I=42\n"), @" .pass_stdin("I=42\n"), @r"
success: false success: false
exit_code: 2 exit_code: 2
----- stdout ----- ----- stdout -----
@@ -1379,7 +1379,7 @@ fn preview_enabled_group_ignore() {
"--output-format=concise", "--output-format=concise",
]) ])
.build(); .build();
assert_cmd_snapshot!(cmd, @" assert_cmd_snapshot!(cmd, @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -1400,7 +1400,7 @@ fn preview_enabled_group_ignore() {
fn removed_direct() { fn removed_direct() {
// Selection of a removed rule should fail // Selection of a removed rule should fail
let mut cmd = RuffCheck::default().args(["--select", "RUF931"]).build(); let mut cmd = RuffCheck::default().args(["--select", "RUF931"]).build();
assert_cmd_snapshot!(cmd, @" assert_cmd_snapshot!(cmd, @r"
success: false success: false
exit_code: 2 exit_code: 2
----- stdout ----- ----- stdout -----
@@ -1418,7 +1418,7 @@ fn removed_direct_multiple() {
let mut cmd = RuffCheck::default() let mut cmd = RuffCheck::default()
.args(["--select", "RUF930", "--select", "RUF931"]) .args(["--select", "RUF930", "--select", "RUF931"])
.build(); .build();
assert_cmd_snapshot!(cmd, @" assert_cmd_snapshot!(cmd, @r"
success: false success: false
exit_code: 2 exit_code: 2
----- stdout ----- ----- stdout -----
@@ -1436,7 +1436,7 @@ fn removed_indirect() {
// Selection _including_ a removed rule without matching should not fail // Selection _including_ a removed rule without matching should not fail
// nor should the rule be used // nor should the rule be used
let mut cmd = RuffCheck::default().args(["--select", "RUF93"]).build(); let mut cmd = RuffCheck::default().args(["--select", "RUF93"]).build();
assert_cmd_snapshot!(cmd, @" assert_cmd_snapshot!(cmd, @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -1449,7 +1449,7 @@ fn removed_indirect() {
#[test] #[test]
fn removed_ignore_direct() { fn removed_ignore_direct() {
let mut cmd = RuffCheck::default().args(["--ignore", "UP027"]).build(); let mut cmd = RuffCheck::default().args(["--ignore", "UP027"]).build();
assert_cmd_snapshot!(cmd, @" assert_cmd_snapshot!(cmd, @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -1466,7 +1466,7 @@ fn removed_ignore_multiple_direct() {
let mut cmd = RuffCheck::default() let mut cmd = RuffCheck::default()
.args(["--ignore", "UP027", "--ignore", "PLR1706"]) .args(["--ignore", "UP027", "--ignore", "PLR1706"])
.build(); .build();
assert_cmd_snapshot!(cmd, @" assert_cmd_snapshot!(cmd, @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -1482,7 +1482,7 @@ fn removed_ignore_multiple_direct() {
#[test] #[test]
fn removed_ignore_remapped_direct() { fn removed_ignore_remapped_direct() {
let mut cmd = RuffCheck::default().args(["--ignore", "PGH001"]).build(); let mut cmd = RuffCheck::default().args(["--ignore", "PGH001"]).build();
assert_cmd_snapshot!(cmd, @" assert_cmd_snapshot!(cmd, @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -1498,7 +1498,7 @@ fn removed_ignore_indirect() {
// `PLR170` includes removed rules but should not select or warn // `PLR170` includes removed rules but should not select or warn
// since it is not a "direct" selection // since it is not a "direct" selection
let mut cmd = RuffCheck::default().args(["--ignore", "PLR170"]).build(); let mut cmd = RuffCheck::default().args(["--ignore", "PLR170"]).build();
assert_cmd_snapshot!(cmd, @" assert_cmd_snapshot!(cmd, @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -1512,7 +1512,7 @@ fn removed_ignore_indirect() {
fn redirect_direct() { fn redirect_direct() {
// Selection of a redirected rule directly should use the new rule and warn // Selection of a redirected rule directly should use the new rule and warn
let mut cmd = RuffCheck::default().args(["--select", "RUF940"]).build(); let mut cmd = RuffCheck::default().args(["--select", "RUF940"]).build();
assert_cmd_snapshot!(cmd, @" assert_cmd_snapshot!(cmd, @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -1531,7 +1531,7 @@ fn redirect_indirect() {
// Selection _including_ a redirected rule without matching should not fail // Selection _including_ a redirected rule without matching should not fail
// nor should the rule be used // nor should the rule be used
let mut cmd = RuffCheck::default().args(["--select", "RUF94"]).build(); let mut cmd = RuffCheck::default().args(["--select", "RUF94"]).build();
assert_cmd_snapshot!(cmd, @" assert_cmd_snapshot!(cmd, @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -1546,7 +1546,7 @@ fn redirect_prefix() {
// Selection using a redirected prefix should switch to all rules in the // Selection using a redirected prefix should switch to all rules in the
// new prefix // new prefix
let mut cmd = RuffCheck::default().args(["--select", "RUF96"]).build(); let mut cmd = RuffCheck::default().args(["--select", "RUF96"]).build();
assert_cmd_snapshot!(cmd, @" assert_cmd_snapshot!(cmd, @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -1565,7 +1565,7 @@ fn deprecated_direct() {
// Selection of a deprecated rule without preview enabled should still work // Selection of a deprecated rule without preview enabled should still work
// but a warning should be displayed // but a warning should be displayed
let mut cmd = RuffCheck::default().args(["--select", "RUF920"]).build(); let mut cmd = RuffCheck::default().args(["--select", "RUF920"]).build();
assert_cmd_snapshot!(cmd, @" assert_cmd_snapshot!(cmd, @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -1586,7 +1586,7 @@ fn deprecated_multiple_direct() {
let mut cmd = RuffCheck::default() let mut cmd = RuffCheck::default()
.args(["--select", "RUF920", "--select", "RUF921"]) .args(["--select", "RUF920", "--select", "RUF921"])
.build(); .build();
assert_cmd_snapshot!(cmd, @" assert_cmd_snapshot!(cmd, @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -1609,7 +1609,7 @@ fn deprecated_indirect() {
// `RUF92` includes deprecated rules but should not warn // `RUF92` includes deprecated rules but should not warn
// since it is not a "direct" selection // since it is not a "direct" selection
let mut cmd = RuffCheck::default().args(["--select", "RUF92"]).build(); let mut cmd = RuffCheck::default().args(["--select", "RUF92"]).build();
assert_cmd_snapshot!(cmd, @" assert_cmd_snapshot!(cmd, @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -1625,7 +1625,7 @@ fn deprecated_direct_preview_enabled() {
let mut cmd = RuffCheck::default() let mut cmd = RuffCheck::default()
.args(["--select", "RUF920", "--preview"]) .args(["--select", "RUF920", "--preview"])
.build(); .build();
assert_cmd_snapshot!(cmd, @" assert_cmd_snapshot!(cmd, @r"
success: false success: false
exit_code: 2 exit_code: 2
----- stdout ----- ----- stdout -----
@@ -1642,7 +1642,7 @@ fn deprecated_indirect_preview_enabled() {
let mut cmd = RuffCheck::default() let mut cmd = RuffCheck::default()
.args(["--select", "RUF92", "--preview"]) .args(["--select", "RUF92", "--preview"])
.build(); .build();
assert_cmd_snapshot!(cmd, @" assert_cmd_snapshot!(cmd, @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -1659,7 +1659,7 @@ fn deprecated_multiple_direct_preview_enabled() {
let mut cmd = RuffCheck::default() let mut cmd = RuffCheck::default()
.args(["--select", "RUF920", "--select", "RUF921", "--preview"]) .args(["--select", "RUF920", "--select", "RUF921", "--preview"])
.build(); .build();
assert_cmd_snapshot!(cmd, @" assert_cmd_snapshot!(cmd, @r"
success: false success: false
exit_code: 2 exit_code: 2
----- stdout ----- ----- stdout -----
@@ -1720,7 +1720,7 @@ fn unreadable_dir() -> Result<()> {
.filename(unreadable_dir.to_str().unwrap()) .filename(unreadable_dir.to_str().unwrap())
.args([]) .args([])
.build(); .build();
assert_cmd_snapshot!(cmd, @" assert_cmd_snapshot!(cmd, @r###"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -1728,7 +1728,7 @@ fn unreadable_dir() -> Result<()> {
----- stderr ----- ----- stderr -----
warning: Encountered error: Permission denied (os error 13) warning: Encountered error: Permission denied (os error 13)
"); "###);
Ok(()) Ok(())
} }
@@ -1758,7 +1758,7 @@ fn check_input_from_argfile() -> Result<()> {
(file_a_path.display().to_string().as_str(), "/path/to/a.py"), (file_a_path.display().to_string().as_str(), "/path/to/a.py"),
]}, { ]}, {
assert_cmd_snapshot!(cmd assert_cmd_snapshot!(cmd
.pass_stdin(""), @" .pass_stdin(""), @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -1787,7 +1787,7 @@ fn missing_argfile_reports_error() {
insta::with_settings!({filters => vec![ insta::with_settings!({filters => vec![
("The system cannot find the file specified.", "No such file or directory") ("The system cannot find the file specified.", "No such file or directory")
]}, { ]}, {
assert_cmd_snapshot!(cmd, @" assert_cmd_snapshot!(cmd, @r"
success: false success: false
exit_code: 2 exit_code: 2
----- stdout ----- ----- stdout -----
@@ -1807,7 +1807,7 @@ fn check_hints_hidden_unsafe_fixes() {
.args(["--select", "RUF901,RUF902"]) .args(["--select", "RUF901,RUF902"])
.build(); .build();
assert_cmd_snapshot!(cmd, assert_cmd_snapshot!(cmd,
@" @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -1829,7 +1829,7 @@ fn check_hints_hidden_unsafe_fixes_with_no_safe_fixes() {
let mut cmd = RuffCheck::default().args(["--select", "RUF902"]).build(); let mut cmd = RuffCheck::default().args(["--select", "RUF902"]).build();
assert_cmd_snapshot!(cmd assert_cmd_snapshot!(cmd
.pass_stdin("x = {'a': 1, 'a': 1}\n"), .pass_stdin("x = {'a': 1, 'a': 1}\n"),
@" @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -1849,7 +1849,7 @@ fn check_no_hint_for_hidden_unsafe_fixes_when_disabled() {
.args(["--select", "RUF901,RUF902", "--no-unsafe-fixes"]) .args(["--select", "RUF901,RUF902", "--no-unsafe-fixes"])
.build(); .build();
assert_cmd_snapshot!(cmd, assert_cmd_snapshot!(cmd,
@" @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -1873,7 +1873,7 @@ fn check_no_hint_for_hidden_unsafe_fixes_with_no_safe_fixes_when_disabled() {
.build(); .build();
assert_cmd_snapshot!(cmd assert_cmd_snapshot!(cmd
.pass_stdin("x = {'a': 1, 'a': 1}\n"), .pass_stdin("x = {'a': 1, 'a': 1}\n"),
@" @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -1892,7 +1892,7 @@ fn check_shows_unsafe_fixes_with_opt_in() {
.args(["--select", "RUF901,RUF902", "--unsafe-fixes"]) .args(["--select", "RUF901,RUF902", "--unsafe-fixes"])
.build(); .build();
assert_cmd_snapshot!(cmd, assert_cmd_snapshot!(cmd,
@" @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -1915,7 +1915,7 @@ fn fix_applies_safe_fixes_by_default() {
.args(["--select", "RUF901,RUF902", "--fix"]) .args(["--select", "RUF901,RUF902", "--fix"])
.build(); .build();
assert_cmd_snapshot!(cmd, assert_cmd_snapshot!(cmd,
@" @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -1936,7 +1936,7 @@ fn fix_applies_unsafe_fixes_with_opt_in() {
.args(["--select", "RUF901,RUF902", "--fix", "--unsafe-fixes"]) .args(["--select", "RUF901,RUF902", "--fix", "--unsafe-fixes"])
.build(); .build();
assert_cmd_snapshot!(cmd, assert_cmd_snapshot!(cmd,
@" @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -1955,7 +1955,7 @@ fn fix_does_not_apply_display_only_fixes() {
.build(); .build();
assert_cmd_snapshot!(cmd assert_cmd_snapshot!(cmd
.pass_stdin("def add_to_list(item, some_list=[]): ..."), .pass_stdin("def add_to_list(item, some_list=[]): ..."),
@" @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -1975,7 +1975,7 @@ fn fix_does_not_apply_display_only_fixes_with_unsafe_fixes_enabled() {
.build(); .build();
assert_cmd_snapshot!(cmd assert_cmd_snapshot!(cmd
.pass_stdin("def add_to_list(item, some_list=[]): ..."), .pass_stdin("def add_to_list(item, some_list=[]): ..."),
@" @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -1994,7 +1994,7 @@ fn fix_only_unsafe_fixes_available() {
.args(["--select", "RUF902", "--fix"]) .args(["--select", "RUF902", "--fix"])
.build(); .build();
assert_cmd_snapshot!(cmd, assert_cmd_snapshot!(cmd,
@" @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -2014,7 +2014,7 @@ fn fix_only_flag_applies_safe_fixes_by_default() {
.args(["--select", "RUF901,RUF902", "--fix-only"]) .args(["--select", "RUF901,RUF902", "--fix-only"])
.build(); .build();
assert_cmd_snapshot!(cmd, assert_cmd_snapshot!(cmd,
@" @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -2031,7 +2031,7 @@ fn fix_only_flag_applies_unsafe_fixes_with_opt_in() {
.args(["--select", "RUF901,RUF902", "--fix-only", "--unsafe-fixes"]) .args(["--select", "RUF901,RUF902", "--fix-only", "--unsafe-fixes"])
.build(); .build();
assert_cmd_snapshot!(cmd, assert_cmd_snapshot!(cmd,
@" @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -2049,7 +2049,7 @@ fn diff_shows_safe_fixes_by_default() {
.args(["--select", "RUF901,RUF902", "--diff"]) .args(["--select", "RUF901,RUF902", "--diff"])
.build(); .build();
assert_cmd_snapshot!(cmd, assert_cmd_snapshot!(cmd,
@" @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -2069,7 +2069,7 @@ fn diff_shows_unsafe_fixes_with_opt_in() {
.args(["--select", "RUF901,RUF902", "--diff", "--unsafe-fixes"]) .args(["--select", "RUF901,RUF902", "--diff", "--unsafe-fixes"])
.build(); .build();
assert_cmd_snapshot!(cmd, assert_cmd_snapshot!(cmd,
@" @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -2091,7 +2091,7 @@ fn diff_does_not_show_display_only_fixes_with_unsafe_fixes_enabled() {
.build(); .build();
assert_cmd_snapshot!(cmd assert_cmd_snapshot!(cmd
.pass_stdin("def add_to_list(item, some_list=[]): ..."), .pass_stdin("def add_to_list(item, some_list=[]): ..."),
@" @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -2106,7 +2106,7 @@ fn diff_only_unsafe_fixes_available() {
.args(["--select", "RUF902", "--diff"]) .args(["--select", "RUF902", "--diff"])
.build(); .build();
assert_cmd_snapshot!(cmd, assert_cmd_snapshot!(cmd,
@" @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -2134,7 +2134,7 @@ extend-unsafe-fixes = ["RUF901"]
.args(["--select", "RUF901,RUF902"]) .args(["--select", "RUF901,RUF902"])
.build(); .build();
assert_cmd_snapshot!(cmd, assert_cmd_snapshot!(cmd,
@" @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -2170,7 +2170,7 @@ extend-safe-fixes = ["RUF902"]
.args(["--select", "RUF901,RUF902"]) .args(["--select", "RUF901,RUF902"])
.build(); .build();
assert_cmd_snapshot!(cmd, assert_cmd_snapshot!(cmd,
@" @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -2208,7 +2208,7 @@ extend-safe-fixes = ["RUF902"]
.args(["--select", "RUF901,RUF902"]) .args(["--select", "RUF901,RUF902"])
.build(); .build();
assert_cmd_snapshot!(cmd, assert_cmd_snapshot!(cmd,
@" @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -2248,7 +2248,7 @@ extend-safe-fixes = ["RUF9"]
.build(); .build();
assert_cmd_snapshot!(cmd assert_cmd_snapshot!(cmd
.pass_stdin("x = {'a': 1, 'a': 1}\nprint(('foo'))\nprint(str('foo'))\nisinstance(x, (int, str))\n"), .pass_stdin("x = {'a': 1, 'a': 1}\nprint(('foo'))\nprint(str('foo'))\nisinstance(x, (int, str))\n"),
@" @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -2307,7 +2307,7 @@ def log(x, base) -> float:
.args(["--select", "D41"]) .args(["--select", "D41"])
.build(); .build();
assert_cmd_snapshot!(cmd assert_cmd_snapshot!(cmd
.pass_stdin(stdin), @" .pass_stdin(stdin), @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -2360,7 +2360,7 @@ select = ["RUF017"]
let mut cmd = RuffCheck::default().config(&ruff_toml).build(); let mut cmd = RuffCheck::default().config(&ruff_toml).build();
assert_cmd_snapshot!(cmd assert_cmd_snapshot!(cmd
.pass_stdin("x = [1, 2, 3]\ny = [4, 5, 6]\nsum([x, y], [])"), .pass_stdin("x = [1, 2, 3]\ny = [4, 5, 6]\nsum([x, y], [])"),
@" @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -2401,7 +2401,7 @@ unfixable = ["RUF"]
let mut cmd = RuffCheck::default().config(&ruff_toml).build(); let mut cmd = RuffCheck::default().config(&ruff_toml).build();
assert_cmd_snapshot!(cmd assert_cmd_snapshot!(cmd
.pass_stdin("x = [1, 2, 3]\ny = [4, 5, 6]\nsum([x, y], [])"), .pass_stdin("x = [1, 2, 3]\ny = [4, 5, 6]\nsum([x, y], [])"),
@" @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -2431,7 +2431,7 @@ fn pyproject_toml_stdin_syntax_error() {
assert_cmd_snapshot!( assert_cmd_snapshot!(
cmd.pass_stdin("[project"), cmd.pass_stdin("[project"),
@" @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -2457,7 +2457,7 @@ fn pyproject_toml_stdin_schema_error() {
assert_cmd_snapshot!( assert_cmd_snapshot!(
cmd.pass_stdin("[project]\nname = 1"), cmd.pass_stdin("[project]\nname = 1"),
@" @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -2484,7 +2484,7 @@ fn pyproject_toml_stdin_no_applicable_rules_selected() {
assert_cmd_snapshot!( assert_cmd_snapshot!(
cmd.pass_stdin("[project"), cmd.pass_stdin("[project"),
@" @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -2503,7 +2503,7 @@ fn pyproject_toml_stdin_no_applicable_rules_selected_2() {
assert_cmd_snapshot!( assert_cmd_snapshot!(
cmd.pass_stdin("[project"), cmd.pass_stdin("[project"),
@" @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -2522,7 +2522,7 @@ fn pyproject_toml_stdin_no_errors() {
assert_cmd_snapshot!( assert_cmd_snapshot!(
cmd.pass_stdin(r#"[project]\nname = "ruff"\nversion = "0.0.0""#), cmd.pass_stdin(r#"[project]\nname = "ruff"\nversion = "0.0.0""#),
@" @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -2547,7 +2547,7 @@ fn pyproject_toml_stdin_schema_error_fix() {
assert_cmd_snapshot!( assert_cmd_snapshot!(
cmd.pass_stdin("[project]\nname = 1"), cmd.pass_stdin("[project]\nname = 1"),
@" @r"
success: false success: false
exit_code: 1 exit_code: 1
----- stdout ----- ----- stdout -----
@@ -2581,7 +2581,7 @@ fn pyproject_toml_stdin_schema_error_fix_only() {
assert_cmd_snapshot!( assert_cmd_snapshot!(
cmd.pass_stdin("[project]\nname = 1"), cmd.pass_stdin("[project]\nname = 1"),
@" @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -2607,7 +2607,7 @@ fn pyproject_toml_stdin_schema_error_fix_diff() {
assert_cmd_snapshot!( assert_cmd_snapshot!(
cmd.pass_stdin("[project]\nname = 1"), cmd.pass_stdin("[project]\nname = 1"),
@" @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----

View File

@@ -29,7 +29,7 @@ fn check_project_include_defaults() {
filters => TEST_FILTERS.to_vec() filters => TEST_FILTERS.to_vec()
}, { }, {
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
.args(["check", "--show-files"]).current_dir(Path::new("./resources/test/fixtures/include-test")), @" .args(["check", "--show-files"]).current_dir(Path::new("./resources/test/fixtures/include-test")), @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -53,7 +53,7 @@ fn check_project_respects_direct_paths() {
filters => TEST_FILTERS.to_vec() filters => TEST_FILTERS.to_vec()
}, { }, {
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
.args(["check", "--show-files", "b.py"]).current_dir(Path::new("./resources/test/fixtures/include-test")), @" .args(["check", "--show-files", "b.py"]).current_dir(Path::new("./resources/test/fixtures/include-test")), @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -72,7 +72,7 @@ fn check_project_respects_subdirectory_includes() {
filters => TEST_FILTERS.to_vec() filters => TEST_FILTERS.to_vec()
}, { }, {
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
.args(["check", "--show-files", "subdirectory"]).current_dir(Path::new("./resources/test/fixtures/include-test")), @" .args(["check", "--show-files", "subdirectory"]).current_dir(Path::new("./resources/test/fixtures/include-test")), @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -91,7 +91,7 @@ fn check_project_from_project_subdirectory_respects_includes() {
filters => TEST_FILTERS.to_vec() filters => TEST_FILTERS.to_vec()
}, { }, {
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)) assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
.args(["check", "--show-files"]).current_dir(Path::new("./resources/test/fixtures/include-test/subdirectory")), @" .args(["check", "--show-files"]).current_dir(Path::new("./resources/test/fixtures/include-test/subdirectory")), @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----

View File

@@ -50,56 +50,6 @@ ignore = [
Ok(()) Ok(())
} }
#[test]
fn display_settings_from_nested_directory() -> anyhow::Result<()> {
let tempdir = TempDir::new().context("Failed to create temp directory.")?;
// Tempdir path's on macos are symlinks, which doesn't play nicely with
// our snapshot filtering.
let project_dir =
dunce::canonicalize(tempdir.path()).context("Failed to canonical tempdir path.")?;
// Root pyproject.toml.
std::fs::write(
project_dir.join("pyproject.toml"),
r#"
[tool.ruff]
line-length = 100
[tool.ruff.lint]
select = ["E", "F"]
"#,
)?;
// Create a subdirectory with its own pyproject.toml.
let subdir = project_dir.join("subdir");
std::fs::create_dir(&subdir)?;
std::fs::write(
subdir.join("pyproject.toml"),
r#"
[tool.ruff]
line-length = 120
[tool.ruff.lint]
select = ["E", "F", "I"]
"#,
)?;
std::fs::write(subdir.join("test.py"), r#"import os"#).context("Failed to write test.py.")?;
insta::with_settings!({filters => vec![
(&*tempdir_filter(&project_dir), "<temp_dir>/"),
(r#"\\(\w\w|\s|\.|")"#, "/$1"),
]}, {
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
.args(["check", "--show-settings", "subdir/test.py"])
.current_dir(&project_dir));
});
Ok(())
}
fn tempdir_filter(project_dir: &Path) -> String { fn tempdir_filter(project_dir: &Path) -> String {
format!(r#"{}\\?/?"#, regex::escape(project_dir.to_str().unwrap())) format!(r#"{}\\?/?"#, regex::escape(project_dir.to_str().unwrap()))
} }

View File

@@ -3,12 +3,11 @@ source: crates/ruff/tests/integration_test.rs
info: info:
program: ruff program: ruff
args: args:
- check - "-"
- "--isolated"
- "--no-cache"
- "--output-format" - "--output-format"
- json - json
- "--no-cache"
- "--isolated"
- "-"
- "--stdin-filename" - "--stdin-filename"
- F401.py - F401.py
stdin: "import os\n" stdin: "import os\n"
@@ -52,3 +51,4 @@ exit_code: 1
} }
] ]
----- stderr ----- ----- stderr -----

View File

@@ -238,7 +238,7 @@ linter.flake8_copyright.notice_rgx = (?i)Copyright\s+((?:\(C\)|©)\s+)?\d{4}((-|
linter.flake8_copyright.author = none linter.flake8_copyright.author = none
linter.flake8_copyright.min_file_size = 0 linter.flake8_copyright.min_file_size = 0
linter.flake8_errmsg.max_string_length = 0 linter.flake8_errmsg.max_string_length = 0
linter.flake8_gettext.function_names = [ linter.flake8_gettext.functions_names = [
_, _,
gettext, gettext,
ngettext, ngettext,
@@ -374,7 +374,6 @@ linter.pylint.max_locals = 15
linter.pylint.max_nested_blocks = 5 linter.pylint.max_nested_blocks = 5
linter.pyupgrade.keep_runtime_typing = false linter.pyupgrade.keep_runtime_typing = false
linter.ruff.parenthesize_tuple_in_subscript = false linter.ruff.parenthesize_tuple_in_subscript = false
linter.ruff.strictly_empty_init_modules = false
# Formatter Settings # Formatter Settings
formatter.exclude = [] formatter.exclude = []

View File

@@ -1,410 +0,0 @@
---
source: crates/ruff/tests/show_settings.rs
info:
program: ruff
args:
- check
- "--show-settings"
- subdir/test.py
---
success: true
exit_code: 0
----- stdout -----
Resolved settings for: "<temp_dir>/subdir/test.py"
Settings path: "<temp_dir>/subdir/pyproject.toml"
# General Settings
cache_dir = "<temp_dir>/subdir/.ruff_cache"
fix = false
fix_only = false
output_format = full
show_fixes = false
unsafe_fixes = hint
# File Resolver Settings
file_resolver.exclude = [
".bzr",
".direnv",
".eggs",
".git",
".git-rewrite",
".hg",
".ipynb_checkpoints",
".mypy_cache",
".nox",
".pants.d",
".pyenv",
".pytest_cache",
".pytype",
".ruff_cache",
".svn",
".tox",
".venv",
".vscode",
"__pypackages__",
"_build",
"buck-out",
"dist",
"node_modules",
"site-packages",
"venv",
]
file_resolver.extend_exclude = []
file_resolver.force_exclude = false
file_resolver.include = [
"*.py",
"*.pyi",
"*.ipynb",
"**/pyproject.toml",
]
file_resolver.extend_include = []
file_resolver.respect_gitignore = true
file_resolver.project_root = "<temp_dir>/subdir"
# Linter Settings
linter.exclude = []
linter.project_root = "<temp_dir>/subdir"
linter.rules.enabled = [
unsorted-imports (I001),
missing-required-import (I002),
mixed-spaces-and-tabs (E101),
multiple-imports-on-one-line (E401),
module-import-not-at-top-of-file (E402),
line-too-long (E501),
multiple-statements-on-one-line-colon (E701),
multiple-statements-on-one-line-semicolon (E702),
useless-semicolon (E703),
none-comparison (E711),
true-false-comparison (E712),
not-in-test (E713),
not-is-test (E714),
type-comparison (E721),
bare-except (E722),
lambda-assignment (E731),
ambiguous-variable-name (E741),
ambiguous-class-name (E742),
ambiguous-function-name (E743),
io-error (E902),
unused-import (F401),
import-shadowed-by-loop-var (F402),
undefined-local-with-import-star (F403),
late-future-import (F404),
undefined-local-with-import-star-usage (F405),
undefined-local-with-nested-import-star-usage (F406),
future-feature-not-defined (F407),
percent-format-invalid-format (F501),
percent-format-expected-mapping (F502),
percent-format-expected-sequence (F503),
percent-format-extra-named-arguments (F504),
percent-format-missing-argument (F505),
percent-format-mixed-positional-and-named (F506),
percent-format-positional-count-mismatch (F507),
percent-format-star-requires-sequence (F508),
percent-format-unsupported-format-character (F509),
string-dot-format-invalid-format (F521),
string-dot-format-extra-named-arguments (F522),
string-dot-format-extra-positional-arguments (F523),
string-dot-format-missing-arguments (F524),
string-dot-format-mixing-automatic (F525),
f-string-missing-placeholders (F541),
multi-value-repeated-key-literal (F601),
multi-value-repeated-key-variable (F602),
expressions-in-star-assignment (F621),
multiple-starred-expressions (F622),
assert-tuple (F631),
is-literal (F632),
invalid-print-syntax (F633),
if-tuple (F634),
break-outside-loop (F701),
continue-outside-loop (F702),
yield-outside-function (F704),
return-outside-function (F706),
default-except-not-last (F707),
forward-annotation-syntax-error (F722),
redefined-while-unused (F811),
undefined-name (F821),
undefined-export (F822),
undefined-local (F823),
unused-variable (F841),
unused-annotation (F842),
raise-not-implemented (F901),
]
linter.rules.should_fix = [
unsorted-imports (I001),
missing-required-import (I002),
mixed-spaces-and-tabs (E101),
multiple-imports-on-one-line (E401),
module-import-not-at-top-of-file (E402),
line-too-long (E501),
multiple-statements-on-one-line-colon (E701),
multiple-statements-on-one-line-semicolon (E702),
useless-semicolon (E703),
none-comparison (E711),
true-false-comparison (E712),
not-in-test (E713),
not-is-test (E714),
type-comparison (E721),
bare-except (E722),
lambda-assignment (E731),
ambiguous-variable-name (E741),
ambiguous-class-name (E742),
ambiguous-function-name (E743),
io-error (E902),
unused-import (F401),
import-shadowed-by-loop-var (F402),
undefined-local-with-import-star (F403),
late-future-import (F404),
undefined-local-with-import-star-usage (F405),
undefined-local-with-nested-import-star-usage (F406),
future-feature-not-defined (F407),
percent-format-invalid-format (F501),
percent-format-expected-mapping (F502),
percent-format-expected-sequence (F503),
percent-format-extra-named-arguments (F504),
percent-format-missing-argument (F505),
percent-format-mixed-positional-and-named (F506),
percent-format-positional-count-mismatch (F507),
percent-format-star-requires-sequence (F508),
percent-format-unsupported-format-character (F509),
string-dot-format-invalid-format (F521),
string-dot-format-extra-named-arguments (F522),
string-dot-format-extra-positional-arguments (F523),
string-dot-format-missing-arguments (F524),
string-dot-format-mixing-automatic (F525),
f-string-missing-placeholders (F541),
multi-value-repeated-key-literal (F601),
multi-value-repeated-key-variable (F602),
expressions-in-star-assignment (F621),
multiple-starred-expressions (F622),
assert-tuple (F631),
is-literal (F632),
invalid-print-syntax (F633),
if-tuple (F634),
break-outside-loop (F701),
continue-outside-loop (F702),
yield-outside-function (F704),
return-outside-function (F706),
default-except-not-last (F707),
forward-annotation-syntax-error (F722),
redefined-while-unused (F811),
undefined-name (F821),
undefined-export (F822),
undefined-local (F823),
unused-variable (F841),
unused-annotation (F842),
raise-not-implemented (F901),
]
linter.per_file_ignores = {}
linter.safety_table.forced_safe = []
linter.safety_table.forced_unsafe = []
linter.unresolved_target_version = none
linter.per_file_target_version = {}
linter.preview = disabled
linter.explicit_preview_rules = false
linter.extension = ExtensionMapping({})
linter.allowed_confusables = []
linter.builtins = []
linter.dummy_variable_rgx = ^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$
linter.external = []
linter.ignore_init_module_imports = true
linter.logger_objects = []
linter.namespace_packages = []
linter.src = [
"<temp_dir>/subdir",
"<temp_dir>/subdir/src",
]
linter.tab_size = 4
linter.line_length = 120
linter.task_tags = [
TODO,
FIXME,
XXX,
]
linter.typing_modules = []
linter.typing_extensions = true
# Linter Plugins
linter.flake8_annotations.mypy_init_return = false
linter.flake8_annotations.suppress_dummy_args = false
linter.flake8_annotations.suppress_none_returning = false
linter.flake8_annotations.allow_star_arg_any = false
linter.flake8_annotations.ignore_fully_untyped = false
linter.flake8_bandit.hardcoded_tmp_directory = [
/tmp,
/var/tmp,
/dev/shm,
]
linter.flake8_bandit.check_typed_exception = false
linter.flake8_bandit.extend_markup_names = []
linter.flake8_bandit.allowed_markup_calls = []
linter.flake8_bugbear.extend_immutable_calls = []
linter.flake8_builtins.allowed_modules = []
linter.flake8_builtins.ignorelist = []
linter.flake8_builtins.strict_checking = false
linter.flake8_comprehensions.allow_dict_calls_with_keyword_arguments = false
linter.flake8_copyright.notice_rgx = (?i)Copyright\s+((?:\(C\)|©)\s+)?\d{4}((-|,\s)\d{4})*
linter.flake8_copyright.author = none
linter.flake8_copyright.min_file_size = 0
linter.flake8_errmsg.max_string_length = 0
linter.flake8_gettext.function_names = [
_,
gettext,
ngettext,
]
linter.flake8_implicit_str_concat.allow_multiline = true
linter.flake8_import_conventions.aliases = {
altair = alt,
holoviews = hv,
matplotlib = mpl,
matplotlib.pyplot = plt,
networkx = nx,
numpy = np,
numpy.typing = npt,
pandas = pd,
panel = pn,
plotly.express = px,
polars = pl,
pyarrow = pa,
seaborn = sns,
tensorflow = tf,
tkinter = tk,
xml.etree.ElementTree = ET,
}
linter.flake8_import_conventions.banned_aliases = {}
linter.flake8_import_conventions.banned_from = []
linter.flake8_pytest_style.fixture_parentheses = false
linter.flake8_pytest_style.parametrize_names_type = tuple
linter.flake8_pytest_style.parametrize_values_type = list
linter.flake8_pytest_style.parametrize_values_row_type = tuple
linter.flake8_pytest_style.raises_require_match_for = [
BaseException,
Exception,
ValueError,
OSError,
IOError,
EnvironmentError,
socket.error,
]
linter.flake8_pytest_style.raises_extend_require_match_for = []
linter.flake8_pytest_style.mark_parentheses = false
linter.flake8_quotes.inline_quotes = double
linter.flake8_quotes.multiline_quotes = double
linter.flake8_quotes.docstring_quotes = double
linter.flake8_quotes.avoid_escape = true
linter.flake8_self.ignore_names = [
_make,
_asdict,
_replace,
_fields,
_field_defaults,
_name_,
_value_,
]
linter.flake8_tidy_imports.ban_relative_imports = "parents"
linter.flake8_tidy_imports.banned_api = {}
linter.flake8_tidy_imports.banned_module_level_imports = []
linter.flake8_type_checking.strict = false
linter.flake8_type_checking.exempt_modules = [
typing,
typing_extensions,
]
linter.flake8_type_checking.runtime_required_base_classes = []
linter.flake8_type_checking.runtime_required_decorators = []
linter.flake8_type_checking.quote_annotations = false
linter.flake8_unused_arguments.ignore_variadic_names = false
linter.isort.required_imports = []
linter.isort.combine_as_imports = false
linter.isort.force_single_line = false
linter.isort.force_sort_within_sections = false
linter.isort.detect_same_package = true
linter.isort.case_sensitive = false
linter.isort.force_wrap_aliases = false
linter.isort.force_to_top = []
linter.isort.known_modules = {}
linter.isort.order_by_type = true
linter.isort.relative_imports_order = furthest_to_closest
linter.isort.single_line_exclusions = []
linter.isort.split_on_trailing_comma = true
linter.isort.classes = []
linter.isort.constants = []
linter.isort.variables = []
linter.isort.no_lines_before = []
linter.isort.lines_after_imports = -1
linter.isort.lines_between_types = 0
linter.isort.forced_separate = []
linter.isort.section_order = [
known { type = future },
known { type = standard_library },
known { type = third_party },
known { type = first_party },
known { type = local_folder },
]
linter.isort.default_section = known { type = third_party }
linter.isort.no_sections = false
linter.isort.from_first = false
linter.isort.length_sort = false
linter.isort.length_sort_straight = false
linter.mccabe.max_complexity = 10
linter.pep8_naming.ignore_names = [
setUp,
tearDown,
setUpClass,
tearDownClass,
setUpModule,
tearDownModule,
asyncSetUp,
asyncTearDown,
setUpTestData,
failureException,
longMessage,
maxDiff,
]
linter.pep8_naming.classmethod_decorators = []
linter.pep8_naming.staticmethod_decorators = []
linter.pycodestyle.max_line_length = 120
linter.pycodestyle.max_doc_length = none
linter.pycodestyle.ignore_overlong_task_comments = false
linter.pyflakes.extend_generics = []
linter.pyflakes.allowed_unused_imports = []
linter.pylint.allow_magic_value_types = [
str,
bytes,
]
linter.pylint.allow_dunder_method_names = []
linter.pylint.max_args = 5
linter.pylint.max_positional_args = 5
linter.pylint.max_returns = 6
linter.pylint.max_bool_expr = 5
linter.pylint.max_branches = 12
linter.pylint.max_statements = 50
linter.pylint.max_public_methods = 20
linter.pylint.max_locals = 15
linter.pylint.max_nested_blocks = 5
linter.pyupgrade.keep_runtime_typing = false
linter.ruff.parenthesize_tuple_in_subscript = false
linter.ruff.strictly_empty_init_modules = false
# Formatter Settings
formatter.exclude = []
formatter.unresolved_target_version = 3.10
formatter.per_file_target_version = {}
formatter.preview = disabled
formatter.line_width = 120
formatter.line_ending = auto
formatter.indent_style = space
formatter.indent_width = 4
formatter.quote_style = double
formatter.magic_trailing_comma = respect
formatter.docstring_code_format = disabled
formatter.docstring_code_line_width = dynamic
# Analyze Settings
analyze.exclude = []
analyze.preview = disabled
analyze.target_version = 3.10
analyze.string_imports = disabled
analyze.extension = ExtensionMapping({})
analyze.include_dependencies = {}
analyze.type_checking_imports = true
----- stderr -----

View File

@@ -16,7 +16,7 @@ const VERSION_FILTER: [(&str, &str); 1] = [(
fn version_basics() { fn version_basics() {
insta::with_settings!({filters => VERSION_FILTER.to_vec()}, { insta::with_settings!({filters => VERSION_FILTER.to_vec()}, {
assert_cmd_snapshot!( assert_cmd_snapshot!(
Command::new(get_cargo_bin(BIN_NAME)).arg("version"), @" Command::new(get_cargo_bin(BIN_NAME)).arg("version"), @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -42,7 +42,7 @@ fn config_option_allowed_but_ignored() -> Result<()> {
.arg("version") .arg("version")
.arg("--config") .arg("--config")
.arg(&ruff_dot_toml) .arg(&ruff_dot_toml)
.args(["--config", "lint.isort.extra-standard-library = ['foo', 'bar']"]), @" .args(["--config", "lint.isort.extra-standard-library = ['foo', 'bar']"]), @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----
@@ -60,7 +60,7 @@ fn config_option_ignored_but_validated() {
assert_cmd_snapshot!( assert_cmd_snapshot!(
Command::new(get_cargo_bin(BIN_NAME)) Command::new(get_cargo_bin(BIN_NAME))
.arg("version") .arg("version")
.args(["--config", "foo = bar"]), @" .args(["--config", "foo = bar"]), @r"
success: false success: false
exit_code: 2 exit_code: 2
----- stdout ----- ----- stdout -----
@@ -91,7 +91,7 @@ fn config_option_ignored_but_validated() {
fn isolated_option_allowed() { fn isolated_option_allowed() {
insta::with_settings!({filters => VERSION_FILTER.to_vec()}, { insta::with_settings!({filters => VERSION_FILTER.to_vec()}, {
assert_cmd_snapshot!( assert_cmd_snapshot!(
Command::new(get_cargo_bin(BIN_NAME)).arg("version").arg("--isolated"), @" Command::new(get_cargo_bin(BIN_NAME)).arg("version").arg("--isolated"), @r"
success: true success: true
exit_code: 0 exit_code: 0
----- stdout ----- ----- stdout -----

View File

@@ -12,6 +12,10 @@ license = "MIT OR Apache-2.0"
[lib] [lib]
[features]
default = []
testing-colors = []
[dependencies] [dependencies]
anstyle = { workspace = true } anstyle = { workspace = true }
memchr = { workspace = true } memchr = { workspace = true }
@@ -19,17 +23,12 @@ unicode-width = { workspace = true }
[dev-dependencies] [dev-dependencies]
ruff_annotate_snippets = { workspace = true, features = ["testing-colors"] } ruff_annotate_snippets = { workspace = true, features = ["testing-colors"] }
anstream = { workspace = true } anstream = { workspace = true }
serde = { workspace = true, features = ["derive"] } serde = { workspace = true, features = ["derive"] }
snapbox = { workspace = true, features = ["diff", "term-svg", "cmd", "examples"] } snapbox = { workspace = true, features = ["diff", "term-svg", "cmd", "examples"] }
toml = { workspace = true } toml = { workspace = true }
tryfn = { workspace = true } tryfn = { workspace = true }
[features]
default = []
testing-colors = []
[[test]] [[test]]
name = "fixtures" name = "fixtures"
harness = false harness = false

View File

@@ -16,80 +16,77 @@ bench = false
test = false test = false
doctest = false doctest = false
[[bench]]
name = "linter"
harness = false
required-features = ["instrumented"]
[[bench]]
name = "lexer"
harness = false
required-features = ["instrumented"]
[[bench]]
name = "parser"
harness = false
required-features = ["instrumented"]
[[bench]]
name = "formatter"
harness = false
required-features = ["instrumented"]
[[bench]]
name = "ty"
harness = false
required-features = ["instrumented"]
[[bench]]
name = "ty_walltime"
harness = false
required-features = ["walltime"]
[dependencies] [dependencies]
ruff_db = { workspace = true, features = ["testing"] } ruff_db = { workspace = true, features = ["testing"] }
ruff_linter = { workspace = true, optional = true }
ruff_python_ast = { workspace = true } ruff_python_ast = { workspace = true }
ruff_linter = { workspace = true, optional = true }
ruff_python_formatter = { workspace = true, optional = true } ruff_python_formatter = { workspace = true, optional = true }
ruff_python_parser = { workspace = true, optional = true } ruff_python_parser = { workspace = true, optional = true }
ruff_python_trivia = { workspace = true, optional = true } ruff_python_trivia = { workspace = true, optional = true }
ty_project = { workspace = true, optional = true } ty_project = { workspace = true, optional = true }
divan = { workspace = true, optional = true }
anyhow = { workspace = true } anyhow = { workspace = true }
codspeed-criterion-compat = { workspace = true, default-features = false, optional = true } codspeed-criterion-compat = { workspace = true, default-features = false, optional = true }
criterion = { workspace = true, default-features = false, optional = true } criterion = { workspace = true, default-features = false, optional = true }
divan = { workspace = true, optional = true }
serde = { workspace = true } serde = { workspace = true }
serde_json = { workspace = true } serde_json = { workspace = true }
tracing = { workspace = true } tracing = { workspace = true }
[target.'cfg(all(not(target_os = "windows"), not(target_os = "openbsd"), any(target_arch = "x86_64", target_arch = "aarch64", target_arch = "powerpc64", target_arch = "riscv64")))'.dependencies] [lints]
tikv-jemallocator = { workspace = true, optional = true } workspace = true
[target.'cfg(target_os = "windows")'.dependencies]
mimalloc = { workspace = true, optional = true }
[dev-dependencies]
rayon = { workspace = true }
rustc-hash = { workspace = true }
[features] [features]
default = ["ty_instrumented", "ty_walltime", "ruff_instrumented"] default = ["instrumented", "walltime"]
# Enables the ruff instrumented benchmarks # Enables the benchmark that should only run with codspeed's instrumented runner
ruff_instrumented = [ instrumented = [
"criterion", "criterion",
"ruff_linter", "ruff_linter",
"ruff_python_formatter", "ruff_python_formatter",
"ruff_python_parser", "ruff_python_parser",
"ruff_python_trivia", "ruff_python_trivia",
"mimalloc", "ty_project",
"tikv-jemallocator",
] ]
# Enables the ty instrumented benchmarks
ty_instrumented = ["criterion", "ty_project", "ruff_python_trivia"]
codspeed = ["codspeed-criterion-compat"] codspeed = ["codspeed-criterion-compat"]
# Enables the ty_walltime benchmarks # Enables benchmark that should only run with codspeed's walltime runner.
ty_walltime = ["ruff_db/os", "ty_project", "divan"] walltime = ["ruff_db/os", "ty_project", "divan"]
[[bench]] [target.'cfg(target_os = "windows")'.dev-dependencies]
name = "linter" mimalloc = { workspace = true }
harness = false
required-features = ["ruff_instrumented"]
[[bench]] [target.'cfg(all(not(target_os = "windows"), not(target_os = "openbsd"), any(target_arch = "x86_64", target_arch = "aarch64", target_arch = "powerpc64", target_arch = "riscv64")))'.dev-dependencies]
name = "lexer" tikv-jemallocator = { workspace = true }
harness = false
required-features = ["ruff_instrumented"]
[[bench]] [dev-dependencies]
name = "parser" rustc-hash = { workspace = true }
harness = false rayon = { workspace = true }
required-features = ["ruff_instrumented"]
[[bench]]
name = "formatter"
harness = false
required-features = ["ruff_instrumented"]
[[bench]]
name = "ty"
harness = false
required-features = ["ty_instrumented"]
[[bench]]
name = "ty_walltime"
harness = false
required-features = ["ty_walltime"]
[lints]
workspace = true

View File

@@ -15,7 +15,7 @@ use ruff_db::files::{File, system_path_to_file};
use ruff_db::source::source_text; use ruff_db::source::source_text;
use ruff_db::system::{InMemorySystem, MemoryFileSystem, SystemPath, SystemPathBuf, TestSystem}; use ruff_db::system::{InMemorySystem, MemoryFileSystem, SystemPath, SystemPathBuf, TestSystem};
use ruff_python_ast::PythonVersion; use ruff_python_ast::PythonVersion;
use ty_project::metadata::options::{AnalysisOptions, EnvironmentOptions, Options}; use ty_project::metadata::options::{EnvironmentOptions, Options};
use ty_project::metadata::value::{RangedValue, RelativePathBuf}; use ty_project::metadata::value::{RangedValue, RelativePathBuf};
use ty_project::watch::{ChangeEvent, ChangedKind}; use ty_project::watch::{ChangeEvent, ChangedKind};
use ty_project::{CheckMode, Db, ProjectDatabase, ProjectMetadata}; use ty_project::{CheckMode, Db, ProjectDatabase, ProjectMetadata};
@@ -67,7 +67,6 @@ fn tomllib_path(file: &TestFile) -> SystemPathBuf {
SystemPathBuf::from("src").join(file.name()) SystemPathBuf::from("src").join(file.name())
} }
#[expect(clippy::needless_update)]
fn setup_tomllib_case() -> Case { fn setup_tomllib_case() -> Case {
let system = TestSystem::default(); let system = TestSystem::default();
let fs = system.memory_file_system().clone(); let fs = system.memory_file_system().clone();
@@ -86,10 +85,6 @@ fn setup_tomllib_case() -> Case {
python_version: Some(RangedValue::cli(PythonVersion::PY312)), python_version: Some(RangedValue::cli(PythonVersion::PY312)),
..EnvironmentOptions::default() ..EnvironmentOptions::default()
}), }),
analysis: Some(AnalysisOptions {
respect_type_ignore_comments: Some(false),
..AnalysisOptions::default()
}),
..Options::default() ..Options::default()
}); });
@@ -226,7 +221,7 @@ fn setup_micro_case(code: &str) -> Case {
let file_path = "src/test.py"; let file_path = "src/test.py";
fs.write_file_all( fs.write_file_all(
SystemPathBuf::from(file_path), SystemPathBuf::from(file_path),
&*ruff_python_trivia::textwrap::dedent(code), ruff_python_trivia::textwrap::dedent(code),
) )
.unwrap(); .unwrap();
@@ -562,60 +557,6 @@ fn benchmark_many_enum_members(criterion: &mut Criterion) {
}); });
} }
fn benchmark_many_enum_members_2(criterion: &mut Criterion) {
const NUM_ENUM_MEMBERS: usize = 48;
setup_rayon();
let mut code = "\
from enum import Enum
from typing_extensions import assert_never
class E(Enum):
"
.to_string();
for i in 0..NUM_ENUM_MEMBERS {
writeln!(&mut code, " m{i} = {i}").ok();
}
code.push_str(
"
def method(self):
match self:",
);
for i in 0..NUM_ENUM_MEMBERS {
write!(
&mut code,
"
case E.m{i}:
pass"
)
.ok();
}
write!(
&mut code,
"
case _:
assert_never(self)"
)
.ok();
criterion.bench_function("ty_micro[many_enum_members_2]", |b| {
b.iter_batched_ref(
|| setup_micro_case(&code),
|case| {
let Case { db, .. } = case;
let result = db.check();
assert_eq!(result.len(), 0);
},
BatchSize::SmallInput,
);
});
}
struct ProjectBenchmark<'a> { struct ProjectBenchmark<'a> {
project: InstalledProject<'a>, project: InstalledProject<'a>,
fs: MemoryFileSystem, fs: MemoryFileSystem,
@@ -760,7 +701,7 @@ fn datetype(criterion: &mut Criterion) {
max_dep_date: "2025-07-04", max_dep_date: "2025-07-04",
python_version: PythonVersion::PY313, python_version: PythonVersion::PY313,
}, },
4, 2,
); );
bench_project(&benchmark, criterion); bench_project(&benchmark, criterion);
@@ -776,7 +717,6 @@ criterion_group!(
benchmark_complex_constrained_attributes_2, benchmark_complex_constrained_attributes_2,
benchmark_complex_constrained_attributes_3, benchmark_complex_constrained_attributes_3,
benchmark_many_enum_members, benchmark_many_enum_members,
benchmark_many_enum_members_2,
); );
criterion_group!(project, anyio, attrs, hydra, datetype); criterion_group!(project, anyio, attrs, hydra, datetype);
criterion_main!(check_file, micro, project); criterion_main!(check_file, micro, project);

View File

@@ -71,8 +71,6 @@ impl Display for Benchmark<'_> {
} }
} }
#[track_caller]
#[expect(clippy::cast_precision_loss)]
fn check_project(db: &ProjectDatabase, project_name: &str, max_diagnostics: usize) { fn check_project(db: &ProjectDatabase, project_name: &str, max_diagnostics: usize) {
let result = db.check(); let result = db.check();
let diagnostics = result.len(); let diagnostics = result.len();
@@ -81,12 +79,6 @@ fn check_project(db: &ProjectDatabase, project_name: &str, max_diagnostics: usiz
diagnostics > 1 && diagnostics <= max_diagnostics, diagnostics > 1 && diagnostics <= max_diagnostics,
"Expected between 1 and {max_diagnostics} diagnostics on project '{project_name}' but got {diagnostics}", "Expected between 1 and {max_diagnostics} diagnostics on project '{project_name}' but got {diagnostics}",
); );
if (max_diagnostics - diagnostics) as f64 / max_diagnostics as f64 > 0.10 {
tracing::warn!(
"The expected diagnostics for project `{project_name}` can be reduced: expected {max_diagnostics} but got {diagnostics}"
);
}
} }
static ALTAIR: Benchmark = Benchmark::new( static ALTAIR: Benchmark = Benchmark::new(
@@ -109,7 +101,7 @@ static ALTAIR: Benchmark = Benchmark::new(
max_dep_date: "2025-06-17", max_dep_date: "2025-06-17",
python_version: PythonVersion::PY312, python_version: PythonVersion::PY312,
}, },
850, 1000,
); );
static COLOUR_SCIENCE: Benchmark = Benchmark::new( static COLOUR_SCIENCE: Benchmark = Benchmark::new(
@@ -128,7 +120,7 @@ static COLOUR_SCIENCE: Benchmark = Benchmark::new(
max_dep_date: "2025-06-17", max_dep_date: "2025-06-17",
python_version: PythonVersion::PY310, python_version: PythonVersion::PY310,
}, },
350, 1070,
); );
static FREQTRADE: Benchmark = Benchmark::new( static FREQTRADE: Benchmark = Benchmark::new(
@@ -171,7 +163,7 @@ static PANDAS: Benchmark = Benchmark::new(
max_dep_date: "2025-06-17", max_dep_date: "2025-06-17",
python_version: PythonVersion::PY312, python_version: PythonVersion::PY312,
}, },
3800, 4000,
); );
static PYDANTIC: Benchmark = Benchmark::new( static PYDANTIC: Benchmark = Benchmark::new(
@@ -189,7 +181,7 @@ static PYDANTIC: Benchmark = Benchmark::new(
max_dep_date: "2025-06-17", max_dep_date: "2025-06-17",
python_version: PythonVersion::PY39, python_version: PythonVersion::PY39,
}, },
3200, 7000,
); );
static SYMPY: Benchmark = Benchmark::new( static SYMPY: Benchmark = Benchmark::new(
@@ -202,7 +194,7 @@ static SYMPY: Benchmark = Benchmark::new(
max_dep_date: "2025-06-17", max_dep_date: "2025-06-17",
python_version: PythonVersion::PY312, python_version: PythonVersion::PY312,
}, },
13400, 13000,
); );
static TANJUN: Benchmark = Benchmark::new( static TANJUN: Benchmark = Benchmark::new(
@@ -215,7 +207,7 @@ static TANJUN: Benchmark = Benchmark::new(
max_dep_date: "2025-06-17", max_dep_date: "2025-06-17",
python_version: PythonVersion::PY312, python_version: PythonVersion::PY312,
}, },
110, 320,
); );
static STATIC_FRAME: Benchmark = Benchmark::new( static STATIC_FRAME: Benchmark = Benchmark::new(
@@ -231,7 +223,7 @@ static STATIC_FRAME: Benchmark = Benchmark::new(
max_dep_date: "2025-08-09", max_dep_date: "2025-08-09",
python_version: PythonVersion::PY311, python_version: PythonVersion::PY311,
}, },
1700, 950,
); );
#[track_caller] #[track_caller]
@@ -243,55 +235,30 @@ fn run_single_threaded(bencher: Bencher, benchmark: &Benchmark) {
}); });
} }
#[bench(sample_size = 2, sample_count = 3)] #[bench(args=[&ALTAIR, &FREQTRADE, &TANJUN], sample_size=2, sample_count=3)]
fn altair(bencher: Bencher) { fn small(bencher: Bencher, benchmark: &Benchmark) {
run_single_threaded(bencher, &ALTAIR); run_single_threaded(bencher, benchmark);
} }
#[bench(sample_size = 2, sample_count = 3)] #[bench(args=[&COLOUR_SCIENCE, &PANDAS, &STATIC_FRAME], sample_size=1, sample_count=3)]
fn freqtrade(bencher: Bencher) { fn medium(bencher: Bencher, benchmark: &Benchmark) {
run_single_threaded(bencher, &FREQTRADE); run_single_threaded(bencher, benchmark);
} }
#[bench(sample_size = 2, sample_count = 3)] #[bench(args=[&SYMPY, &PYDANTIC], sample_size=1, sample_count=2)]
fn tanjun(bencher: Bencher) { fn large(bencher: Bencher, benchmark: &Benchmark) {
run_single_threaded(bencher, &TANJUN); run_single_threaded(bencher, benchmark);
} }
#[bench(sample_size = 2, sample_count = 3)] #[bench(args=[&ALTAIR], sample_size=3, sample_count=8)]
fn pydantic(bencher: Bencher) { fn multithreaded(bencher: Bencher, benchmark: &Benchmark) {
run_single_threaded(bencher, &PYDANTIC);
}
#[bench(sample_size = 1, sample_count = 3)]
fn static_frame(bencher: Bencher) {
run_single_threaded(bencher, &STATIC_FRAME);
}
#[bench(sample_size = 1, sample_count = 2)]
fn colour_science(bencher: Bencher) {
run_single_threaded(bencher, &COLOUR_SCIENCE);
}
#[bench(sample_size = 1, sample_count = 2)]
fn pandas(bencher: Bencher) {
run_single_threaded(bencher, &PANDAS);
}
#[bench(sample_size = 1, sample_count = 2)]
fn sympy(bencher: Bencher) {
run_single_threaded(bencher, &SYMPY);
}
#[bench(sample_size = 3, sample_count = 8)]
fn multithreaded(bencher: Bencher) {
let thread_pool = ThreadPoolBuilder::new().build().unwrap(); let thread_pool = ThreadPoolBuilder::new().build().unwrap();
bencher bencher
.with_inputs(|| ALTAIR.setup_iteration()) .with_inputs(|| benchmark.setup_iteration())
.bench_local_values(|db| { .bench_local_values(|db| {
thread_pool.install(|| { thread_pool.install(|| {
check_project(&db, ALTAIR.project.name, ALTAIR.max_diagnostics); check_project(&db, benchmark.project.name, benchmark.max_diagnostics);
db db
}) })
}); });

View File

@@ -1,6 +1,6 @@
use std::path::PathBuf; use std::path::PathBuf;
#[cfg(any(feature = "ty_instrumented", feature = "ruff_instrumented"))] #[cfg(feature = "instrumented")]
pub mod criterion; pub mod criterion;
pub mod real_world_projects; pub mod real_world_projects;

View File

@@ -11,11 +11,11 @@ repository = { workspace = true }
license = { workspace = true } license = { workspace = true }
[dependencies] [dependencies]
filetime = { workspace = true }
glob = { workspace = true } glob = { workspace = true }
globset = { workspace = true } globset = { workspace = true }
itertools = { workspace = true } itertools = { workspace = true }
regex = { workspace = true } regex = { workspace = true }
filetime = { workspace = true }
seahash = { workspace = true } seahash = { workspace = true }
[dev-dependencies] [dev-dependencies]

View File

@@ -48,12 +48,12 @@ tracing = { workspace = true }
tracing-subscriber = { workspace = true, optional = true } tracing-subscriber = { workspace = true, optional = true }
zip = { workspace = true } zip = { workspace = true }
[target.'cfg(not(target_arch="wasm32"))'.dependencies]
etcetera = { workspace = true, optional = true }
[target.'cfg(target_arch="wasm32")'.dependencies] [target.'cfg(target_arch="wasm32")'.dependencies]
web-time = { version = "1.1.0" } web-time = { version = "1.1.0" }
[target.'cfg(not(target_arch="wasm32"))'.dependencies]
etcetera = { workspace = true, optional = true }
[dev-dependencies] [dev-dependencies]
insta = { workspace = true, features = ["filters"] } insta = { workspace = true, features = ["filters"] }
tempfile = { workspace = true } tempfile = { workspace = true }

View File

@@ -1,64 +0,0 @@
use std::fmt::Formatter;
use std::sync::Arc;
use std::sync::atomic::AtomicBool;
/// Signals a [`CancellationToken`] that it should be canceled.
#[derive(Debug, Clone)]
pub struct CancellationTokenSource {
cancelled: Arc<AtomicBool>,
}
impl Default for CancellationTokenSource {
fn default() -> Self {
Self::new()
}
}
impl CancellationTokenSource {
pub fn new() -> Self {
Self {
cancelled: Arc::new(AtomicBool::new(false)),
}
}
pub fn is_cancellation_requested(&self) -> bool {
self.cancelled.load(std::sync::atomic::Ordering::Relaxed)
}
/// Creates a new token that uses this source.
pub fn token(&self) -> CancellationToken {
CancellationToken {
cancelled: self.cancelled.clone(),
}
}
/// Requests cancellation for operations using this token.
pub fn cancel(&self) {
self.cancelled
.store(true, std::sync::atomic::Ordering::Relaxed);
}
}
/// Token signals whether an operation should be canceled.
#[derive(Debug, Clone)]
pub struct CancellationToken {
cancelled: Arc<AtomicBool>,
}
impl CancellationToken {
pub fn is_cancelled(&self) -> bool {
self.cancelled.load(std::sync::atomic::Ordering::Relaxed)
}
}
/// The operation was canceled by the provided [`CancellationToken`].
#[derive(Debug)]
pub struct Canceled;
impl std::error::Error for Canceled {}
impl std::fmt::Display for Canceled {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_str("operation was canceled")
}
}

View File

@@ -1,4 +1,4 @@
use std::{borrow::Cow, fmt::Formatter, path::Path, sync::Arc}; use std::{fmt::Formatter, path::Path, sync::Arc};
use ruff_diagnostics::{Applicability, Fix}; use ruff_diagnostics::{Applicability, Fix};
use ruff_source_file::{LineColumn, SourceCode, SourceFile}; use ruff_source_file::{LineColumn, SourceCode, SourceFile};
@@ -11,7 +11,6 @@ pub use self::render::{
ceil_char_boundary, ceil_char_boundary,
github::{DisplayGithubDiagnostics, GithubRenderer}, github::{DisplayGithubDiagnostics, GithubRenderer},
}; };
use crate::cancellation::CancellationToken;
use crate::{Db, files::File}; use crate::{Db, files::File};
mod render; mod render;
@@ -98,44 +97,6 @@ impl Diagnostic {
diag diag
} }
/// Adds sub diagnostics that tell the user that this is a bug in ty
/// and asks them to open an issue on GitHub.
pub fn add_bug_sub_diagnostics(&mut self, url_encoded_title: &str) {
self.sub(SubDiagnostic::new(
SubDiagnosticSeverity::Info,
"This indicates a bug in ty.",
));
self.sub(SubDiagnostic::new(
SubDiagnosticSeverity::Info,
format_args!(
"If you could open an issue at https://github.com/astral-sh/ty/issues/new?title={url_encoded_title}, we'd be very appreciative!"
),
));
self.sub(SubDiagnostic::new(
SubDiagnosticSeverity::Info,
format!(
"Platform: {os} {arch}",
os = std::env::consts::OS,
arch = std::env::consts::ARCH
),
));
if let Some(version) = crate::program_version() {
self.sub(SubDiagnostic::new(
SubDiagnosticSeverity::Info,
format!("Version: {version}"),
));
}
self.sub(SubDiagnostic::new(
SubDiagnosticSeverity::Info,
format!(
"Args: {args:?}",
args = std::env::args().collect::<Vec<_>>()
),
));
}
/// Add an annotation to this diagnostic. /// Add an annotation to this diagnostic.
/// ///
/// Annotations for a diagnostic are optional, but if any are added, /// Annotations for a diagnostic are optional, but if any are added,
@@ -449,6 +410,11 @@ impl Diagnostic {
self.id().is_invalid_syntax() self.id().is_invalid_syntax()
} }
/// Returns the message body to display to the user.
pub fn body(&self) -> &str {
self.primary_message()
}
/// Returns the message of the first sub-diagnostic with a `Help` severity. /// Returns the message of the first sub-diagnostic with a `Help` severity.
/// ///
/// Note that this is used as the fix title/suggestion for some of Ruff's output formats, but in /// Note that this is used as the fix title/suggestion for some of Ruff's output formats, but in
@@ -1057,13 +1023,6 @@ impl DiagnosticId {
matches!(self, DiagnosticId::Lint(_)) matches!(self, DiagnosticId::Lint(_))
} }
pub const fn as_lint(&self) -> Option<LintName> {
match self {
DiagnosticId::Lint(name) => Some(*name),
_ => None,
}
}
/// Returns `true` if this `DiagnosticId` represents a lint with the given name. /// Returns `true` if this `DiagnosticId` represents a lint with the given name.
pub fn is_lint_named(&self, name: &str) -> bool { pub fn is_lint_named(&self, name: &str) -> bool {
matches!(self, DiagnosticId::Lint(self_name) if self_name == name) matches!(self, DiagnosticId::Lint(self_name) if self_name == name)
@@ -1353,8 +1312,6 @@ pub struct DisplayDiagnosticConfig {
show_fix_diff: bool, show_fix_diff: bool,
/// The lowest applicability that should be shown when reporting diagnostics. /// The lowest applicability that should be shown when reporting diagnostics.
fix_applicability: Applicability, fix_applicability: Applicability,
cancellation_token: Option<CancellationToken>,
} }
impl DisplayDiagnosticConfig { impl DisplayDiagnosticConfig {
@@ -1428,20 +1385,6 @@ impl DisplayDiagnosticConfig {
pub fn fix_applicability(&self) -> Applicability { pub fn fix_applicability(&self) -> Applicability {
self.fix_applicability self.fix_applicability
} }
pub fn with_cancellation_token(
mut self,
token: Option<CancellationToken>,
) -> DisplayDiagnosticConfig {
self.cancellation_token = token;
self
}
pub fn is_canceled(&self) -> bool {
self.cancellation_token
.as_ref()
.is_some_and(|token| token.is_cancelled())
}
} }
impl Default for DisplayDiagnosticConfig { impl Default for DisplayDiagnosticConfig {
@@ -1455,7 +1398,6 @@ impl Default for DisplayDiagnosticConfig {
show_fix_status: false, show_fix_status: false,
show_fix_diff: false, show_fix_diff: false,
fix_applicability: Applicability::Safe, fix_applicability: Applicability::Safe,
cancellation_token: None,
} }
} }
} }
@@ -1532,15 +1474,6 @@ pub enum ConciseMessage<'a> {
Custom(&'a str), Custom(&'a str),
} }
impl<'a> ConciseMessage<'a> {
pub fn to_str(&self) -> Cow<'a, str> {
match self {
ConciseMessage::MainDiagnostic(s) | ConciseMessage::Custom(s) => Cow::Borrowed(s),
ConciseMessage::Both { .. } => Cow::Owned(self.to_string()),
}
}
}
impl std::fmt::Display for ConciseMessage<'_> { impl std::fmt::Display for ConciseMessage<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match *self { match *self {
@@ -1557,16 +1490,6 @@ impl std::fmt::Display for ConciseMessage<'_> {
} }
} }
#[cfg(feature = "serde")]
impl serde::Serialize for ConciseMessage<'_> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.collect_str(self)
}
}
/// A diagnostic message string. /// A diagnostic message string.
/// ///
/// This is, for all intents and purposes, equivalent to a `Box<str>`. /// This is, for all intents and purposes, equivalent to a `Box<str>`.

View File

@@ -1284,7 +1284,7 @@ watermelon
let diag = env.err().primary("animals", "5", "5", "").build(); let diag = env.err().primary("animals", "5", "5", "").build();
insta::assert_snapshot!( insta::assert_snapshot!(
env.render(&diag), env.render(&diag),
@" @r"
error[test-diagnostic]: main diagnostic message error[test-diagnostic]: main diagnostic message
--> animals:5:1 --> animals:5:1
| |
@@ -1308,7 +1308,7 @@ watermelon
.build(); .build();
insta::assert_snapshot!( insta::assert_snapshot!(
env.render(&diag), env.render(&diag),
@" @r"
warning[test-diagnostic]: main diagnostic message warning[test-diagnostic]: main diagnostic message
--> animals:5:1 --> animals:5:1
| |
@@ -1328,7 +1328,7 @@ watermelon
.build(); .build();
insta::assert_snapshot!( insta::assert_snapshot!(
env.render(&diag), env.render(&diag),
@" @r"
info[test-diagnostic]: main diagnostic message info[test-diagnostic]: main diagnostic message
--> animals:5:1 --> animals:5:1
| |
@@ -1355,7 +1355,7 @@ watermelon
let diag = builder.build(); let diag = builder.build();
insta::assert_snapshot!( insta::assert_snapshot!(
env.render(&diag), env.render(&diag),
@" @r"
error[test-diagnostic]: main diagnostic message error[test-diagnostic]: main diagnostic message
--> animals:1:1 --> animals:1:1
| |
@@ -1374,7 +1374,7 @@ watermelon
let diag = builder.build(); let diag = builder.build();
insta::assert_snapshot!( insta::assert_snapshot!(
env.render(&diag), env.render(&diag),
@" @r"
error[test-diagnostic]: main diagnostic message error[test-diagnostic]: main diagnostic message
--> animals:1:1 --> animals:1:1
| |
@@ -1395,7 +1395,7 @@ watermelon
let diag = env.err().primary("non-ascii", "5", "5", "").build(); let diag = env.err().primary("non-ascii", "5", "5", "").build();
insta::assert_snapshot!( insta::assert_snapshot!(
env.render(&diag), env.render(&diag),
@" @r"
error[test-diagnostic]: main diagnostic message error[test-diagnostic]: main diagnostic message
--> non-ascii:5:1 --> non-ascii:5:1
| |
@@ -1414,7 +1414,7 @@ watermelon
let diag = env.err().primary("non-ascii", "2:4", "2:8", "").build(); let diag = env.err().primary("non-ascii", "2:4", "2:8", "").build();
insta::assert_snapshot!( insta::assert_snapshot!(
env.render(&diag), env.render(&diag),
@" @r"
error[test-diagnostic]: main diagnostic message error[test-diagnostic]: main diagnostic message
--> non-ascii:2:2 --> non-ascii:2:2
| |
@@ -1438,7 +1438,7 @@ watermelon
env.context(1); env.context(1);
insta::assert_snapshot!( insta::assert_snapshot!(
env.render(&diag), env.render(&diag),
@" @r"
error[test-diagnostic]: main diagnostic message error[test-diagnostic]: main diagnostic message
--> animals:5:1 --> animals:5:1
| |
@@ -1455,7 +1455,7 @@ watermelon
env.context(0); env.context(0);
insta::assert_snapshot!( insta::assert_snapshot!(
env.render(&diag), env.render(&diag),
@" @r"
error[test-diagnostic]: main diagnostic message error[test-diagnostic]: main diagnostic message
--> animals:5:1 --> animals:5:1
| |
@@ -1470,7 +1470,7 @@ watermelon
env.context(2); env.context(2);
insta::assert_snapshot!( insta::assert_snapshot!(
env.render(&diag), env.render(&diag),
@" @r"
error[test-diagnostic]: main diagnostic message error[test-diagnostic]: main diagnostic message
--> animals:1:1 --> animals:1:1
| |
@@ -1487,7 +1487,7 @@ watermelon
env.context(2); env.context(2);
insta::assert_snapshot!( insta::assert_snapshot!(
env.render(&diag), env.render(&diag),
@" @r"
error[test-diagnostic]: main diagnostic message error[test-diagnostic]: main diagnostic message
--> animals:11:1 --> animals:11:1
| |
@@ -1504,7 +1504,7 @@ watermelon
env.context(200); env.context(200);
insta::assert_snapshot!( insta::assert_snapshot!(
env.render(&diag), env.render(&diag),
@" @r"
error[test-diagnostic]: main diagnostic message error[test-diagnostic]: main diagnostic message
--> animals:5:1 --> animals:5:1
| |
@@ -1537,7 +1537,7 @@ watermelon
.build(); .build();
insta::assert_snapshot!( insta::assert_snapshot!(
env.render(&diag), env.render(&diag),
@" @r"
error[test-diagnostic]: main diagnostic message error[test-diagnostic]: main diagnostic message
--> animals:1:1 --> animals:1:1
| |
@@ -1581,7 +1581,7 @@ watermelon
.build(); .build();
insta::assert_snapshot!( insta::assert_snapshot!(
env.render(&diag), env.render(&diag),
@" @r"
error[test-diagnostic]: main diagnostic message error[test-diagnostic]: main diagnostic message
--> animals:1:1 --> animals:1:1
| |
@@ -1606,7 +1606,7 @@ watermelon
.build(); .build();
insta::assert_snapshot!( insta::assert_snapshot!(
env.render(&diag), env.render(&diag),
@" @r"
error[test-diagnostic]: main diagnostic message error[test-diagnostic]: main diagnostic message
--> animals:1:1 --> animals:1:1
| |
@@ -1634,7 +1634,7 @@ watermelon
.build(); .build();
insta::assert_snapshot!( insta::assert_snapshot!(
env.render(&diag), env.render(&diag),
@" @r"
error[test-diagnostic]: main diagnostic message error[test-diagnostic]: main diagnostic message
--> animals:1:1 --> animals:1:1
| |
@@ -1662,7 +1662,7 @@ watermelon
.build(); .build();
insta::assert_snapshot!( insta::assert_snapshot!(
env.render(&diag), env.render(&diag),
@" @r"
error[test-diagnostic]: main diagnostic message error[test-diagnostic]: main diagnostic message
--> animals:1:1 --> animals:1:1
| |
@@ -1687,7 +1687,7 @@ watermelon
.build(); .build();
insta::assert_snapshot!( insta::assert_snapshot!(
env.render(&diag), env.render(&diag),
@" @r"
error[test-diagnostic]: main diagnostic message error[test-diagnostic]: main diagnostic message
--> animals:1:1 --> animals:1:1
| |
@@ -1718,7 +1718,7 @@ watermelon
// window. // window.
insta::assert_snapshot!( insta::assert_snapshot!(
env.render(&diag), env.render(&diag),
@" @r"
error[test-diagnostic]: main diagnostic message error[test-diagnostic]: main diagnostic message
--> animals:1:1 --> animals:1:1
| |
@@ -1756,7 +1756,7 @@ watermelon
let diag = env.err().primary("spacey-animals", "8", "8", "").build(); let diag = env.err().primary("spacey-animals", "8", "8", "").build();
insta::assert_snapshot!( insta::assert_snapshot!(
env.render(&diag), env.render(&diag),
@" @r"
error[test-diagnostic]: main diagnostic message error[test-diagnostic]: main diagnostic message
--> spacey-animals:8:1 --> spacey-animals:8:1
| |
@@ -1773,7 +1773,7 @@ watermelon
let diag = env.err().primary("spacey-animals", "12", "12", "").build(); let diag = env.err().primary("spacey-animals", "12", "12", "").build();
insta::assert_snapshot!( insta::assert_snapshot!(
env.render(&diag), env.render(&diag),
@" @r"
error[test-diagnostic]: main diagnostic message error[test-diagnostic]: main diagnostic message
--> spacey-animals:12:1 --> spacey-animals:12:1
| |
@@ -1791,7 +1791,7 @@ watermelon
let diag = env.err().primary("spacey-animals", "13", "13", "").build(); let diag = env.err().primary("spacey-animals", "13", "13", "").build();
insta::assert_snapshot!( insta::assert_snapshot!(
env.render(&diag), env.render(&diag),
@" @r"
error[test-diagnostic]: main diagnostic message error[test-diagnostic]: main diagnostic message
--> spacey-animals:13:1 --> spacey-animals:13:1
| |
@@ -1831,7 +1831,7 @@ watermelon
// instead of special casing the snippet assembly. // instead of special casing the snippet assembly.
insta::assert_snapshot!( insta::assert_snapshot!(
env.render(&diag), env.render(&diag),
@" @r"
error[test-diagnostic]: main diagnostic message error[test-diagnostic]: main diagnostic message
--> spacey-animals:3:1 --> spacey-animals:3:1
| |
@@ -1860,7 +1860,7 @@ watermelon
.build(); .build();
insta::assert_snapshot!( insta::assert_snapshot!(
env.render(&diag), env.render(&diag),
@" @r"
error[test-diagnostic]: main diagnostic message error[test-diagnostic]: main diagnostic message
--> animals:3:1 --> animals:3:1
| |
@@ -1897,7 +1897,7 @@ watermelon
); );
insta::assert_snapshot!( insta::assert_snapshot!(
env.render(&diag), env.render(&diag),
@" @r"
error[test-diagnostic]: main diagnostic message error[test-diagnostic]: main diagnostic message
--> animals:3:1 --> animals:3:1
| |
@@ -1934,7 +1934,7 @@ watermelon
); );
insta::assert_snapshot!( insta::assert_snapshot!(
env.render(&diag), env.render(&diag),
@" @r"
error[test-diagnostic]: main diagnostic message error[test-diagnostic]: main diagnostic message
--> animals:3:1 --> animals:3:1
| |
@@ -1962,7 +1962,7 @@ watermelon
diag.sub(env.sub_warn().primary("fruits", "3", "3", "").build()); diag.sub(env.sub_warn().primary("fruits", "3", "3", "").build());
insta::assert_snapshot!( insta::assert_snapshot!(
env.render(&diag), env.render(&diag),
@" @r"
error[test-diagnostic]: main diagnostic message error[test-diagnostic]: main diagnostic message
--> animals:3:1 --> animals:3:1
| |
@@ -1998,7 +1998,7 @@ watermelon
diag.sub(env.sub_warn().primary("animals", "11", "11", "").build()); diag.sub(env.sub_warn().primary("animals", "11", "11", "").build());
insta::assert_snapshot!( insta::assert_snapshot!(
env.render(&diag), env.render(&diag),
@" @r"
error[test-diagnostic]: main diagnostic message error[test-diagnostic]: main diagnostic message
--> animals:3:1 --> animals:3:1
| |
@@ -2037,7 +2037,7 @@ watermelon
diag.sub(env.sub_warn().primary("fruits", "3", "3", "").build()); diag.sub(env.sub_warn().primary("fruits", "3", "3", "").build());
insta::assert_snapshot!( insta::assert_snapshot!(
env.render(&diag), env.render(&diag),
@" @r"
error[test-diagnostic]: main diagnostic message error[test-diagnostic]: main diagnostic message
--> animals:3:1 --> animals:3:1
| |
@@ -2085,7 +2085,7 @@ watermelon
diag.sub(env.sub_warn().secondary("animals", "3", "3", "").build()); diag.sub(env.sub_warn().secondary("animals", "3", "3", "").build());
insta::assert_snapshot!( insta::assert_snapshot!(
env.render(&diag), env.render(&diag),
@" @r"
error[test-diagnostic]: main diagnostic message error[test-diagnostic]: main diagnostic message
--> animals:3:1 --> animals:3:1
| |
@@ -2121,7 +2121,7 @@ watermelon
let diag = env.err().primary("animals", "5", "6", "").build(); let diag = env.err().primary("animals", "5", "6", "").build();
insta::assert_snapshot!( insta::assert_snapshot!(
env.render(&diag), env.render(&diag),
@" @r"
error[test-diagnostic]: main diagnostic message error[test-diagnostic]: main diagnostic message
--> animals:5:1 --> animals:5:1
| |
@@ -2144,7 +2144,7 @@ watermelon
let diag = env.err().primary("animals", "5", "7:0", "").build(); let diag = env.err().primary("animals", "5", "7:0", "").build();
insta::assert_snapshot!( insta::assert_snapshot!(
env.render(&diag), env.render(&diag),
@" @r"
error[test-diagnostic]: main diagnostic message error[test-diagnostic]: main diagnostic message
--> animals:5:1 --> animals:5:1
| |
@@ -2164,7 +2164,7 @@ watermelon
let diag = env.err().primary("animals", "5", "7:1", "").build(); let diag = env.err().primary("animals", "5", "7:1", "").build();
insta::assert_snapshot!( insta::assert_snapshot!(
env.render(&diag), env.render(&diag),
@" @r"
error[test-diagnostic]: main diagnostic message error[test-diagnostic]: main diagnostic message
--> animals:5:1 --> animals:5:1
| |
@@ -2184,7 +2184,7 @@ watermelon
let diag = env.err().primary("animals", "5:3", "8:8", "").build(); let diag = env.err().primary("animals", "5:3", "8:8", "").build();
insta::assert_snapshot!( insta::assert_snapshot!(
env.render(&diag), env.render(&diag),
@" @r"
error[test-diagnostic]: main diagnostic message error[test-diagnostic]: main diagnostic message
--> animals:5:4 --> animals:5:4
| |
@@ -2206,7 +2206,7 @@ watermelon
let diag = env.err().secondary("animals", "5:3", "8:8", "").build(); let diag = env.err().secondary("animals", "5:3", "8:8", "").build();
insta::assert_snapshot!( insta::assert_snapshot!(
env.render(&diag), env.render(&diag),
@" @r"
error[test-diagnostic]: main diagnostic message error[test-diagnostic]: main diagnostic message
--> animals:5:4 --> animals:5:4
| |
@@ -2238,7 +2238,7 @@ watermelon
.build(); .build();
insta::assert_snapshot!( insta::assert_snapshot!(
env.render(&diag), env.render(&diag),
@" @r"
error[test-diagnostic]: main diagnostic message error[test-diagnostic]: main diagnostic message
--> animals:4:1 --> animals:4:1
| |
@@ -2267,7 +2267,7 @@ watermelon
.build(); .build();
insta::assert_snapshot!( insta::assert_snapshot!(
env.render(&diag), env.render(&diag),
@" @r"
error[test-diagnostic]: main diagnostic message error[test-diagnostic]: main diagnostic message
--> animals:4:1 --> animals:4:1
| |
@@ -2298,7 +2298,7 @@ watermelon
.build(); .build();
insta::assert_snapshot!( insta::assert_snapshot!(
env.render(&diag), env.render(&diag),
@" @r"
error[test-diagnostic]: main diagnostic message error[test-diagnostic]: main diagnostic message
--> animals:5:1 --> animals:5:1
| |
@@ -2333,7 +2333,7 @@ watermelon
// better using only ASCII art. // better using only ASCII art.
insta::assert_snapshot!( insta::assert_snapshot!(
env.render(&diag), env.render(&diag),
@" @r"
error[test-diagnostic]: main diagnostic message error[test-diagnostic]: main diagnostic message
--> animals:5:1 --> animals:5:1
| |
@@ -2361,7 +2361,7 @@ watermelon
.build(); .build();
insta::assert_snapshot!( insta::assert_snapshot!(
env.render(&diag), env.render(&diag),
@" @r"
error[test-diagnostic]: main diagnostic message error[test-diagnostic]: main diagnostic message
--> animals:5:1 --> animals:5:1
| |
@@ -2393,7 +2393,7 @@ watermelon
.build(); .build();
insta::assert_snapshot!( insta::assert_snapshot!(
env.render(&diag), env.render(&diag),
@" @r"
error[test-diagnostic]: main diagnostic message error[test-diagnostic]: main diagnostic message
--> animals:5:3 --> animals:5:3
| |
@@ -2415,7 +2415,7 @@ watermelon
.build(); .build();
insta::assert_snapshot!( insta::assert_snapshot!(
env.render(&diag), env.render(&diag),
@" @r"
error[test-diagnostic]: main diagnostic message error[test-diagnostic]: main diagnostic message
--> animals:5:3 --> animals:5:3
| |
@@ -2448,7 +2448,7 @@ watermelon
.build(); .build();
insta::assert_snapshot!( insta::assert_snapshot!(
env.render(&diag), env.render(&diag),
@" @r"
error[test-diagnostic]: main diagnostic message error[test-diagnostic]: main diagnostic message
--> animals:8:1 --> animals:8:1
| |
@@ -2488,7 +2488,7 @@ watermelon
.build(); .build();
insta::assert_snapshot!( insta::assert_snapshot!(
env.render(&diag), env.render(&diag),
@" @r"
error[test-diagnostic]: main diagnostic message error[test-diagnostic]: main diagnostic message
--> animals:5:1 --> animals:5:1
| |
@@ -2532,7 +2532,7 @@ watermelon
.build(); .build();
insta::assert_snapshot!( insta::assert_snapshot!(
env.render(&diag), env.render(&diag),
@" @r"
error[test-diagnostic]: main diagnostic message error[test-diagnostic]: main diagnostic message
--> fruits:1:1 --> fruits:1:1
| |
@@ -2567,7 +2567,7 @@ watermelon
.build(); .build();
insta::assert_snapshot!( insta::assert_snapshot!(
env.render(&diag), env.render(&diag),
@" @r"
error[test-diagnostic]: main diagnostic message error[test-diagnostic]: main diagnostic message
--> animals:11:1 --> animals:11:1
| |

View File

@@ -52,7 +52,7 @@ impl AzureRenderer<'_> {
f, f,
"code={code};]{body}", "code={code};]{body}",
code = diag.secondary_code_or_id(), code = diag.secondary_code_or_id(),
body = diag.concise_message(), body = diag.body(),
)?; )?;
} }

View File

@@ -28,10 +28,6 @@ impl<'a> ConciseRenderer<'a> {
let sep = fmt_styled(":", stylesheet.separator); let sep = fmt_styled(":", stylesheet.separator);
for diag in diagnostics { for diag in diagnostics {
if self.config.is_canceled() {
return Ok(());
}
if let Some(span) = diag.primary_span() { if let Some(span) = diag.primary_span() {
write!( write!(
f, f,
@@ -137,7 +133,7 @@ mod tests {
#[test] #[test]
fn output() { fn output() {
let (env, diagnostics) = create_diagnostics(DiagnosticFormat::Concise); let (env, diagnostics) = create_diagnostics(DiagnosticFormat::Concise);
insta::assert_snapshot!(env.render_diagnostics(&diagnostics), @" insta::assert_snapshot!(env.render_diagnostics(&diagnostics), @r"
fib.py:1:8: error[unused-import] `os` imported but unused fib.py:1:8: error[unused-import] `os` imported but unused
fib.py:6:5: error[unused-variable] Local variable `x` is assigned to but never used fib.py:6:5: error[unused-variable] Local variable `x` is assigned to but never used
undef.py:1:4: error[undefined-name] Undefined name `a` undef.py:1:4: error[undefined-name] Undefined name `a`
@@ -150,7 +146,7 @@ mod tests {
env.hide_severity(true); env.hide_severity(true);
env.show_fix_status(true); env.show_fix_status(true);
env.fix_applicability(Applicability::DisplayOnly); env.fix_applicability(Applicability::DisplayOnly);
insta::assert_snapshot!(env.render_diagnostics(&diagnostics), @" insta::assert_snapshot!(env.render_diagnostics(&diagnostics), @r"
fib.py:1:8: F401 [*] `os` imported but unused fib.py:1:8: F401 [*] `os` imported but unused
fib.py:6:5: F841 [*] Local variable `x` is assigned to but never used fib.py:6:5: F841 [*] Local variable `x` is assigned to but never used
undef.py:1:4: F821 Undefined name `a` undef.py:1:4: F821 Undefined name `a`
@@ -164,7 +160,7 @@ mod tests {
env.show_fix_status(true); env.show_fix_status(true);
env.fix_applicability(Applicability::DisplayOnly); env.fix_applicability(Applicability::DisplayOnly);
env.preview(true); env.preview(true);
insta::assert_snapshot!(env.render_diagnostics(&diagnostics), @" insta::assert_snapshot!(env.render_diagnostics(&diagnostics), @r"
fib.py:1:8: F401 [*] `os` imported but unused fib.py:1:8: F401 [*] `os` imported but unused
fib.py:6:5: F841 [*] Local variable `x` is assigned to but never used fib.py:6:5: F841 [*] Local variable `x` is assigned to but never used
undef.py:1:4: F821 Undefined name `a` undef.py:1:4: F821 Undefined name `a`
@@ -177,7 +173,7 @@ mod tests {
env.hide_severity(true); env.hide_severity(true);
env.show_fix_status(true); env.show_fix_status(true);
env.fix_applicability(Applicability::DisplayOnly); env.fix_applicability(Applicability::DisplayOnly);
insta::assert_snapshot!(env.render_diagnostics(&diagnostics), @" insta::assert_snapshot!(env.render_diagnostics(&diagnostics), @r"
syntax_errors.py:1:15: invalid-syntax: Expected one or more symbol names after import syntax_errors.py:1:15: invalid-syntax: Expected one or more symbol names after import
syntax_errors.py:3:12: invalid-syntax: Expected ')', found newline syntax_errors.py:3:12: invalid-syntax: Expected ')', found newline
"); ");
@@ -186,7 +182,7 @@ mod tests {
#[test] #[test]
fn syntax_errors() { fn syntax_errors() {
let (env, diagnostics) = create_syntax_error_diagnostics(DiagnosticFormat::Concise); let (env, diagnostics) = create_syntax_error_diagnostics(DiagnosticFormat::Concise);
insta::assert_snapshot!(env.render_diagnostics(&diagnostics), @" insta::assert_snapshot!(env.render_diagnostics(&diagnostics), @r"
syntax_errors.py:1:15: error[invalid-syntax] Expected one or more symbol names after import syntax_errors.py:1:15: error[invalid-syntax] Expected one or more symbol names after import
syntax_errors.py:3:12: error[invalid-syntax] Expected ')', found newline syntax_errors.py:3:12: error[invalid-syntax] Expected ')', found newline
"); ");
@@ -195,7 +191,7 @@ mod tests {
#[test] #[test]
fn notebook_output() { fn notebook_output() {
let (env, diagnostics) = create_notebook_diagnostics(DiagnosticFormat::Concise); let (env, diagnostics) = create_notebook_diagnostics(DiagnosticFormat::Concise);
insta::assert_snapshot!(env.render_diagnostics(&diagnostics), @" insta::assert_snapshot!(env.render_diagnostics(&diagnostics), @r"
notebook.ipynb:cell 1:2:8: error[unused-import] `os` imported but unused notebook.ipynb:cell 1:2:8: error[unused-import] `os` imported but unused
notebook.ipynb:cell 2:2:8: error[unused-import] `math` imported but unused notebook.ipynb:cell 2:2:8: error[unused-import] `math` imported but unused
notebook.ipynb:cell 3:4:5: error[unused-variable] Local variable `x` is assigned to but never used notebook.ipynb:cell 3:4:5: error[unused-variable] Local variable `x` is assigned to but never used

View File

@@ -53,10 +53,6 @@ impl<'a> FullRenderer<'a> {
.hyperlink(stylesheet.hyperlink); .hyperlink(stylesheet.hyperlink);
for diag in diagnostics { for diag in diagnostics {
if self.config.is_canceled() {
return Ok(());
}
let resolved = Resolved::new(self.resolver, diag, self.config); let resolved = Resolved::new(self.resolver, diag, self.config);
let renderable = resolved.to_renderable(self.config.context); let renderable = resolved.to_renderable(self.config.context);
for diag in renderable.diagnostics.iter() { for diag in renderable.diagnostics.iter() {

View File

@@ -49,10 +49,6 @@ impl<'a> GithubRenderer<'a> {
} }
.unwrap_or_default(); .unwrap_or_default();
// GitHub Actions workflow commands have constraints on error annotations:
// - `col` and `endColumn` cannot be set if `line` and `endLine` are different
// See: https://github.com/astral-sh/ruff/issues/22074
if start_location.line == end_location.line {
write!( write!(
f, f,
",line={row},col={column},endLine={end_row},endColumn={end_column}::", ",line={row},col={column},endLine={end_row},endColumn={end_column}::",
@@ -61,14 +57,6 @@ impl<'a> GithubRenderer<'a> {
end_row = end_location.line, end_row = end_location.line,
end_column = end_location.column, end_column = end_location.column,
)?; )?;
} else {
write!(
f,
",line={row},endLine={end_row}::",
row = start_location.line,
end_row = end_location.line,
)?;
}
write!( write!(
f, f,
@@ -87,7 +75,7 @@ impl<'a> GithubRenderer<'a> {
write!(f, "{id}:", id = diagnostic.id())?; write!(f, "{id}:", id = diagnostic.id())?;
} }
writeln!(f, " {}", diagnostic.concise_message())?; writeln!(f, " {}", diagnostic.body())?;
} }
Ok(()) Ok(())

View File

@@ -98,7 +98,7 @@ impl Serialize for SerializedMessages<'_> {
} }
fingerprints.insert(message_fingerprint); fingerprints.insert(message_fingerprint);
let description = diagnostic.concise_message(); let description = diagnostic.body();
let check_name = diagnostic.secondary_code_or_id(); let check_name = diagnostic.secondary_code_or_id();
let severity = match diagnostic.severity() { let severity = match diagnostic.severity() {
Severity::Info => "info", Severity::Info => "info",

View File

@@ -6,7 +6,7 @@ use ruff_notebook::NotebookIndex;
use ruff_source_file::{LineColumn, OneIndexed}; use ruff_source_file::{LineColumn, OneIndexed};
use ruff_text_size::Ranged; use ruff_text_size::Ranged;
use crate::diagnostic::{ConciseMessage, Diagnostic, DiagnosticSource, DisplayDiagnosticConfig}; use crate::diagnostic::{Diagnostic, DiagnosticSource, DisplayDiagnosticConfig};
use super::FileResolver; use super::FileResolver;
@@ -101,7 +101,7 @@ pub(super) fn diagnostic_to_json<'a>(
JsonDiagnostic { JsonDiagnostic {
code: diagnostic.secondary_code_or_id(), code: diagnostic.secondary_code_or_id(),
url: diagnostic.documentation_url(), url: diagnostic.documentation_url(),
message: diagnostic.concise_message(), message: diagnostic.body(),
fix, fix,
cell: notebook_cell_index, cell: notebook_cell_index,
location: start_location.map(JsonLocation::from), location: start_location.map(JsonLocation::from),
@@ -113,7 +113,7 @@ pub(super) fn diagnostic_to_json<'a>(
JsonDiagnostic { JsonDiagnostic {
code: diagnostic.secondary_code_or_id(), code: diagnostic.secondary_code_or_id(),
url: diagnostic.documentation_url(), url: diagnostic.documentation_url(),
message: diagnostic.concise_message(), message: diagnostic.body(),
fix, fix,
cell: notebook_cell_index, cell: notebook_cell_index,
location: Some(start_location.unwrap_or_default().into()), location: Some(start_location.unwrap_or_default().into()),
@@ -226,7 +226,7 @@ pub(crate) struct JsonDiagnostic<'a> {
filename: Option<&'a str>, filename: Option<&'a str>,
fix: Option<JsonFix<'a>>, fix: Option<JsonFix<'a>>,
location: Option<JsonLocation>, location: Option<JsonLocation>,
message: ConciseMessage<'a>, message: &'a str,
noqa_row: Option<OneIndexed>, noqa_row: Option<OneIndexed>,
url: Option<&'a str>, url: Option<&'a str>,
} }

View File

@@ -56,17 +56,17 @@ impl<'a> JunitRenderer<'a> {
start_location: location, start_location: location,
} = diagnostic; } = diagnostic;
let mut status = TestCaseStatus::non_success(NonSuccessKind::Failure); let mut status = TestCaseStatus::non_success(NonSuccessKind::Failure);
status.set_message(diagnostic.concise_message().to_str()); status.set_message(diagnostic.body());
if let Some(location) = location { if let Some(location) = location {
status.set_description(format!( status.set_description(format!(
"line {row}, col {col}, {body}", "line {row}, col {col}, {body}",
row = location.line, row = location.line,
col = location.column, col = location.column,
body = diagnostic.concise_message() body = diagnostic.body()
)); ));
} else { } else {
status.set_description(diagnostic.concise_message().to_str()); status.set_description(diagnostic.body());
} }
let code = diagnostic let code = diagnostic

View File

@@ -55,7 +55,7 @@ impl PylintRenderer<'_> {
f, f,
"{path}:{row}: [{code}] {body}", "{path}:{row}: [{code}] {body}",
path = filename, path = filename,
body = diagnostic.concise_message() body = diagnostic.body()
)?; )?;
} }

Some files were not shown because too many files have changed in this diff Show More