Compare commits
132 Commits
dcreager/s
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
87eec9bb51 | ||
|
|
eaed0d9b5c | ||
|
|
eb96456e1e | ||
|
|
3e0299488e | ||
|
|
7f0ce3e88d | ||
|
|
ba0736385d | ||
|
|
e41f045ec5 | ||
|
|
b24afb643c | ||
|
|
853bb00626 | ||
|
|
b5814b91c1 | ||
|
|
ea46426157 | ||
|
|
ddd2fc7a90 | ||
|
|
4ebf10cf1b | ||
|
|
9a676bbeb7 | ||
|
|
d9028a098b | ||
|
|
56077ee9a9 | ||
|
|
20c01d2553 | ||
|
|
c98ea1bc24 | ||
|
|
9a2990b2a1 | ||
|
|
a697050a83 | ||
|
|
2f64ef9c72 | ||
|
|
fde7d72fbb | ||
|
|
d13b5db066 | ||
|
|
c7b41060f4 | ||
|
|
3878701265 | ||
|
|
6e89e0abff | ||
|
|
cb31883c5f | ||
|
|
6d8f2864c3 | ||
|
|
990d0a8999 | ||
|
|
99beabdde8 | ||
|
|
3ae4db3ccd | ||
|
|
8ac5f9d8bc | ||
|
|
4abc5fe2f1 | ||
|
|
78ef241200 | ||
|
|
e4ba29392b | ||
|
|
29064034ba | ||
|
|
f1db842821 | ||
|
|
5a3deee353 | ||
|
|
e15f88ff21 | ||
|
|
a559275c3e | ||
|
|
95199c4217 | ||
|
|
f92a818fdd | ||
|
|
39ec97df79 | ||
|
|
a21988d820 | ||
|
|
eab41d5a4c | ||
|
|
52f4a529f7 | ||
|
|
8fd142f4ef | ||
|
|
5dca6d22df | ||
|
|
4c5846c6fe | ||
|
|
0289d1b163 | ||
|
|
09ff3e7056 | ||
|
|
7bacca9b62 | ||
|
|
2c68057c4b | ||
|
|
8e29be9c1c | ||
|
|
880513a013 | ||
|
|
046c5a46d8 | ||
|
|
cfed34334c | ||
|
|
11cc324449 | ||
|
|
c88e1a0663 | ||
|
|
2c7ac17b1e | ||
|
|
a0f2cd0ded | ||
|
|
dc61104726 | ||
|
|
f40c578ffb | ||
|
|
baaf6966f6 | ||
|
|
a6df4a3be7 | ||
|
|
1094009790 | ||
|
|
10eb3d52d5 | ||
|
|
91d24ebb92 | ||
|
|
e68fba20a9 | ||
|
|
64117c1146 | ||
|
|
2196ef3a33 | ||
|
|
c36397031b | ||
|
|
eef34958f9 | ||
|
|
f1bd5f1941 | ||
|
|
56862f8241 | ||
|
|
e9cc2f6f42 | ||
|
|
8dd56d4264 | ||
|
|
d4c1b0ccc7 | ||
|
|
e61657ff3c | ||
|
|
ba5dd5837c | ||
|
|
c5f6a74da5 | ||
|
|
b3cde98cd1 | ||
|
|
f9f7a6901b | ||
|
|
c920cf8cdb | ||
|
|
bb757b5a79 | ||
|
|
1f49e8ef51 | ||
|
|
701f5134ab | ||
|
|
eea9ad8352 | ||
|
|
eeac2bd3ee | ||
|
|
7319c37f4e | ||
|
|
805503c19a | ||
|
|
68a2f6c57d | ||
|
|
abaa735e1d | ||
|
|
c02d164357 | ||
|
|
88aa3f82f0 | ||
|
|
30902497db | ||
|
|
3ad99fb1f4 | ||
|
|
d0ff59cfe5 | ||
|
|
952193e0c6 | ||
|
|
4cba2e8f91 | ||
|
|
1a7f53022a | ||
|
|
266a7bc4c5 | ||
|
|
3b7a5e4de8 | ||
|
|
93039d055d | ||
|
|
3b61da0da3 | ||
|
|
5933cc0101 | ||
|
|
2190fcebe0 | ||
|
|
df9d6886d4 | ||
|
|
5133fa4516 | ||
|
|
21c5cfe236 | ||
|
|
f97da18267 | ||
|
|
bc191f59b9 | ||
|
|
00f86c39e0 | ||
|
|
2ec29b7418 | ||
|
|
ab1ac254d9 | ||
|
|
01de8bef3e | ||
|
|
b59f6eb5e9 | ||
|
|
9ca78bdf76 | ||
|
|
d65542c05e | ||
|
|
98728b2c98 | ||
|
|
924b2972f2 | ||
|
|
d035744959 | ||
|
|
ce059c4857 | ||
|
|
acbc83d6d2 | ||
|
|
a9e5246786 | ||
|
|
8b8b174e4f | ||
|
|
28fa02129b | ||
|
|
a10e42294b | ||
|
|
12a4ca003f | ||
|
|
60f7ec90ef | ||
|
|
922d964bcb | ||
|
|
4712503c6d |
@@ -5,4 +5,4 @@ rustup component add clippy rustfmt
|
||||
cargo install cargo-insta
|
||||
cargo fetch
|
||||
|
||||
pip install maturin pre-commit
|
||||
pip install maturin prek
|
||||
|
||||
10
.github/CODEOWNERS
vendored
10
.github/CODEOWNERS
vendored
@@ -20,9 +20,11 @@
|
||||
# ty
|
||||
/crates/ty* @carljm @MichaReiser @AlexWaygood @sharkdp @dcreager
|
||||
/crates/ruff_db/ @carljm @MichaReiser @sharkdp @dcreager
|
||||
/crates/ty_project/ @carljm @MichaReiser @sharkdp @dcreager
|
||||
/crates/ty_server/ @carljm @MichaReiser @sharkdp @dcreager
|
||||
/crates/ty_project/ @carljm @MichaReiser @sharkdp @dcreager @Gankra
|
||||
/crates/ty_ide/ @carljm @MichaReiser @AlexWaygood @sharkdp @dcreager @Gankra
|
||||
/crates/ty_server/ @carljm @MichaReiser @sharkdp @dcreager @Gankra
|
||||
/crates/ty/ @carljm @MichaReiser @sharkdp @dcreager
|
||||
/crates/ty_wasm/ @carljm @MichaReiser @sharkdp @dcreager
|
||||
/crates/ty_wasm/ @carljm @MichaReiser @sharkdp @dcreager @Gankra
|
||||
/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
|
||||
|
||||
4
.github/actionlint.yaml
vendored
4
.github/actionlint.yaml
vendored
@@ -1,4 +1,4 @@
|
||||
# Configuration for the actionlint tool, which we run via pre-commit
|
||||
# Configuration for the actionlint tool, which we run via prek
|
||||
# to verify the correctness of the syntax in our GitHub Actions workflows.
|
||||
|
||||
self-hosted-runner:
|
||||
@@ -17,4 +17,4 @@ self-hosted-runner:
|
||||
paths:
|
||||
".github/workflows/mypy_primer.yaml":
|
||||
ignore:
|
||||
- 'condition "false" is always evaluated to false. remove the if: section'
|
||||
- 'constant expression "false" in condition. remove the if: section'
|
||||
|
||||
2
.github/mypy-primer-ty.toml
vendored
2
.github/mypy-primer-ty.toml
vendored
@@ -5,5 +5,5 @@
|
||||
[rules]
|
||||
possibly-unresolved-reference = "warn"
|
||||
possibly-missing-import = "warn"
|
||||
unused-ignore-comment = "warn"
|
||||
division-by-zero = "warn"
|
||||
unsupported-dynamic-base = "warn"
|
||||
|
||||
4
.github/renovate.json5
vendored
4
.github/renovate.json5
vendored
@@ -76,9 +76,9 @@
|
||||
enabled: false,
|
||||
},
|
||||
{
|
||||
groupName: "pre-commit dependencies",
|
||||
groupName: "prek dependencies",
|
||||
matchManagers: ["pre-commit"],
|
||||
description: "Weekly update of pre-commit dependencies",
|
||||
description: "Weekly update of prek dependencies",
|
||||
},
|
||||
{
|
||||
groupName: "NPM Development dependencies",
|
||||
|
||||
8
.github/workflows/build-binaries.yml
vendored
8
.github/workflows/build-binaries.yml
vendored
@@ -51,6 +51,7 @@ jobs:
|
||||
- name: "Build sdist"
|
||||
uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # v1.49.4
|
||||
with:
|
||||
maturin-version: v1.9.6
|
||||
command: sdist
|
||||
args: --out dist
|
||||
- name: "Test sdist"
|
||||
@@ -81,6 +82,7 @@ jobs:
|
||||
- name: "Build wheels - x86_64"
|
||||
uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # v1.49.4
|
||||
with:
|
||||
maturin-version: v1.9.6
|
||||
target: x86_64
|
||||
args: --release --locked --out dist
|
||||
- name: "Upload wheels"
|
||||
@@ -123,6 +125,7 @@ jobs:
|
||||
- name: "Build wheels - aarch64"
|
||||
uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # v1.49.4
|
||||
with:
|
||||
maturin-version: v1.9.6
|
||||
target: aarch64
|
||||
args: --release --locked --out dist
|
||||
- name: "Test wheel - aarch64"
|
||||
@@ -179,6 +182,7 @@ jobs:
|
||||
- name: "Build wheels"
|
||||
uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # v1.49.4
|
||||
with:
|
||||
maturin-version: v1.9.6
|
||||
target: ${{ matrix.platform.target }}
|
||||
args: --release --locked --out dist
|
||||
env:
|
||||
@@ -232,6 +236,7 @@ jobs:
|
||||
- name: "Build wheels"
|
||||
uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # v1.49.4
|
||||
with:
|
||||
maturin-version: v1.9.6
|
||||
target: ${{ matrix.target }}
|
||||
manylinux: auto
|
||||
args: --release --locked --out dist
|
||||
@@ -308,6 +313,7 @@ jobs:
|
||||
- name: "Build wheels"
|
||||
uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # v1.49.4
|
||||
with:
|
||||
maturin-version: v1.9.6
|
||||
target: ${{ matrix.platform.target }}
|
||||
manylinux: auto
|
||||
docker-options: ${{ matrix.platform.maturin_docker_options }}
|
||||
@@ -374,6 +380,7 @@ jobs:
|
||||
- name: "Build wheels"
|
||||
uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # v1.49.4
|
||||
with:
|
||||
maturin-version: v1.9.6
|
||||
target: ${{ matrix.target }}
|
||||
manylinux: musllinux_1_2
|
||||
args: --release --locked --out dist
|
||||
@@ -439,6 +446,7 @@ jobs:
|
||||
- name: "Build wheels"
|
||||
uses: PyO3/maturin-action@86b9d133d34bc1b40018696f782949dac11bd380 # v1.49.4
|
||||
with:
|
||||
maturin-version: v1.9.6
|
||||
target: ${{ matrix.platform.target }}
|
||||
manylinux: musllinux_1_2
|
||||
args: --release --locked --out dist
|
||||
|
||||
58
.github/workflows/build-wasm.yml
vendored
Normal file
58
.github/workflows/build-wasm.yml
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
# 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
|
||||
73
.github/workflows/ci.yaml
vendored
73
.github/workflows/ci.yaml
vendored
@@ -281,15 +281,15 @@ jobs:
|
||||
- name: "Install mold"
|
||||
uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1
|
||||
- name: "Install cargo nextest"
|
||||
uses: taiki-e/install-action@28a9d316db64b78a951f3f8587a5d08cc97ad8eb # v2.65.6
|
||||
uses: taiki-e/install-action@0e76c5c569f13f7eb21e8e5b26fe710062b57b62 # v2.65.13
|
||||
with:
|
||||
tool: cargo-nextest
|
||||
- name: "Install cargo insta"
|
||||
uses: taiki-e/install-action@28a9d316db64b78a951f3f8587a5d08cc97ad8eb # v2.65.6
|
||||
uses: taiki-e/install-action@0e76c5c569f13f7eb21e8e5b26fe710062b57b62 # v2.65.13
|
||||
with:
|
||||
tool: cargo-insta
|
||||
- name: "Install uv"
|
||||
uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7.1.6
|
||||
uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0
|
||||
with:
|
||||
enable-cache: "true"
|
||||
- name: ty mdtests (GitHub annotations)
|
||||
@@ -343,11 +343,11 @@ jobs:
|
||||
- name: "Install mold"
|
||||
uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1
|
||||
- name: "Install cargo nextest"
|
||||
uses: taiki-e/install-action@28a9d316db64b78a951f3f8587a5d08cc97ad8eb # v2.65.6
|
||||
uses: taiki-e/install-action@0e76c5c569f13f7eb21e8e5b26fe710062b57b62 # v2.65.13
|
||||
with:
|
||||
tool: cargo-nextest
|
||||
- name: "Install uv"
|
||||
uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7.1.6
|
||||
uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0
|
||||
with:
|
||||
enable-cache: "true"
|
||||
- name: "Run tests"
|
||||
@@ -376,11 +376,11 @@ jobs:
|
||||
- name: "Install Rust toolchain"
|
||||
run: rustup show
|
||||
- name: "Install cargo nextest"
|
||||
uses: taiki-e/install-action@28a9d316db64b78a951f3f8587a5d08cc97ad8eb # v2.65.6
|
||||
uses: taiki-e/install-action@0e76c5c569f13f7eb21e8e5b26fe710062b57b62 # v2.65.13
|
||||
with:
|
||||
tool: cargo-nextest
|
||||
- name: "Install uv"
|
||||
uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7.1.6
|
||||
uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0
|
||||
with:
|
||||
enable-cache: "true"
|
||||
- name: "Run tests"
|
||||
@@ -486,7 +486,7 @@ jobs:
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7.1.6
|
||||
- uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0
|
||||
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
|
||||
with:
|
||||
shared-key: ruff-linux-debug
|
||||
@@ -521,7 +521,7 @@ jobs:
|
||||
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
|
||||
with:
|
||||
save-if: ${{ github.ref == 'refs/heads/main' }}
|
||||
- uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7.1.6
|
||||
- uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0
|
||||
- name: "Install Rust toolchain"
|
||||
run: rustup component add rustfmt
|
||||
# Run all code generation scripts, and verify that the current output is
|
||||
@@ -561,7 +561,7 @@ jobs:
|
||||
ref: ${{ github.event.pull_request.base.ref }}
|
||||
persist-credentials: false
|
||||
|
||||
- uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7.1.6
|
||||
- uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
activate-environment: true
|
||||
@@ -667,7 +667,7 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
- uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7.1.6
|
||||
- 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' }}
|
||||
@@ -726,7 +726,7 @@ jobs:
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7.1.6
|
||||
- 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' }}
|
||||
@@ -769,32 +769,29 @@ jobs:
|
||||
- name: "Remove wheels from cache"
|
||||
run: rm -rf target/wheels
|
||||
|
||||
pre-commit:
|
||||
name: "pre-commit"
|
||||
prek:
|
||||
name: "prek"
|
||||
runs-on: ${{ github.repository == 'astral-sh/ruff' && 'depot-ubuntu-22.04-16' || 'ubuntu-latest' }}
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7.1.6
|
||||
- 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
|
||||
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
|
||||
with:
|
||||
node-version: 24
|
||||
- name: "Cache pre-commit"
|
||||
- name: "Cache prek"
|
||||
uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1
|
||||
with:
|
||||
path: ~/.cache/pre-commit
|
||||
key: pre-commit-${{ hashFiles('.pre-commit-config.yaml') }}
|
||||
- name: "Run pre-commit"
|
||||
path: ~/.cache/prek
|
||||
key: prek-${{ hashFiles('.pre-commit-config.yaml') }}
|
||||
- name: "Run prek"
|
||||
run: |
|
||||
echo '```console' > "$GITHUB_STEP_SUMMARY"
|
||||
# Enable color output for pre-commit and remove it for the summary
|
||||
# Use --hook-stage=manual to enable slower pre-commit hooks that are skipped by default
|
||||
SKIP=cargo-fmt uvx --python="${PYTHON_VERSION}" pre-commit run --all-files --show-diff-on-failure --color=always --hook-stage=manual | \
|
||||
# Enable color output for prek and remove it for the summary
|
||||
# Use --hook-stage=manual to enable slower hooks that are skipped by default
|
||||
SKIP=rustfmt uvx prek 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
|
||||
exit_code="${PIPESTATUS[0]}"
|
||||
echo '```' >> "$GITHUB_STEP_SUMMARY"
|
||||
@@ -814,7 +811,7 @@ jobs:
|
||||
- name: "Install Rust toolchain"
|
||||
run: rustup show
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7.1.6
|
||||
uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0
|
||||
with:
|
||||
python-version: 3.13
|
||||
activate-environment: true
|
||||
@@ -966,13 +963,13 @@ jobs:
|
||||
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
|
||||
with:
|
||||
save-if: ${{ github.ref == 'refs/heads/main' }}
|
||||
- uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7.1.6
|
||||
- uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0
|
||||
|
||||
- name: "Install Rust toolchain"
|
||||
run: rustup show
|
||||
|
||||
- name: "Install codspeed"
|
||||
uses: taiki-e/install-action@28a9d316db64b78a951f3f8587a5d08cc97ad8eb # v2.65.6
|
||||
uses: taiki-e/install-action@0e76c5c569f13f7eb21e8e5b26fe710062b57b62 # v2.65.13
|
||||
with:
|
||||
tool: cargo-codspeed
|
||||
|
||||
@@ -980,7 +977,7 @@ jobs:
|
||||
run: cargo codspeed build --features "codspeed,ruff_instrumented" --profile profiling --no-default-features -p ruff_benchmark --bench formatter --bench lexer --bench linter --bench parser
|
||||
|
||||
- name: "Run benchmarks"
|
||||
uses: CodSpeedHQ/action@972e3437949c89e1357ebd1a2dbc852fcbc57245 # v4.5.1
|
||||
uses: CodSpeedHQ/action@dbda7111f8ac363564b0c51b992d4ce76bb89f2f # v4.5.2
|
||||
with:
|
||||
mode: simulation
|
||||
run: cargo codspeed run
|
||||
@@ -1011,7 +1008,7 @@ jobs:
|
||||
run: rustup show
|
||||
|
||||
- name: "Install codspeed"
|
||||
uses: taiki-e/install-action@28a9d316db64b78a951f3f8587a5d08cc97ad8eb # v2.65.6
|
||||
uses: taiki-e/install-action@0e76c5c569f13f7eb21e8e5b26fe710062b57b62 # v2.65.13
|
||||
with:
|
||||
tool: cargo-codspeed
|
||||
|
||||
@@ -1044,10 +1041,10 @@ jobs:
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7.1.6
|
||||
- uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0
|
||||
|
||||
- name: "Install codspeed"
|
||||
uses: taiki-e/install-action@28a9d316db64b78a951f3f8587a5d08cc97ad8eb # v2.65.6
|
||||
uses: taiki-e/install-action@0e76c5c569f13f7eb21e8e5b26fe710062b57b62 # v2.65.13
|
||||
with:
|
||||
tool: cargo-codspeed
|
||||
|
||||
@@ -1061,7 +1058,7 @@ jobs:
|
||||
run: chmod +x target/codspeed/simulation/ruff_benchmark/ty
|
||||
|
||||
- name: "Run benchmarks"
|
||||
uses: CodSpeedHQ/action@972e3437949c89e1357ebd1a2dbc852fcbc57245 # v4.5.1
|
||||
uses: CodSpeedHQ/action@dbda7111f8ac363564b0c51b992d4ce76bb89f2f # v4.5.2
|
||||
with:
|
||||
mode: simulation
|
||||
run: cargo codspeed run --bench ty "${{ matrix.benchmark }}"
|
||||
@@ -1092,13 +1089,13 @@ jobs:
|
||||
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
|
||||
with:
|
||||
save-if: ${{ github.ref == 'refs/heads/main' }}
|
||||
- uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7.1.6
|
||||
- uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0
|
||||
|
||||
- name: "Install Rust toolchain"
|
||||
run: rustup show
|
||||
|
||||
- name: "Install codspeed"
|
||||
uses: taiki-e/install-action@28a9d316db64b78a951f3f8587a5d08cc97ad8eb # v2.65.6
|
||||
uses: taiki-e/install-action@0e76c5c569f13f7eb21e8e5b26fe710062b57b62 # v2.65.13
|
||||
with:
|
||||
tool: cargo-codspeed
|
||||
|
||||
@@ -1133,10 +1130,10 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7.1.6
|
||||
- uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0
|
||||
|
||||
- name: "Install codspeed"
|
||||
uses: taiki-e/install-action@28a9d316db64b78a951f3f8587a5d08cc97ad8eb # v2.65.6
|
||||
uses: taiki-e/install-action@0e76c5c569f13f7eb21e8e5b26fe710062b57b62 # v2.65.13
|
||||
with:
|
||||
tool: cargo-codspeed
|
||||
|
||||
@@ -1150,7 +1147,7 @@ jobs:
|
||||
run: chmod +x target/codspeed/walltime/ruff_benchmark/ty_walltime
|
||||
|
||||
- name: "Run benchmarks"
|
||||
uses: CodSpeedHQ/action@972e3437949c89e1357ebd1a2dbc852fcbc57245 # v4.5.1
|
||||
uses: CodSpeedHQ/action@dbda7111f8ac363564b0c51b992d4ce76bb89f2f # v4.5.2
|
||||
env:
|
||||
# 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
|
||||
|
||||
2
.github/workflows/daily_fuzz.yaml
vendored
2
.github/workflows/daily_fuzz.yaml
vendored
@@ -34,7 +34,7 @@ jobs:
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7.1.6
|
||||
- uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0
|
||||
- name: "Install Rust toolchain"
|
||||
run: rustup show
|
||||
- name: "Install mold"
|
||||
|
||||
6
.github/workflows/mypy_primer.yaml
vendored
6
.github/workflows/mypy_primer.yaml
vendored
@@ -48,7 +48,7 @@ jobs:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Install the latest version of uv
|
||||
uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7.1.6
|
||||
uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0
|
||||
|
||||
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
|
||||
with:
|
||||
@@ -87,7 +87,7 @@ jobs:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Install the latest version of uv
|
||||
uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7.1.6
|
||||
uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0
|
||||
|
||||
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
|
||||
with:
|
||||
@@ -129,7 +129,7 @@ jobs:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Install the latest version of uv
|
||||
uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7.1.6
|
||||
uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0
|
||||
|
||||
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
|
||||
with:
|
||||
|
||||
2
.github/workflows/publish-pypi.yml
vendored
2
.github/workflows/publish-pypi.yml
vendored
@@ -22,7 +22,7 @@ jobs:
|
||||
id-token: write
|
||||
steps:
|
||||
- name: "Install uv"
|
||||
uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7.1.6
|
||||
uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0
|
||||
- uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
|
||||
with:
|
||||
pattern: wheels-*
|
||||
|
||||
35
.github/workflows/publish-wasm.yml
vendored
35
.github/workflows/publish-wasm.yml
vendored
@@ -1,25 +1,18 @@
|
||||
# Build and publish ruff-api for wasm.
|
||||
# Publish ruff_wasm to npm.
|
||||
#
|
||||
# Assumed to run as a subworkflow of .github/workflows/release.yml; specifically, as a publish
|
||||
# job within `cargo-dist`.
|
||||
name: "Build and publish wasm"
|
||||
name: "Publish wasm"
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
workflow_call:
|
||||
inputs:
|
||||
plan:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
env:
|
||||
CARGO_INCREMENTAL: 0
|
||||
CARGO_NET_RETRY: 10
|
||||
CARGO_TERM_COLOR: always
|
||||
RUSTUP_MAX_RETRIES: 10
|
||||
|
||||
jobs:
|
||||
ruff_wasm:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -29,31 +22,19 @@ jobs:
|
||||
target: [web, bundler, nodejs]
|
||||
fail-fast: false
|
||||
steps:
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
- uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
|
||||
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: artifacts-wasm-${{ matrix.target }}
|
||||
path: pkg
|
||||
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
|
||||
with:
|
||||
node-version: 24
|
||||
registry-url: "https://registry.npmjs.org"
|
||||
- name: "Publish (dry-run)"
|
||||
if: ${{ inputs.plan == '' || fromJson(inputs.plan).announcement_tag_is_implicit }}
|
||||
run: npm publish --dry-run crates/ruff_wasm/pkg
|
||||
run: npm publish --dry-run pkg
|
||||
- name: "Publish"
|
||||
if: ${{ inputs.plan != '' && !fromJson(inputs.plan).announcement_tag_is_implicit }}
|
||||
run: npm publish --provenance --access public crates/ruff_wasm/pkg
|
||||
run: npm publish --provenance --access public pkg
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
|
||||
21
.github/workflows/release.yml
vendored
21
.github/workflows/release.yml
vendored
@@ -60,7 +60,7 @@ jobs:
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
steps:
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
@@ -112,18 +112,28 @@ jobs:
|
||||
"contents": "read"
|
||||
"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-global-artifacts:
|
||||
needs:
|
||||
- plan
|
||||
- custom-build-binaries
|
||||
- custom-build-docker
|
||||
- custom-build-wasm
|
||||
runs-on: "depot-ubuntu-latest-4"
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
BUILD_MANIFEST_NAME: target/distrib/global-dist-manifest.json
|
||||
steps:
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
@@ -165,16 +175,17 @@ jobs:
|
||||
- plan
|
||||
- custom-build-binaries
|
||||
- custom-build-docker
|
||||
- custom-build-wasm
|
||||
- build-global-artifacts
|
||||
# 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') }}
|
||||
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') }}
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
runs-on: "depot-ubuntu-latest-4"
|
||||
outputs:
|
||||
val: ${{ steps.host.outputs.manifest }}
|
||||
steps:
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
@@ -250,7 +261,7 @@ jobs:
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
steps:
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
|
||||
6
.github/workflows/sync_typeshed.yaml
vendored
6
.github/workflows/sync_typeshed.yaml
vendored
@@ -76,7 +76,7 @@ jobs:
|
||||
run: |
|
||||
git config --global user.name typeshedbot
|
||||
git config --global user.email '<>'
|
||||
- uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7.1.6
|
||||
- uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0
|
||||
- name: Sync typeshed stubs
|
||||
run: |
|
||||
rm -rf "ruff/${VENDORED_TYPESHED}"
|
||||
@@ -130,7 +130,7 @@ jobs:
|
||||
with:
|
||||
persist-credentials: true
|
||||
ref: ${{ env.UPSTREAM_BRANCH}}
|
||||
- uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7.1.6
|
||||
- uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0
|
||||
- name: Setup git
|
||||
run: |
|
||||
git config --global user.name typeshedbot
|
||||
@@ -169,7 +169,7 @@ jobs:
|
||||
with:
|
||||
persist-credentials: true
|
||||
ref: ${{ env.UPSTREAM_BRANCH}}
|
||||
- uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7.1.6
|
||||
- uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0
|
||||
- name: Setup git
|
||||
run: |
|
||||
git config --global user.name typeshedbot
|
||||
|
||||
6
.github/workflows/ty-ecosystem-analyzer.yaml
vendored
6
.github/workflows/ty-ecosystem-analyzer.yaml
vendored
@@ -38,14 +38,14 @@ jobs:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Install the latest version of uv
|
||||
uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7.1.6
|
||||
uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0
|
||||
with:
|
||||
enable-cache: true # zizmor: ignore[cache-poisoning] acceptable risk for CloudFlare pages artifact
|
||||
enable-cache: true
|
||||
|
||||
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
|
||||
with:
|
||||
workspaces: "ruff"
|
||||
lookup-only: false # zizmor: ignore[cache-poisoning] acceptable risk for CloudFlare pages artifact
|
||||
lookup-only: false
|
||||
|
||||
- name: Install Rust toolchain
|
||||
run: rustup show
|
||||
|
||||
2
.github/workflows/ty-ecosystem-report.yaml
vendored
2
.github/workflows/ty-ecosystem-report.yaml
vendored
@@ -32,7 +32,7 @@ jobs:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Install the latest version of uv
|
||||
uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7.1.6
|
||||
uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0
|
||||
with:
|
||||
enable-cache: true
|
||||
|
||||
|
||||
@@ -21,15 +21,61 @@ exclude: |
|
||||
)$
|
||||
|
||||
repos:
|
||||
# Priority 0: Read-only hooks; hooks that modify disjoint file types.
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v6.0.0
|
||||
hooks:
|
||||
- id: check-merge-conflict
|
||||
priority: 0
|
||||
|
||||
- repo: https://github.com/abravalheri/validate-pyproject
|
||||
rev: v0.24.1
|
||||
hooks:
|
||||
- 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
|
||||
rev: 1.0.0
|
||||
@@ -44,7 +90,20 @@ repos:
|
||||
docs/formatter/black\.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
|
||||
rev: v0.47.0
|
||||
hooks:
|
||||
@@ -54,7 +113,9 @@ repos:
|
||||
docs/formatter/black\.md
|
||||
| docs/\w+\.md
|
||||
)$
|
||||
priority: 1
|
||||
|
||||
# Priority 2: blacken-docs runs after markdownlint-fix (both modify markdown).
|
||||
- repo: https://github.com/adamchainz/blacken-docs
|
||||
rev: 1.20.0
|
||||
hooks:
|
||||
@@ -68,70 +129,26 @@ repos:
|
||||
)$
|
||||
additional_dependencies:
|
||||
- black==25.12.0
|
||||
|
||||
- repo: https://github.com/crate-ci/typos
|
||||
rev: v1.40.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.14.10
|
||||
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.7.4
|
||||
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.19.0
|
||||
hooks:
|
||||
- id: zizmor
|
||||
|
||||
- repo: https://github.com/python-jsonschema/check-jsonschema
|
||||
rev: 0.36.0
|
||||
hooks:
|
||||
- id: check-github-workflows
|
||||
priority: 2
|
||||
|
||||
# `actionlint` hook, for verifying correct syntax in GitHub Actions workflows.
|
||||
# Some additional configuration for `actionlint` can be found in `.github/actionlint.yaml`.
|
||||
- repo: https://github.com/rhysd/actionlint
|
||||
rev: v1.7.9
|
||||
rev: v1.7.10
|
||||
hooks:
|
||||
- id: actionlint
|
||||
stages:
|
||||
# This hook is disabled by default, since it's quite slow.
|
||||
# To run all hooks *including* this hook, use `uvx pre-commit run -a --hook-stage=manual`.
|
||||
# To run *just* this hook, use `uvx pre-commit run -a actionlint --hook-stage=manual`.
|
||||
# To run all hooks *including* this hook, use `uvx prek run -a --hook-stage=manual`.
|
||||
# To run *just* this hook, use `uvx prek run -a actionlint --hook-stage=manual`.
|
||||
- manual
|
||||
args:
|
||||
- "-ignore=SC2129" # ignorable stylistic lint from shellcheck
|
||||
- "-ignore=SC2016" # another shellcheck lint: seems to have false positives?
|
||||
language: golang # means renovate will also update `additional_dependencies`
|
||||
additional_dependencies:
|
||||
# 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,
|
||||
# but the integration only works if shellcheck is installed
|
||||
- "github.com/wasilibs/go-shellcheck/cmd/shellcheck@v0.11.1"
|
||||
|
||||
- repo: https://github.com/shellcheck-py/shellcheck-py
|
||||
rev: v0.11.0.1
|
||||
hooks:
|
||||
- id: shellcheck
|
||||
priority: 0
|
||||
|
||||
58
CHANGELOG.md
58
CHANGELOG.md
@@ -1,5 +1,63 @@
|
||||
# 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.
|
||||
|
||||
@@ -10,6 +10,12 @@ Run all tests (using `nextest` for faster execution):
|
||||
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
|
||||
@@ -59,6 +65,7 @@ When working on ty, PR titles should start with `[ty]` and be tagged with the `t
|
||||
- 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 pre-commit run -a` at the end of a task.
|
||||
- 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.
|
||||
|
||||
@@ -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
|
||||
run Python utility commands.
|
||||
|
||||
You can optionally install pre-commit hooks to automatically run the validation checks
|
||||
You can optionally install hooks to automatically run the validation checks
|
||||
when making a commit:
|
||||
|
||||
```shell
|
||||
uv tool install pre-commit
|
||||
pre-commit install
|
||||
uv tool install prek
|
||||
prek install
|
||||
```
|
||||
|
||||
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
|
||||
cargo clippy --workspace --all-targets --all-features -- -D warnings # Rust linting
|
||||
RUFF_UPDATE_SCHEMA=1 cargo test # Rust testing and updating ruff.schema.json
|
||||
uvx pre-commit run --all-files --show-diff-on-failure # Rust and Python formatting, Markdown and Python linting, etc.
|
||||
uvx prek run -a # 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
|
||||
@@ -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
|
||||
- Changes should be edited to be user-facing descriptions, avoiding internal details
|
||||
- Square brackets (eg, `[ruff]` project name) will be automatically escaped by `pre-commit`
|
||||
- Square brackets (eg, `[ruff]` project name) will be automatically escaped by `prek`
|
||||
|
||||
Additionally, for minor releases:
|
||||
|
||||
|
||||
72
Cargo.lock
generated
72
Cargo.lock
generated
@@ -466,9 +466,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.53"
|
||||
version = "4.5.54"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c9e340e012a1bf4935f5282ed1436d1489548e8f72308207ea5df0e23d2d03f8"
|
||||
checksum = "c6e6ff9dcd79cff5cd969a17a545d79e84ab086e444102a591e288a8aa3ce394"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
@@ -476,9 +476,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.53"
|
||||
version = "4.5.54"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d76b5d13eaa18c901fd2f7fca939fefe3a0727a953561fefdf3b2922b8569d00"
|
||||
checksum = "fa42cf4d2b7a41bc8f663a7cab4031ebafa1bf3875705bfaf8466dc60ab52c00"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
@@ -1583,11 +1583,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "imperative"
|
||||
version = "1.0.6"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29a1f6526af721f9aec9ceed7ab8ebfca47f3399d08b80056c2acca3fcb694a9"
|
||||
checksum = "35e1d0bd9c575c52e59aad8e122a11786e852a154678d0c86e9e243d55273970"
|
||||
dependencies = [
|
||||
"phf",
|
||||
"phf 0.13.1",
|
||||
"rust-stemmers",
|
||||
]
|
||||
|
||||
@@ -1648,9 +1648,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "insta"
|
||||
version = "1.45.1"
|
||||
version = "1.46.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "983e3b24350c84ab8a65151f537d67afbbf7153bb9f1110e03e9fa9b07f67a5c"
|
||||
checksum = "1b66886d14d18d420ab5052cbff544fc5d34d0b2cdd35eb5976aaa10a4a472e5"
|
||||
dependencies = [
|
||||
"console 0.15.11",
|
||||
"once_cell",
|
||||
@@ -1874,9 +1874,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.178"
|
||||
version = "0.2.179"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091"
|
||||
checksum = "c5a2d376baa530d1238d133232d15e239abad80d05838b4b59354e5268af431f"
|
||||
|
||||
[[package]]
|
||||
name = "libcst"
|
||||
@@ -2488,7 +2488,17 @@ version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078"
|
||||
dependencies = [
|
||||
"phf_shared",
|
||||
"phf_shared 0.11.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf"
|
||||
dependencies = [
|
||||
"phf_shared 0.13.1",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2498,7 +2508,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a"
|
||||
dependencies = [
|
||||
"phf_generator",
|
||||
"phf_shared",
|
||||
"phf_shared 0.11.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2507,7 +2517,7 @@ version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d"
|
||||
dependencies = [
|
||||
"phf_shared",
|
||||
"phf_shared 0.11.3",
|
||||
"rand 0.8.5",
|
||||
]
|
||||
|
||||
@@ -2520,6 +2530,15 @@ dependencies = [
|
||||
"siphasher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_shared"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266"
|
||||
dependencies = [
|
||||
"siphasher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.16"
|
||||
@@ -2912,7 +2931,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.14.10"
|
||||
version = "0.14.11"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"argfile",
|
||||
@@ -2928,6 +2947,7 @@ dependencies = [
|
||||
"filetime",
|
||||
"globwalk",
|
||||
"ignore",
|
||||
"indexmap",
|
||||
"indoc",
|
||||
"insta",
|
||||
"insta-cmd",
|
||||
@@ -3171,7 +3191,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff_linter"
|
||||
version = "0.14.10"
|
||||
version = "0.14.11"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"anyhow",
|
||||
@@ -3285,7 +3305,6 @@ dependencies = [
|
||||
"compact_str",
|
||||
"get-size2",
|
||||
"is-macro",
|
||||
"itertools 0.14.0",
|
||||
"memchr",
|
||||
"ruff_cache",
|
||||
"ruff_macros",
|
||||
@@ -3529,7 +3548,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff_wasm"
|
||||
version = "0.14.10"
|
||||
version = "0.14.11"
|
||||
dependencies = [
|
||||
"console_error_panic_hook",
|
||||
"console_log",
|
||||
@@ -3645,7 +3664,7 @@ checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
|
||||
[[package]]
|
||||
name = "salsa"
|
||||
version = "0.25.2"
|
||||
source = "git+https://github.com/salsa-rs/salsa.git?rev=309c249088fdeef0129606fa34ec2eefc74736ff#309c249088fdeef0129606fa34ec2eefc74736ff"
|
||||
source = "git+https://github.com/salsa-rs/salsa.git?rev=9860ff6ca0f1f8f3a8d6b832020002790b501254#9860ff6ca0f1f8f3a8d6b832020002790b501254"
|
||||
dependencies = [
|
||||
"boxcar",
|
||||
"compact_str",
|
||||
@@ -3670,12 +3689,12 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "salsa-macro-rules"
|
||||
version = "0.25.2"
|
||||
source = "git+https://github.com/salsa-rs/salsa.git?rev=309c249088fdeef0129606fa34ec2eefc74736ff#309c249088fdeef0129606fa34ec2eefc74736ff"
|
||||
source = "git+https://github.com/salsa-rs/salsa.git?rev=9860ff6ca0f1f8f3a8d6b832020002790b501254#9860ff6ca0f1f8f3a8d6b832020002790b501254"
|
||||
|
||||
[[package]]
|
||||
name = "salsa-macros"
|
||||
version = "0.25.2"
|
||||
source = "git+https://github.com/salsa-rs/salsa.git?rev=309c249088fdeef0129606fa34ec2eefc74736ff#309c249088fdeef0129606fa34ec2eefc74736ff"
|
||||
source = "git+https://github.com/salsa-rs/salsa.git?rev=9860ff6ca0f1f8f3a8d6b832020002790b501254#9860ff6ca0f1f8f3a8d6b832020002790b501254"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -3993,9 +4012,9 @@ checksum = "e396b6523b11ccb83120b115a0b7366de372751aa6edf19844dfb13a6af97e91"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.111"
|
||||
version = "2.0.113"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87"
|
||||
checksum = "678faa00651c9eb72dd2020cbdf275d92eccb2400d568e419efdd64838145cb4"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -4059,7 +4078,7 @@ checksum = "d4ea810f0692f9f51b382fff5893887bb4580f5fa246fde546e0b13e7fcee662"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"nom",
|
||||
"phf",
|
||||
"phf 0.11.3",
|
||||
"phf_codegen",
|
||||
]
|
||||
|
||||
@@ -4443,6 +4462,7 @@ version = "0.0.0"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"camino",
|
||||
"compact_str",
|
||||
"get-size2",
|
||||
"insta",
|
||||
"itertools 0.14.0",
|
||||
@@ -4511,11 +4531,13 @@ dependencies = [
|
||||
"regex-automata",
|
||||
"ruff_cache",
|
||||
"ruff_db",
|
||||
"ruff_diagnostics",
|
||||
"ruff_macros",
|
||||
"ruff_memory_usage",
|
||||
"ruff_options_metadata",
|
||||
"ruff_python_ast",
|
||||
"ruff_python_formatter",
|
||||
"ruff_python_trivia",
|
||||
"ruff_text_size",
|
||||
"rustc-hash",
|
||||
"salsa",
|
||||
@@ -4804,7 +4826,7 @@ version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d1673eca9782c84de5f81b82e4109dcfb3611c8ba0d52930ec4a9478f547b2dd"
|
||||
dependencies = [
|
||||
"phf",
|
||||
"phf 0.11.3",
|
||||
"unicode_names2_generator",
|
||||
]
|
||||
|
||||
|
||||
@@ -150,7 +150,7 @@ regex-automata = { version = "0.4.9" }
|
||||
rustc-hash = { version = "2.0.0" }
|
||||
rustc-stable-hash = { version = "0.1.2" }
|
||||
# When updating salsa, make sure to also update the revision in `fuzz/Cargo.toml`
|
||||
salsa = { git = "https://github.com/salsa-rs/salsa.git", rev = "309c249088fdeef0129606fa34ec2eefc74736ff", default-features = false, features = [
|
||||
salsa = { git = "https://github.com/salsa-rs/salsa.git", rev = "9860ff6ca0f1f8f3a8d6b832020002790b501254", default-features = false, features = [
|
||||
"compact_str",
|
||||
"macros",
|
||||
"salsa_unstable",
|
||||
@@ -335,6 +335,11 @@ strip = false
|
||||
debug = "full"
|
||||
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.
|
||||
[profile.dist]
|
||||
inherits = "release"
|
||||
|
||||
@@ -150,8 +150,8 @@ curl -LsSf https://astral.sh/ruff/install.sh | sh
|
||||
powershell -c "irm https://astral.sh/ruff/install.ps1 | iex"
|
||||
|
||||
# For a specific version.
|
||||
curl -LsSf https://astral.sh/ruff/0.14.10/install.sh | sh
|
||||
powershell -c "irm https://astral.sh/ruff/0.14.10/install.ps1 | iex"
|
||||
curl -LsSf https://astral.sh/ruff/0.14.11/install.sh | sh
|
||||
powershell -c "irm https://astral.sh/ruff/0.14.11/install.ps1 | iex"
|
||||
```
|
||||
|
||||
You can also install Ruff via [Homebrew](https://formulae.brew.sh/formula/ruff), [Conda](https://anaconda.org/conda-forge/ruff),
|
||||
@@ -184,7 +184,7 @@ Ruff can also be used as a [pre-commit](https://pre-commit.com/) hook via [`ruff
|
||||
```yaml
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
# Ruff version.
|
||||
rev: v0.14.10
|
||||
rev: v0.14.11
|
||||
hooks:
|
||||
# Run the linter.
|
||||
- id: ruff-check
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ruff"
|
||||
version = "0.14.10"
|
||||
version = "0.14.11"
|
||||
publish = true
|
||||
authors = { workspace = true }
|
||||
edition = { workspace = true }
|
||||
@@ -48,6 +48,7 @@ colored = { workspace = true }
|
||||
filetime = { workspace = true }
|
||||
globwalk = { workspace = true }
|
||||
ignore = { workspace = true }
|
||||
indexmap = { workspace = true }
|
||||
is-macro = { workspace = true }
|
||||
itertools = { workspace = true }
|
||||
jiff = { workspace = true }
|
||||
|
||||
@@ -2,6 +2,7 @@ use crate::args::{AnalyzeGraphArgs, ConfigArguments};
|
||||
use crate::resolve::resolve;
|
||||
use crate::{ExitStatus, resolve_default_files};
|
||||
use anyhow::Result;
|
||||
use indexmap::IndexSet;
|
||||
use log::{debug, warn};
|
||||
use path_absolutize::CWD;
|
||||
use ruff_db::system::{SystemPath, SystemPathBuf};
|
||||
@@ -11,7 +12,7 @@ use ruff_linter::source_kind::SourceKind;
|
||||
use ruff_linter::{warn_user, warn_user_once};
|
||||
use ruff_python_ast::{PySourceType, SourceType};
|
||||
use ruff_workspace::resolver::{ResolvedFile, match_exclusion, python_files_in_path};
|
||||
use rustc_hash::FxHashMap;
|
||||
use rustc_hash::{FxBuildHasher, FxHashMap};
|
||||
use std::io::Write;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::{Arc, Mutex};
|
||||
@@ -59,17 +60,34 @@ pub(crate) fn analyze_graph(
|
||||
})
|
||||
.collect::<FxHashMap<_, _>>();
|
||||
|
||||
// Create a database from the source roots.
|
||||
let src_roots = package_roots
|
||||
.values()
|
||||
.filter_map(|package| package.as_deref())
|
||||
.filter_map(|package| package.parent())
|
||||
.map(Path::to_path_buf)
|
||||
.filter_map(|path| SystemPathBuf::from_path_buf(path).ok())
|
||||
.collect();
|
||||
// Create a database from the source roots, combining configured `src` paths with detected
|
||||
// package roots. Configured paths are added first so they take precedence, and duplicates
|
||||
// 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()
|
||||
.filter_map(|package| package.as_deref())
|
||||
.filter_map(|path| path.parent())
|
||||
.filter_map(|path| SystemPathBuf::from_path_buf(path.to_path_buf()).ok()),
|
||||
);
|
||||
|
||||
let db = ModuleDb::from_src_roots(
|
||||
src_roots,
|
||||
src_roots.into_iter().collect(),
|
||||
pyproject_config
|
||||
.settings
|
||||
.analyze
|
||||
|
||||
@@ -1305,7 +1305,7 @@ mod tests {
|
||||
settings.add_filter(r"(Panicked at) [^:]+:\d+:\d+", "$1 <location>");
|
||||
let _s = settings.bind_to_scope();
|
||||
|
||||
assert_snapshot!(str::from_utf8(&buf)?, @r"
|
||||
assert_snapshot!(str::from_utf8(&buf)?, @"
|
||||
io: test.py: Permission denied
|
||||
--> test.py:1:1
|
||||
|
||||
|
||||
@@ -29,10 +29,10 @@ pub(crate) fn show_settings(
|
||||
bail!("No files found under the given path");
|
||||
};
|
||||
|
||||
let settings = resolver.resolve(&path);
|
||||
let (settings, config_path) = resolver.resolve_with_path(&path);
|
||||
|
||||
writeln!(writer, "Resolved settings for: \"{}\"", path.display())?;
|
||||
if let Some(settings_path) = pyproject_config.path.as_ref() {
|
||||
if let Some(settings_path) = config_path {
|
||||
writeln!(writer, "Settings path: \"{}\"", settings_path.display())?;
|
||||
}
|
||||
write!(writer, "{settings}")?;
|
||||
|
||||
@@ -4,4 +4,3 @@ source: crates/ruff/src/commands/check.rs
|
||||
/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/pyproject.toml:1:1: E902 Permission denied (os error 13)
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
---
|
||||
source: crates/ruff/src/version.rs
|
||||
expression: version
|
||||
snapshot_kind: text
|
||||
---
|
||||
0.0.0
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
---
|
||||
source: crates/ruff/src/version.rs
|
||||
expression: version
|
||||
snapshot_kind: text
|
||||
---
|
||||
0.0.0 (53b0f5d92 2023-10-19)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
---
|
||||
source: crates/ruff/src/version.rs
|
||||
expression: version
|
||||
snapshot_kind: text
|
||||
---
|
||||
0.0.0+24 (53b0f5d92 2023-10-19)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
---
|
||||
source: crates/ruff/src/version.rs
|
||||
expression: version
|
||||
snapshot_kind: text
|
||||
---
|
||||
{
|
||||
"version": "0.0.0",
|
||||
|
||||
@@ -132,29 +132,29 @@ fn dependents() -> Result<()> {
|
||||
insta::with_settings!({
|
||||
filters => INSTA_FILTERS.to_vec(),
|
||||
}, {
|
||||
assert_cmd_snapshot!(command().arg("--direction").arg("dependents").current_dir(&root), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
{
|
||||
"ruff/__init__.py": [],
|
||||
"ruff/a.py": [],
|
||||
"ruff/b.py": [
|
||||
"ruff/a.py"
|
||||
],
|
||||
"ruff/c.py": [
|
||||
"ruff/b.py"
|
||||
],
|
||||
"ruff/d.py": [
|
||||
"ruff/c.py"
|
||||
],
|
||||
"ruff/e.py": [
|
||||
"ruff/d.py"
|
||||
]
|
||||
}
|
||||
assert_cmd_snapshot!(command().arg("--direction").arg("dependents").current_dir(&root), @r#"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
{
|
||||
"ruff/__init__.py": [],
|
||||
"ruff/a.py": [],
|
||||
"ruff/b.py": [
|
||||
"ruff/a.py"
|
||||
],
|
||||
"ruff/c.py": [
|
||||
"ruff/b.py"
|
||||
],
|
||||
"ruff/d.py": [
|
||||
"ruff/c.py"
|
||||
],
|
||||
"ruff/e.py": [
|
||||
"ruff/d.py"
|
||||
]
|
||||
}
|
||||
|
||||
----- stderr -----
|
||||
"###);
|
||||
----- stderr -----
|
||||
"#);
|
||||
});
|
||||
|
||||
Ok(())
|
||||
@@ -184,21 +184,21 @@ fn string_detection() -> Result<()> {
|
||||
insta::with_settings!({
|
||||
filters => INSTA_FILTERS.to_vec(),
|
||||
}, {
|
||||
assert_cmd_snapshot!(command().current_dir(&root), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
{
|
||||
"ruff/__init__.py": [],
|
||||
"ruff/a.py": [
|
||||
"ruff/b.py"
|
||||
],
|
||||
"ruff/b.py": [],
|
||||
"ruff/c.py": []
|
||||
}
|
||||
assert_cmd_snapshot!(command().current_dir(&root), @r#"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
{
|
||||
"ruff/__init__.py": [],
|
||||
"ruff/a.py": [
|
||||
"ruff/b.py"
|
||||
],
|
||||
"ruff/b.py": [],
|
||||
"ruff/c.py": []
|
||||
}
|
||||
|
||||
----- stderr -----
|
||||
"###);
|
||||
----- stderr -----
|
||||
"#);
|
||||
});
|
||||
|
||||
insta::with_settings!({
|
||||
@@ -319,7 +319,7 @@ fn globs() -> Result<()> {
|
||||
insta::with_settings!({
|
||||
filters => INSTA_FILTERS.to_vec(),
|
||||
}, {
|
||||
assert_cmd_snapshot!(command().current_dir(&root), @r###"
|
||||
assert_cmd_snapshot!(command().current_dir(&root), @r#"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -340,7 +340,7 @@ fn globs() -> Result<()> {
|
||||
}
|
||||
|
||||
----- stderr -----
|
||||
"###);
|
||||
"#);
|
||||
});
|
||||
|
||||
Ok(())
|
||||
@@ -368,7 +368,7 @@ fn exclude() -> Result<()> {
|
||||
insta::with_settings!({
|
||||
filters => INSTA_FILTERS.to_vec(),
|
||||
}, {
|
||||
assert_cmd_snapshot!(command().current_dir(&root), @r###"
|
||||
assert_cmd_snapshot!(command().current_dir(&root), @r#"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -381,7 +381,7 @@ fn exclude() -> Result<()> {
|
||||
}
|
||||
|
||||
----- stderr -----
|
||||
"###);
|
||||
"#);
|
||||
});
|
||||
|
||||
Ok(())
|
||||
@@ -421,7 +421,7 @@ fn wildcard() -> Result<()> {
|
||||
insta::with_settings!({
|
||||
filters => INSTA_FILTERS.to_vec(),
|
||||
}, {
|
||||
assert_cmd_snapshot!(command().current_dir(&root), @r###"
|
||||
assert_cmd_snapshot!(command().current_dir(&root), @r#"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -443,7 +443,7 @@ fn wildcard() -> Result<()> {
|
||||
}
|
||||
|
||||
----- stderr -----
|
||||
"###);
|
||||
"#);
|
||||
});
|
||||
|
||||
Ok(())
|
||||
@@ -639,7 +639,7 @@ fn venv() -> Result<()> {
|
||||
}, {
|
||||
assert_cmd_snapshot!(
|
||||
command().args(["--python", "none"]).arg("packages/albatross").current_dir(&root),
|
||||
@r"
|
||||
@"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
@@ -695,7 +695,7 @@ fn notebook_basic() -> Result<()> {
|
||||
insta::with_settings!({
|
||||
filters => INSTA_FILTERS.to_vec(),
|
||||
}, {
|
||||
assert_cmd_snapshot!(command().current_dir(&root), @r###"
|
||||
assert_cmd_snapshot!(command().current_dir(&root), @r#"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -708,7 +708,122 @@ fn notebook_basic() -> Result<()> {
|
||||
}
|
||||
|
||||
----- 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(())
|
||||
@@ -765,7 +880,7 @@ fn notebook_with_magic() -> Result<()> {
|
||||
insta::with_settings!({
|
||||
filters => INSTA_FILTERS.to_vec(),
|
||||
}, {
|
||||
assert_cmd_snapshot!(command().current_dir(&root), @r###"
|
||||
assert_cmd_snapshot!(command().current_dir(&root), @r#"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -778,7 +893,7 @@ fn notebook_with_magic() -> Result<()> {
|
||||
}
|
||||
|
||||
----- stderr -----
|
||||
"###);
|
||||
"#);
|
||||
});
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -29,7 +29,7 @@ fn type_checking_imports() -> anyhow::Result<()> {
|
||||
("ruff/c.py", ""),
|
||||
])?;
|
||||
|
||||
assert_cmd_snapshot!(test.command(), @r###"
|
||||
assert_cmd_snapshot!(test.command(), @r#"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -46,12 +46,12 @@ fn type_checking_imports() -> anyhow::Result<()> {
|
||||
}
|
||||
|
||||
----- stderr -----
|
||||
"###);
|
||||
"#);
|
||||
|
||||
assert_cmd_snapshot!(
|
||||
test.command()
|
||||
.arg("--no-type-checking-imports"),
|
||||
@r###"
|
||||
@r#"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -65,7 +65,7 @@ fn type_checking_imports() -> anyhow::Result<()> {
|
||||
}
|
||||
|
||||
----- stderr -----
|
||||
"###
|
||||
"#
|
||||
);
|
||||
|
||||
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
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -117,7 +117,7 @@ fn type_checking_imports_from_config() -> anyhow::Result<()> {
|
||||
}
|
||||
|
||||
----- stderr -----
|
||||
"###);
|
||||
"#);
|
||||
|
||||
test.write_file(
|
||||
"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
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -144,7 +144,7 @@ fn type_checking_imports_from_config() -> anyhow::Result<()> {
|
||||
}
|
||||
|
||||
----- stderr -----
|
||||
"###
|
||||
"#
|
||||
);
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -51,7 +51,7 @@ fn default_files() -> Result<()> {
|
||||
|
||||
assert_cmd_snapshot!(test.format_command()
|
||||
.arg("--isolated")
|
||||
.arg("--check"), @r"
|
||||
.arg("--check"), @"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -71,7 +71,7 @@ fn format_warn_stdin_filename_with_files() -> Result<()> {
|
||||
assert_cmd_snapshot!(test.format_command()
|
||||
.args(["--isolated", "--stdin-filename", "foo.py"])
|
||||
.arg("foo.py")
|
||||
.pass_stdin("foo = 1"), @r"
|
||||
.pass_stdin("foo = 1"), @"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -87,7 +87,7 @@ fn format_warn_stdin_filename_with_files() -> Result<()> {
|
||||
fn nonexistent_config_file() -> Result<()> {
|
||||
let test = CliTest::new()?;
|
||||
assert_cmd_snapshot!(test.format_command()
|
||||
.args(["--config", "foo.toml", "."]), @r"
|
||||
.args(["--config", "foo.toml", "."]), @"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
@@ -111,7 +111,7 @@ fn nonexistent_config_file() -> Result<()> {
|
||||
fn config_override_rejected_if_invalid_toml() -> Result<()> {
|
||||
let test = CliTest::new()?;
|
||||
assert_cmd_snapshot!(test.format_command()
|
||||
.args(["--config", "foo = bar", "."]), @r"
|
||||
.args(["--config", "foo = bar", "."]), @"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
@@ -145,7 +145,7 @@ fn too_many_config_files() -> Result<()> {
|
||||
.arg("ruff.toml")
|
||||
.arg("--config")
|
||||
.arg("ruff2.toml")
|
||||
.arg("."), @r"
|
||||
.arg("."), @"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
@@ -168,7 +168,7 @@ fn config_file_and_isolated() -> Result<()> {
|
||||
.arg("--isolated")
|
||||
.arg("--config")
|
||||
.arg("ruff.toml")
|
||||
.arg("."), @r"
|
||||
.arg("."), @"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
@@ -390,7 +390,7 @@ fn mixed_line_endings() -> Result<()> {
|
||||
assert_cmd_snapshot!(test.format_command()
|
||||
.arg("--diff")
|
||||
.arg("--isolated")
|
||||
.arg("."), @r"
|
||||
.arg("."), @"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -446,7 +446,7 @@ OTHER = "OTHER"
|
||||
// Explicitly pass test.py, should be formatted regardless of it being excluded by format.exclude
|
||||
.arg("test.py")
|
||||
// Format all other files in the directory, should respect the `exclude` and `format.exclude` options
|
||||
.arg("."), @r"
|
||||
.arg("."), @"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -469,7 +469,7 @@ fn deduplicate_directory_and_explicit_file() -> Result<()> {
|
||||
.arg("--check")
|
||||
.arg(".")
|
||||
.arg("main.py"),
|
||||
@r"
|
||||
@"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -495,7 +495,7 @@ from module import =
|
||||
assert_cmd_snapshot!(test.format_command()
|
||||
.arg("--check")
|
||||
.arg("--isolated")
|
||||
.arg("main.py"), @r"
|
||||
.arg("main.py"), @"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
@@ -522,7 +522,7 @@ if __name__ == "__main__":
|
||||
assert_cmd_snapshot!(test.format_command()
|
||||
.arg("--isolated")
|
||||
.arg("--check")
|
||||
.arg("main.py"), @r"
|
||||
.arg("main.py"), @"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -534,7 +534,7 @@ if __name__ == "__main__":
|
||||
|
||||
assert_cmd_snapshot!(test.format_command()
|
||||
.arg("--isolated")
|
||||
.arg("main.py"), @r"
|
||||
.arg("main.py"), @"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -545,7 +545,7 @@ if __name__ == "__main__":
|
||||
|
||||
assert_cmd_snapshot!(test.format_command()
|
||||
.arg("--isolated")
|
||||
.arg("main.py"), @r"
|
||||
.arg("main.py"), @"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -614,7 +614,7 @@ fn output_format_notebook() -> Result<()> {
|
||||
|
||||
assert_cmd_snapshot!(
|
||||
test.format_command().args(["--isolated", "--preview", "--check"]).arg(path),
|
||||
@r"
|
||||
@"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -672,7 +672,7 @@ if __name__ == "__main__":
|
||||
assert_cmd_snapshot!(test.format_command()
|
||||
.arg("--isolated")
|
||||
.arg("--exit-non-zero-on-format")
|
||||
.arg("main.py"), @r"
|
||||
.arg("main.py"), @"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -685,7 +685,7 @@ if __name__ == "__main__":
|
||||
assert_cmd_snapshot!(test.format_command()
|
||||
.arg("--isolated")
|
||||
.arg("--exit-non-zero-on-format")
|
||||
.arg("main.py"), @r"
|
||||
.arg("main.py"), @"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -701,7 +701,7 @@ if __name__ == "__main__":
|
||||
assert_cmd_snapshot!(test.format_command()
|
||||
.arg("--isolated")
|
||||
.arg("--exit-non-zero-on-fix")
|
||||
.arg("main.py"), @r"
|
||||
.arg("main.py"), @"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -714,7 +714,7 @@ if __name__ == "__main__":
|
||||
assert_cmd_snapshot!(test.format_command()
|
||||
.arg("--isolated")
|
||||
.arg("--exit-non-zero-on-fix")
|
||||
.arg("main.py"), @r"
|
||||
.arg("main.py"), @"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -771,7 +771,7 @@ OTHER = "OTHER"
|
||||
// Explicitly pass test.py, should not be formatted because of --force-exclude
|
||||
.arg("test.py")
|
||||
// Format all other files in the directory, should respect the `exclude` and `format.exclude` options
|
||||
.arg("."), @r"
|
||||
.arg("."), @"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -931,7 +931,7 @@ tab-size = 2
|
||||
.pass_stdin(r"
|
||||
if True:
|
||||
pass
|
||||
"), @r"
|
||||
"), @"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
@@ -1144,7 +1144,7 @@ def say_hy(name: str):
|
||||
assert_cmd_snapshot!(test.format_command()
|
||||
.arg("--config")
|
||||
.arg("ruff.toml")
|
||||
.arg("test.py"), @r"
|
||||
.arg("test.py"), @"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -1184,7 +1184,7 @@ def say_hy(name: str):
|
||||
assert_cmd_snapshot!(test.format_command()
|
||||
.arg("--config")
|
||||
.arg("ruff.toml")
|
||||
.arg("test.py"), @r"
|
||||
.arg("test.py"), @"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -1216,7 +1216,7 @@ def say_hy(name: str):
|
||||
assert_cmd_snapshot!(test.format_command()
|
||||
.arg("--config")
|
||||
.arg("ruff.toml")
|
||||
.arg("test.py"), @r"
|
||||
.arg("test.py"), @"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -1246,7 +1246,7 @@ fn test_diff() -> Result<()> {
|
||||
|
||||
assert_cmd_snapshot!(
|
||||
test.format_command().args(["--isolated", "--diff"]).args(paths),
|
||||
@r"
|
||||
@"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -1311,7 +1311,7 @@ fn test_diff_no_change() -> Result<()> {
|
||||
let paths = [fixtures.join("unformatted.py")];
|
||||
assert_cmd_snapshot!(
|
||||
test.format_command().args(["--isolated", "--diff"]).args(paths),
|
||||
@r"
|
||||
@"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -1341,7 +1341,7 @@ fn test_diff_stdin_unformatted() -> Result<()> {
|
||||
test.format_command()
|
||||
.args(["--isolated", "--diff", "-", "--stdin-filename", "unformatted.py"])
|
||||
.pass_stdin(unformatted),
|
||||
@r"
|
||||
@"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -1366,7 +1366,7 @@ fn test_diff_stdin_formatted() -> Result<()> {
|
||||
let unformatted = fs::read(fixtures.join("formatted.py")).unwrap();
|
||||
assert_cmd_snapshot!(
|
||||
test.format_command().args(["--isolated", "--diff", "-"]).pass_stdin(unformatted),
|
||||
@r"
|
||||
@"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -1873,7 +1873,7 @@ include = ["*.ipy"]
|
||||
assert_cmd_snapshot!(test.format_command()
|
||||
.args(["--config", "ruff.toml"])
|
||||
.args(["--extension", "ipy:ipynb"])
|
||||
.arg("."), @r"
|
||||
.arg("."), @"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
@@ -1938,7 +1938,7 @@ include = ["*.ipy"]
|
||||
assert_cmd_snapshot!(test.format_command()
|
||||
.args(["--config", "ruff.toml"])
|
||||
.args(["--extension", "ipy:ipynb"])
|
||||
.arg("."), @r"
|
||||
.arg("."), @"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -2021,7 +2021,7 @@ def file2(arg1, arg2,):
|
||||
assert_cmd_snapshot!(test.format_command()
|
||||
.args(["--isolated", "--range=1:8-1:15"])
|
||||
.arg("file1.py")
|
||||
.arg("file2.py"), @r"
|
||||
.arg("file2.py"), @"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
@@ -2068,7 +2068,7 @@ fn range_start_larger_than_end() -> Result<()> {
|
||||
def foo(arg1, arg2,):
|
||||
print("Shouldn't format this" )
|
||||
|
||||
"#), @r"
|
||||
"#), @"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
@@ -2168,7 +2168,7 @@ fn range_missing_line() -> Result<()> {
|
||||
def foo(arg1, arg2,):
|
||||
print("Should format this" )
|
||||
|
||||
"#), @r"
|
||||
"#), @"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
@@ -2192,7 +2192,7 @@ fn zero_line_number() -> Result<()> {
|
||||
def foo(arg1, arg2,):
|
||||
print("Should format this" )
|
||||
|
||||
"#), @r"
|
||||
"#), @"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
@@ -2217,7 +2217,7 @@ fn column_and_line_zero() -> Result<()> {
|
||||
def foo(arg1, arg2,):
|
||||
print("Should format this" )
|
||||
|
||||
"#), @r"
|
||||
"#), @"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
@@ -2274,7 +2274,7 @@ fn range_formatting_notebook() -> Result<()> {
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
"#), @r"
|
||||
"#), @"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
@@ -2355,7 +2355,7 @@ fn cookiecutter_globbing() -> Result<()> {
|
||||
])?;
|
||||
|
||||
assert_cmd_snapshot!(test.format_command()
|
||||
.args(["--isolated", "--diff", "."]), @r"
|
||||
.args(["--isolated", "--diff", "."]), @"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -2374,7 +2374,7 @@ fn stable_output_format_warning() -> Result<()> {
|
||||
test.format_command()
|
||||
.args(["--output-format=full", "-"])
|
||||
.pass_stdin(""),
|
||||
@r"
|
||||
@"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
---
|
||||
source: crates/ruff/tests/lint.rs
|
||||
source: crates/ruff/tests/cli/lint.rs
|
||||
info:
|
||||
program: ruff
|
||||
args:
|
||||
@@ -17,7 +17,6 @@ info:
|
||||
- "--fix"
|
||||
- "-"
|
||||
stdin: "1"
|
||||
snapshot_kind: text
|
||||
---
|
||||
success: false
|
||||
exit_code: 2
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
source: crates/ruff/tests/lint.rs
|
||||
source: crates/ruff/tests/cli/lint.rs
|
||||
info:
|
||||
program: ruff
|
||||
args:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
source: crates/ruff/tests/lint.rs
|
||||
source: crates/ruff/tests/cli/lint.rs
|
||||
info:
|
||||
program: ruff
|
||||
args:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
source: crates/ruff/tests/lint.rs
|
||||
source: crates/ruff/tests/cli/lint.rs
|
||||
info:
|
||||
program: ruff
|
||||
args:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
source: crates/ruff/tests/lint.rs
|
||||
source: crates/ruff/tests/cli/lint.rs
|
||||
info:
|
||||
program: ruff
|
||||
args:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
source: crates/ruff/tests/lint.rs
|
||||
source: crates/ruff/tests/cli/lint.rs
|
||||
info:
|
||||
program: ruff
|
||||
args:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
source: crates/ruff/tests/lint.rs
|
||||
source: crates/ruff/tests/cli/lint.rs
|
||||
info:
|
||||
program: ruff
|
||||
args:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
source: crates/ruff/tests/lint.rs
|
||||
source: crates/ruff/tests/cli/lint.rs
|
||||
info:
|
||||
program: ruff
|
||||
args:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
source: crates/ruff/tests/lint.rs
|
||||
source: crates/ruff/tests/cli/lint.rs
|
||||
info:
|
||||
program: ruff
|
||||
args:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
source: crates/ruff/tests/lint.rs
|
||||
source: crates/ruff/tests/cli/lint.rs
|
||||
info:
|
||||
program: ruff
|
||||
args:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
source: crates/ruff/tests/lint.rs
|
||||
source: crates/ruff/tests/cli/lint.rs
|
||||
info:
|
||||
program: ruff
|
||||
args:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
source: crates/ruff/tests/lint.rs
|
||||
source: crates/ruff/tests/cli/lint.rs
|
||||
info:
|
||||
program: ruff
|
||||
args:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
source: crates/ruff/tests/lint.rs
|
||||
source: crates/ruff/tests/cli/lint.rs
|
||||
info:
|
||||
program: ruff
|
||||
args:
|
||||
|
||||
@@ -12,7 +12,6 @@ info:
|
||||
- "--target-version"
|
||||
- py39
|
||||
- input.py
|
||||
snapshot_kind: text
|
||||
---
|
||||
success: false
|
||||
exit_code: 1
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
source: crates/ruff/tests/lint.rs
|
||||
source: crates/ruff/tests/cli/lint.rs
|
||||
info:
|
||||
program: ruff
|
||||
args:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
source: crates/ruff/tests/lint.rs
|
||||
source: crates/ruff/tests/cli/lint.rs
|
||||
info:
|
||||
program: ruff
|
||||
args:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
source: crates/ruff/tests/lint.rs
|
||||
source: crates/ruff/tests/cli/lint.rs
|
||||
info:
|
||||
program: ruff
|
||||
args:
|
||||
|
||||
@@ -16,6 +16,7 @@ success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
Resolved settings for: "[TMP]/foo/test.py"
|
||||
Settings path: "[TMP]/foo/pyproject.toml"
|
||||
|
||||
# General Settings
|
||||
cache_dir = "[TMP]/foo/.ruff_cache"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
source: crates/ruff/tests/lint.rs
|
||||
source: crates/ruff/tests/cli/lint.rs
|
||||
info:
|
||||
program: ruff
|
||||
args:
|
||||
|
||||
@@ -18,13 +18,13 @@ fn check_in_deleted_directory_errors() {
|
||||
set_current_dir(&temp_path).unwrap();
|
||||
drop(temp_dir);
|
||||
|
||||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)).arg("check"), @r###"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME)).arg("check"), @"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
ruff failed
|
||||
Cause: Working directory does not exist
|
||||
"###);
|
||||
----- stderr -----
|
||||
ruff failed
|
||||
Cause: Working directory does not exist
|
||||
");
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ impl<'a> RuffCheck<'a> {
|
||||
fn stdin_success() {
|
||||
let mut cmd = RuffCheck::default().args([]).build();
|
||||
assert_cmd_snapshot!(cmd
|
||||
.pass_stdin(""), @r"
|
||||
.pass_stdin(""), @"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -111,7 +111,7 @@ fn stdin_success() {
|
||||
fn stdin_error() {
|
||||
let mut cmd = RuffCheck::default().args([]).build();
|
||||
assert_cmd_snapshot!(cmd
|
||||
.pass_stdin("import os\n"), @r"
|
||||
.pass_stdin("import os\n"), @"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -136,7 +136,7 @@ fn stdin_filename() {
|
||||
.args(["--stdin-filename", "F401.py"])
|
||||
.build();
|
||||
assert_cmd_snapshot!(cmd
|
||||
.pass_stdin("import os\n"), @r"
|
||||
.pass_stdin("import os\n"), @"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -172,7 +172,7 @@ import bar # unused import
|
||||
)?;
|
||||
|
||||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||||
.args(["check", "--isolated", "--no-cache", "--select", "F401"]).current_dir(tempdir.path()), @r"
|
||||
.args(["check", "--isolated", "--no-cache", "--select", "F401"]).current_dir(tempdir.path()), @"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -208,7 +208,7 @@ fn check_warn_stdin_filename_with_files() {
|
||||
.filename("foo.py")
|
||||
.build();
|
||||
assert_cmd_snapshot!(cmd
|
||||
.pass_stdin("import os\n"), @r"
|
||||
.pass_stdin("import os\n"), @"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -235,7 +235,7 @@ fn stdin_source_type_py() {
|
||||
.args(["--stdin-filename", "TCH.py"])
|
||||
.build();
|
||||
assert_cmd_snapshot!(cmd
|
||||
.pass_stdin("import os\n"), @r"
|
||||
.pass_stdin("import os\n"), @"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -261,7 +261,7 @@ fn stdin_source_type_pyi() {
|
||||
.args(["--stdin-filename", "TCH.pyi", "--select", "TCH"])
|
||||
.build();
|
||||
assert_cmd_snapshot!(cmd
|
||||
.pass_stdin("import os\n"), @r"
|
||||
.pass_stdin("import os\n"), @"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -294,7 +294,7 @@ fn stdin_json() {
|
||||
fn stdin_fix_py() {
|
||||
let mut cmd = RuffCheck::default().args(["--fix"]).build();
|
||||
assert_cmd_snapshot!(cmd
|
||||
.pass_stdin("import os\nimport sys\n\nprint(sys.version)\n"), @r"
|
||||
.pass_stdin("import os\nimport sys\n\nprint(sys.version)\n"), @"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -572,7 +572,7 @@ fn stdin_override_parser_ipynb() {
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}"#), @r"
|
||||
}"#), @"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -610,7 +610,7 @@ fn stdin_override_parser_py() {
|
||||
])
|
||||
.build();
|
||||
assert_cmd_snapshot!(cmd
|
||||
.pass_stdin("import os\n"), @r"
|
||||
.pass_stdin("import os\n"), @"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -633,7 +633,7 @@ fn stdin_override_parser_py() {
|
||||
fn stdin_fix_when_not_fixable_should_still_print_contents() {
|
||||
let mut cmd = RuffCheck::default().args(["--fix"]).build();
|
||||
assert_cmd_snapshot!(cmd
|
||||
.pass_stdin("import os\nimport sys\n\nif (1, 2):\n print(sys.version)\n"), @r###"
|
||||
.pass_stdin("import os\nimport sys\n\nif (1, 2):\n print(sys.version)\n"), @"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -654,14 +654,14 @@ fn stdin_fix_when_not_fixable_should_still_print_contents() {
|
||||
|
|
||||
|
||||
Found 2 errors (1 fixed, 1 remaining).
|
||||
"###);
|
||||
");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn stdin_fix_when_no_issues_should_still_print_contents() {
|
||||
let mut cmd = RuffCheck::default().args(["--fix"]).build();
|
||||
assert_cmd_snapshot!(cmd
|
||||
.pass_stdin("import sys\n\nprint(sys.version)\n"), @r"
|
||||
.pass_stdin("import sys\n\nprint(sys.version)\n"), @"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -805,7 +805,7 @@ fn stdin_format_jupyter() {
|
||||
fn stdin_parse_error() {
|
||||
let mut cmd = RuffCheck::default().build();
|
||||
assert_cmd_snapshot!(cmd
|
||||
.pass_stdin("from foo import\n"), @r"
|
||||
.pass_stdin("from foo import\n"), @"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -826,7 +826,7 @@ fn stdin_parse_error() {
|
||||
fn stdin_multiple_parse_error() {
|
||||
let mut cmd = RuffCheck::default().build();
|
||||
assert_cmd_snapshot!(cmd
|
||||
.pass_stdin("from foo import\nbar =\n"), @r"
|
||||
.pass_stdin("from foo import\nbar =\n"), @"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -857,7 +857,7 @@ fn parse_error_not_included() {
|
||||
// Parse errors are always shown
|
||||
let mut cmd = RuffCheck::default().args(["--select=I"]).build();
|
||||
assert_cmd_snapshot!(cmd
|
||||
.pass_stdin("foo =\n"), @r"
|
||||
.pass_stdin("foo =\n"), @"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -878,7 +878,7 @@ fn parse_error_not_included() {
|
||||
fn full_output_preview() {
|
||||
let mut cmd = RuffCheck::default().args(["--preview"]).build();
|
||||
assert_cmd_snapshot!(cmd
|
||||
.pass_stdin("l = 1"), @r"
|
||||
.pass_stdin("l = 1"), @"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -907,7 +907,7 @@ preview = true
|
||||
",
|
||||
)?;
|
||||
let mut cmd = RuffCheck::default().config(&pyproject_toml).build();
|
||||
assert_cmd_snapshot!(cmd.pass_stdin("l = 1"), @r"
|
||||
assert_cmd_snapshot!(cmd.pass_stdin("l = 1"), @"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -929,7 +929,7 @@ preview = true
|
||||
fn full_output_format() {
|
||||
let mut cmd = RuffCheck::default().output_format("full").build();
|
||||
assert_cmd_snapshot!(cmd
|
||||
.pass_stdin("l = 1"), @r"
|
||||
.pass_stdin("l = 1"), @"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -967,7 +967,7 @@ fn rule_f401_output_text() {
|
||||
|
||||
#[test]
|
||||
fn rule_invalid_rule_name() {
|
||||
assert_cmd_snapshot!(ruff_cmd().args(["rule", "RUF404"]), @r"
|
||||
assert_cmd_snapshot!(ruff_cmd().args(["rule", "RUF404"]), @"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
@@ -981,7 +981,7 @@ fn rule_invalid_rule_name() {
|
||||
|
||||
#[test]
|
||||
fn rule_invalid_rule_name_output_json() {
|
||||
assert_cmd_snapshot!(ruff_cmd().args(["rule", "RUF404", "--output-format", "json"]), @r"
|
||||
assert_cmd_snapshot!(ruff_cmd().args(["rule", "RUF404", "--output-format", "json"]), @"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
@@ -995,7 +995,7 @@ fn rule_invalid_rule_name_output_json() {
|
||||
|
||||
#[test]
|
||||
fn rule_invalid_rule_name_output_text() {
|
||||
assert_cmd_snapshot!(ruff_cmd().args(["rule", "RUF404", "--output-format", "text"]), @r"
|
||||
assert_cmd_snapshot!(ruff_cmd().args(["rule", "RUF404", "--output-format", "text"]), @"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
@@ -1016,7 +1016,7 @@ fn show_statistics() {
|
||||
.pass_stdin(r#"
|
||||
def mvce(keys, values):
|
||||
return {key: value for key, value in zip(keys, values)}
|
||||
"#), @r"
|
||||
"#), @"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -1037,7 +1037,7 @@ fn show_statistics_unsafe_fixes() {
|
||||
.pass_stdin(r#"
|
||||
def mvce(keys, values):
|
||||
return {key: value for key, value in zip(keys, values)}
|
||||
"#), @r"
|
||||
"#), @"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -1152,7 +1152,7 @@ fn show_statistics_partial_fix() {
|
||||
.args(["--select", "UP035", "--statistics"])
|
||||
.build();
|
||||
assert_cmd_snapshot!(cmd
|
||||
.pass_stdin("from typing import List, AsyncGenerator"), @r"
|
||||
.pass_stdin("from typing import List, AsyncGenerator"), @"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -1173,7 +1173,7 @@ fn show_statistics_syntax_errors() {
|
||||
// ParseError
|
||||
assert_cmd_snapshot!(
|
||||
cmd.pass_stdin("x ="),
|
||||
@r"
|
||||
@"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -1186,7 +1186,7 @@ fn show_statistics_syntax_errors() {
|
||||
// match before 3.10, UnsupportedSyntaxError
|
||||
assert_cmd_snapshot!(
|
||||
cmd.pass_stdin("match 2:\n case 1: ..."),
|
||||
@r"
|
||||
@"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -1199,7 +1199,7 @@ fn show_statistics_syntax_errors() {
|
||||
// rebound comprehension variable, SemanticSyntaxError
|
||||
assert_cmd_snapshot!(
|
||||
cmd.pass_stdin("[x := 1 for x in range(0)]"),
|
||||
@r"
|
||||
@"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -1216,7 +1216,7 @@ fn preview_enabled_prefix() {
|
||||
let mut cmd = RuffCheck::default()
|
||||
.args(["--select", "RUF9", "--output-format=concise", "--preview"])
|
||||
.build();
|
||||
assert_cmd_snapshot!(cmd, @r"
|
||||
assert_cmd_snapshot!(cmd, @"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -1238,7 +1238,7 @@ fn preview_enabled_all() {
|
||||
let mut cmd = RuffCheck::default()
|
||||
.args(["--select", "ALL", "--output-format=concise", "--preview"])
|
||||
.build();
|
||||
assert_cmd_snapshot!(cmd, @r"
|
||||
assert_cmd_snapshot!(cmd, @"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -1265,7 +1265,7 @@ fn preview_enabled_direct() {
|
||||
let mut cmd = RuffCheck::default()
|
||||
.args(["--select", "RUF911", "--output-format=concise", "--preview"])
|
||||
.build();
|
||||
assert_cmd_snapshot!(cmd, @r"
|
||||
assert_cmd_snapshot!(cmd, @"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -1282,7 +1282,7 @@ fn preview_disabled_direct() {
|
||||
let mut cmd = RuffCheck::default()
|
||||
.args(["--select", "RUF911", "--output-format=concise"])
|
||||
.build();
|
||||
assert_cmd_snapshot!(cmd, @r"
|
||||
assert_cmd_snapshot!(cmd, @"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -1299,7 +1299,7 @@ fn preview_disabled_prefix_empty() {
|
||||
let mut cmd = RuffCheck::default()
|
||||
.args(["--select", "RUF91", "--output-format=concise"])
|
||||
.build();
|
||||
assert_cmd_snapshot!(cmd, @r"
|
||||
assert_cmd_snapshot!(cmd, @"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -1316,7 +1316,7 @@ fn preview_disabled_does_not_warn_for_empty_ignore_selections() {
|
||||
let mut cmd = RuffCheck::default()
|
||||
.args(["--ignore", "RUF9", "--output-format=concise"])
|
||||
.build();
|
||||
assert_cmd_snapshot!(cmd, @r"
|
||||
assert_cmd_snapshot!(cmd, @"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -1332,7 +1332,7 @@ fn preview_disabled_does_not_warn_for_empty_fixable_selections() {
|
||||
let mut cmd = RuffCheck::default()
|
||||
.args(["--fixable", "RUF9", "--output-format=concise"])
|
||||
.build();
|
||||
assert_cmd_snapshot!(cmd, @r"
|
||||
assert_cmd_snapshot!(cmd, @"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -1354,7 +1354,7 @@ fn preview_group_selector() {
|
||||
])
|
||||
.build();
|
||||
assert_cmd_snapshot!(cmd
|
||||
.pass_stdin("I=42\n"), @r"
|
||||
.pass_stdin("I=42\n"), @"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
@@ -1379,7 +1379,7 @@ fn preview_enabled_group_ignore() {
|
||||
"--output-format=concise",
|
||||
])
|
||||
.build();
|
||||
assert_cmd_snapshot!(cmd, @r"
|
||||
assert_cmd_snapshot!(cmd, @"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -1400,7 +1400,7 @@ fn preview_enabled_group_ignore() {
|
||||
fn removed_direct() {
|
||||
// Selection of a removed rule should fail
|
||||
let mut cmd = RuffCheck::default().args(["--select", "RUF931"]).build();
|
||||
assert_cmd_snapshot!(cmd, @r"
|
||||
assert_cmd_snapshot!(cmd, @"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
@@ -1418,7 +1418,7 @@ fn removed_direct_multiple() {
|
||||
let mut cmd = RuffCheck::default()
|
||||
.args(["--select", "RUF930", "--select", "RUF931"])
|
||||
.build();
|
||||
assert_cmd_snapshot!(cmd, @r"
|
||||
assert_cmd_snapshot!(cmd, @"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
@@ -1436,7 +1436,7 @@ fn removed_indirect() {
|
||||
// Selection _including_ a removed rule without matching should not fail
|
||||
// nor should the rule be used
|
||||
let mut cmd = RuffCheck::default().args(["--select", "RUF93"]).build();
|
||||
assert_cmd_snapshot!(cmd, @r"
|
||||
assert_cmd_snapshot!(cmd, @"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -1449,7 +1449,7 @@ fn removed_indirect() {
|
||||
#[test]
|
||||
fn removed_ignore_direct() {
|
||||
let mut cmd = RuffCheck::default().args(["--ignore", "UP027"]).build();
|
||||
assert_cmd_snapshot!(cmd, @r"
|
||||
assert_cmd_snapshot!(cmd, @"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -1466,7 +1466,7 @@ fn removed_ignore_multiple_direct() {
|
||||
let mut cmd = RuffCheck::default()
|
||||
.args(["--ignore", "UP027", "--ignore", "PLR1706"])
|
||||
.build();
|
||||
assert_cmd_snapshot!(cmd, @r"
|
||||
assert_cmd_snapshot!(cmd, @"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -1482,7 +1482,7 @@ fn removed_ignore_multiple_direct() {
|
||||
#[test]
|
||||
fn removed_ignore_remapped_direct() {
|
||||
let mut cmd = RuffCheck::default().args(["--ignore", "PGH001"]).build();
|
||||
assert_cmd_snapshot!(cmd, @r"
|
||||
assert_cmd_snapshot!(cmd, @"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -1498,7 +1498,7 @@ fn removed_ignore_indirect() {
|
||||
// `PLR170` includes removed rules but should not select or warn
|
||||
// since it is not a "direct" selection
|
||||
let mut cmd = RuffCheck::default().args(["--ignore", "PLR170"]).build();
|
||||
assert_cmd_snapshot!(cmd, @r"
|
||||
assert_cmd_snapshot!(cmd, @"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -1512,7 +1512,7 @@ fn removed_ignore_indirect() {
|
||||
fn redirect_direct() {
|
||||
// Selection of a redirected rule directly should use the new rule and warn
|
||||
let mut cmd = RuffCheck::default().args(["--select", "RUF940"]).build();
|
||||
assert_cmd_snapshot!(cmd, @r"
|
||||
assert_cmd_snapshot!(cmd, @"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -1531,7 +1531,7 @@ fn redirect_indirect() {
|
||||
// Selection _including_ a redirected rule without matching should not fail
|
||||
// nor should the rule be used
|
||||
let mut cmd = RuffCheck::default().args(["--select", "RUF94"]).build();
|
||||
assert_cmd_snapshot!(cmd, @r"
|
||||
assert_cmd_snapshot!(cmd, @"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -1546,7 +1546,7 @@ fn redirect_prefix() {
|
||||
// Selection using a redirected prefix should switch to all rules in the
|
||||
// new prefix
|
||||
let mut cmd = RuffCheck::default().args(["--select", "RUF96"]).build();
|
||||
assert_cmd_snapshot!(cmd, @r"
|
||||
assert_cmd_snapshot!(cmd, @"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -1565,7 +1565,7 @@ fn deprecated_direct() {
|
||||
// Selection of a deprecated rule without preview enabled should still work
|
||||
// but a warning should be displayed
|
||||
let mut cmd = RuffCheck::default().args(["--select", "RUF920"]).build();
|
||||
assert_cmd_snapshot!(cmd, @r"
|
||||
assert_cmd_snapshot!(cmd, @"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -1586,7 +1586,7 @@ fn deprecated_multiple_direct() {
|
||||
let mut cmd = RuffCheck::default()
|
||||
.args(["--select", "RUF920", "--select", "RUF921"])
|
||||
.build();
|
||||
assert_cmd_snapshot!(cmd, @r"
|
||||
assert_cmd_snapshot!(cmd, @"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -1609,7 +1609,7 @@ fn deprecated_indirect() {
|
||||
// `RUF92` includes deprecated rules but should not warn
|
||||
// since it is not a "direct" selection
|
||||
let mut cmd = RuffCheck::default().args(["--select", "RUF92"]).build();
|
||||
assert_cmd_snapshot!(cmd, @r"
|
||||
assert_cmd_snapshot!(cmd, @"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -1625,7 +1625,7 @@ fn deprecated_direct_preview_enabled() {
|
||||
let mut cmd = RuffCheck::default()
|
||||
.args(["--select", "RUF920", "--preview"])
|
||||
.build();
|
||||
assert_cmd_snapshot!(cmd, @r"
|
||||
assert_cmd_snapshot!(cmd, @"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
@@ -1642,7 +1642,7 @@ fn deprecated_indirect_preview_enabled() {
|
||||
let mut cmd = RuffCheck::default()
|
||||
.args(["--select", "RUF92", "--preview"])
|
||||
.build();
|
||||
assert_cmd_snapshot!(cmd, @r"
|
||||
assert_cmd_snapshot!(cmd, @"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -1659,7 +1659,7 @@ fn deprecated_multiple_direct_preview_enabled() {
|
||||
let mut cmd = RuffCheck::default()
|
||||
.args(["--select", "RUF920", "--select", "RUF921", "--preview"])
|
||||
.build();
|
||||
assert_cmd_snapshot!(cmd, @r"
|
||||
assert_cmd_snapshot!(cmd, @"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
@@ -1720,7 +1720,7 @@ fn unreadable_dir() -> Result<()> {
|
||||
.filename(unreadable_dir.to_str().unwrap())
|
||||
.args([])
|
||||
.build();
|
||||
assert_cmd_snapshot!(cmd, @r###"
|
||||
assert_cmd_snapshot!(cmd, @"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -1728,7 +1728,7 @@ fn unreadable_dir() -> Result<()> {
|
||||
|
||||
----- stderr -----
|
||||
warning: Encountered error: Permission denied (os error 13)
|
||||
"###);
|
||||
");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1758,7 +1758,7 @@ fn check_input_from_argfile() -> Result<()> {
|
||||
(file_a_path.display().to_string().as_str(), "/path/to/a.py"),
|
||||
]}, {
|
||||
assert_cmd_snapshot!(cmd
|
||||
.pass_stdin(""), @r"
|
||||
.pass_stdin(""), @"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -1787,17 +1787,17 @@ fn missing_argfile_reports_error() {
|
||||
insta::with_settings!({filters => vec![
|
||||
("The system cannot find the file specified.", "No such file or directory")
|
||||
]}, {
|
||||
assert_cmd_snapshot!(cmd, @r"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
assert_cmd_snapshot!(cmd, @"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
ruff failed
|
||||
Cause: Failed to read CLI arguments from files
|
||||
Cause: failed to open file `!.txt`
|
||||
Cause: No such file or directory (os error 2)
|
||||
");
|
||||
----- stderr -----
|
||||
ruff failed
|
||||
Cause: Failed to read CLI arguments from files
|
||||
Cause: failed to open file `!.txt`
|
||||
Cause: No such file or directory (os error 2)
|
||||
");
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1807,7 +1807,7 @@ fn check_hints_hidden_unsafe_fixes() {
|
||||
.args(["--select", "RUF901,RUF902"])
|
||||
.build();
|
||||
assert_cmd_snapshot!(cmd,
|
||||
@r"
|
||||
@"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -1829,7 +1829,7 @@ fn check_hints_hidden_unsafe_fixes_with_no_safe_fixes() {
|
||||
let mut cmd = RuffCheck::default().args(["--select", "RUF902"]).build();
|
||||
assert_cmd_snapshot!(cmd
|
||||
.pass_stdin("x = {'a': 1, 'a': 1}\n"),
|
||||
@r"
|
||||
@"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -1849,7 +1849,7 @@ fn check_no_hint_for_hidden_unsafe_fixes_when_disabled() {
|
||||
.args(["--select", "RUF901,RUF902", "--no-unsafe-fixes"])
|
||||
.build();
|
||||
assert_cmd_snapshot!(cmd,
|
||||
@r"
|
||||
@"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -1873,7 +1873,7 @@ fn check_no_hint_for_hidden_unsafe_fixes_with_no_safe_fixes_when_disabled() {
|
||||
.build();
|
||||
assert_cmd_snapshot!(cmd
|
||||
.pass_stdin("x = {'a': 1, 'a': 1}\n"),
|
||||
@r"
|
||||
@"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -1892,7 +1892,7 @@ fn check_shows_unsafe_fixes_with_opt_in() {
|
||||
.args(["--select", "RUF901,RUF902", "--unsafe-fixes"])
|
||||
.build();
|
||||
assert_cmd_snapshot!(cmd,
|
||||
@r"
|
||||
@"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -1915,7 +1915,7 @@ fn fix_applies_safe_fixes_by_default() {
|
||||
.args(["--select", "RUF901,RUF902", "--fix"])
|
||||
.build();
|
||||
assert_cmd_snapshot!(cmd,
|
||||
@r"
|
||||
@"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -1936,7 +1936,7 @@ fn fix_applies_unsafe_fixes_with_opt_in() {
|
||||
.args(["--select", "RUF901,RUF902", "--fix", "--unsafe-fixes"])
|
||||
.build();
|
||||
assert_cmd_snapshot!(cmd,
|
||||
@r"
|
||||
@"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -1955,7 +1955,7 @@ fn fix_does_not_apply_display_only_fixes() {
|
||||
.build();
|
||||
assert_cmd_snapshot!(cmd
|
||||
.pass_stdin("def add_to_list(item, some_list=[]): ..."),
|
||||
@r"
|
||||
@"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -1975,7 +1975,7 @@ fn fix_does_not_apply_display_only_fixes_with_unsafe_fixes_enabled() {
|
||||
.build();
|
||||
assert_cmd_snapshot!(cmd
|
||||
.pass_stdin("def add_to_list(item, some_list=[]): ..."),
|
||||
@r"
|
||||
@"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -1994,7 +1994,7 @@ fn fix_only_unsafe_fixes_available() {
|
||||
.args(["--select", "RUF902", "--fix"])
|
||||
.build();
|
||||
assert_cmd_snapshot!(cmd,
|
||||
@r"
|
||||
@"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -2014,7 +2014,7 @@ fn fix_only_flag_applies_safe_fixes_by_default() {
|
||||
.args(["--select", "RUF901,RUF902", "--fix-only"])
|
||||
.build();
|
||||
assert_cmd_snapshot!(cmd,
|
||||
@r"
|
||||
@"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -2031,7 +2031,7 @@ fn fix_only_flag_applies_unsafe_fixes_with_opt_in() {
|
||||
.args(["--select", "RUF901,RUF902", "--fix-only", "--unsafe-fixes"])
|
||||
.build();
|
||||
assert_cmd_snapshot!(cmd,
|
||||
@r"
|
||||
@"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -2049,7 +2049,7 @@ fn diff_shows_safe_fixes_by_default() {
|
||||
.args(["--select", "RUF901,RUF902", "--diff"])
|
||||
.build();
|
||||
assert_cmd_snapshot!(cmd,
|
||||
@r"
|
||||
@"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -2069,7 +2069,7 @@ fn diff_shows_unsafe_fixes_with_opt_in() {
|
||||
.args(["--select", "RUF901,RUF902", "--diff", "--unsafe-fixes"])
|
||||
.build();
|
||||
assert_cmd_snapshot!(cmd,
|
||||
@r"
|
||||
@"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -2091,7 +2091,7 @@ fn diff_does_not_show_display_only_fixes_with_unsafe_fixes_enabled() {
|
||||
.build();
|
||||
assert_cmd_snapshot!(cmd
|
||||
.pass_stdin("def add_to_list(item, some_list=[]): ..."),
|
||||
@r"
|
||||
@"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -2106,7 +2106,7 @@ fn diff_only_unsafe_fixes_available() {
|
||||
.args(["--select", "RUF902", "--diff"])
|
||||
.build();
|
||||
assert_cmd_snapshot!(cmd,
|
||||
@r"
|
||||
@"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -2134,7 +2134,7 @@ extend-unsafe-fixes = ["RUF901"]
|
||||
.args(["--select", "RUF901,RUF902"])
|
||||
.build();
|
||||
assert_cmd_snapshot!(cmd,
|
||||
@r"
|
||||
@"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -2170,7 +2170,7 @@ extend-safe-fixes = ["RUF902"]
|
||||
.args(["--select", "RUF901,RUF902"])
|
||||
.build();
|
||||
assert_cmd_snapshot!(cmd,
|
||||
@r"
|
||||
@"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -2208,7 +2208,7 @@ extend-safe-fixes = ["RUF902"]
|
||||
.args(["--select", "RUF901,RUF902"])
|
||||
.build();
|
||||
assert_cmd_snapshot!(cmd,
|
||||
@r"
|
||||
@"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -2248,7 +2248,7 @@ extend-safe-fixes = ["RUF9"]
|
||||
.build();
|
||||
assert_cmd_snapshot!(cmd
|
||||
.pass_stdin("x = {'a': 1, 'a': 1}\nprint(('foo'))\nprint(str('foo'))\nisinstance(x, (int, str))\n"),
|
||||
@r"
|
||||
@"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -2307,7 +2307,7 @@ def log(x, base) -> float:
|
||||
.args(["--select", "D41"])
|
||||
.build();
|
||||
assert_cmd_snapshot!(cmd
|
||||
.pass_stdin(stdin), @r"
|
||||
.pass_stdin(stdin), @"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -2360,7 +2360,7 @@ select = ["RUF017"]
|
||||
let mut cmd = RuffCheck::default().config(&ruff_toml).build();
|
||||
assert_cmd_snapshot!(cmd
|
||||
.pass_stdin("x = [1, 2, 3]\ny = [4, 5, 6]\nsum([x, y], [])"),
|
||||
@r"
|
||||
@"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -2401,7 +2401,7 @@ unfixable = ["RUF"]
|
||||
let mut cmd = RuffCheck::default().config(&ruff_toml).build();
|
||||
assert_cmd_snapshot!(cmd
|
||||
.pass_stdin("x = [1, 2, 3]\ny = [4, 5, 6]\nsum([x, y], [])"),
|
||||
@r"
|
||||
@"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -2431,7 +2431,7 @@ fn pyproject_toml_stdin_syntax_error() {
|
||||
|
||||
assert_cmd_snapshot!(
|
||||
cmd.pass_stdin("[project"),
|
||||
@r"
|
||||
@"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -2457,7 +2457,7 @@ fn pyproject_toml_stdin_schema_error() {
|
||||
|
||||
assert_cmd_snapshot!(
|
||||
cmd.pass_stdin("[project]\nname = 1"),
|
||||
@r"
|
||||
@"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -2484,7 +2484,7 @@ fn pyproject_toml_stdin_no_applicable_rules_selected() {
|
||||
|
||||
assert_cmd_snapshot!(
|
||||
cmd.pass_stdin("[project"),
|
||||
@r"
|
||||
@"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -2503,7 +2503,7 @@ fn pyproject_toml_stdin_no_applicable_rules_selected_2() {
|
||||
|
||||
assert_cmd_snapshot!(
|
||||
cmd.pass_stdin("[project"),
|
||||
@r"
|
||||
@"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -2522,7 +2522,7 @@ fn pyproject_toml_stdin_no_errors() {
|
||||
|
||||
assert_cmd_snapshot!(
|
||||
cmd.pass_stdin(r#"[project]\nname = "ruff"\nversion = "0.0.0""#),
|
||||
@r"
|
||||
@"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -2547,7 +2547,7 @@ fn pyproject_toml_stdin_schema_error_fix() {
|
||||
|
||||
assert_cmd_snapshot!(
|
||||
cmd.pass_stdin("[project]\nname = 1"),
|
||||
@r"
|
||||
@"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -2581,7 +2581,7 @@ fn pyproject_toml_stdin_schema_error_fix_only() {
|
||||
|
||||
assert_cmd_snapshot!(
|
||||
cmd.pass_stdin("[project]\nname = 1"),
|
||||
@r"
|
||||
@"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -2607,7 +2607,7 @@ fn pyproject_toml_stdin_schema_error_fix_diff() {
|
||||
|
||||
assert_cmd_snapshot!(
|
||||
cmd.pass_stdin("[project]\nname = 1"),
|
||||
@r"
|
||||
@"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
@@ -29,7 +29,7 @@ fn check_project_include_defaults() {
|
||||
filters => TEST_FILTERS.to_vec()
|
||||
}, {
|
||||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||||
.args(["check", "--show-files"]).current_dir(Path::new("./resources/test/fixtures/include-test")), @r"
|
||||
.args(["check", "--show-files"]).current_dir(Path::new("./resources/test/fixtures/include-test")), @"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -53,7 +53,7 @@ fn check_project_respects_direct_paths() {
|
||||
filters => TEST_FILTERS.to_vec()
|
||||
}, {
|
||||
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")), @r"
|
||||
.args(["check", "--show-files", "b.py"]).current_dir(Path::new("./resources/test/fixtures/include-test")), @"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -72,7 +72,7 @@ fn check_project_respects_subdirectory_includes() {
|
||||
filters => TEST_FILTERS.to_vec()
|
||||
}, {
|
||||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||||
.args(["check", "--show-files", "subdirectory"]).current_dir(Path::new("./resources/test/fixtures/include-test")), @r"
|
||||
.args(["check", "--show-files", "subdirectory"]).current_dir(Path::new("./resources/test/fixtures/include-test")), @"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -91,7 +91,7 @@ fn check_project_from_project_subdirectory_respects_includes() {
|
||||
filters => TEST_FILTERS.to_vec()
|
||||
}, {
|
||||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||||
.args(["check", "--show-files"]).current_dir(Path::new("./resources/test/fixtures/include-test/subdirectory")), @r"
|
||||
.args(["check", "--show-files"]).current_dir(Path::new("./resources/test/fixtures/include-test/subdirectory")), @"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
@@ -50,6 +50,56 @@ ignore = [
|
||||
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 {
|
||||
format!(r#"{}\\?/?"#, regex::escape(project_dir.to_str().unwrap()))
|
||||
}
|
||||
|
||||
@@ -3,11 +3,12 @@ source: crates/ruff/tests/integration_test.rs
|
||||
info:
|
||||
program: ruff
|
||||
args:
|
||||
- "-"
|
||||
- "--isolated"
|
||||
- "--no-cache"
|
||||
- check
|
||||
- "--output-format"
|
||||
- json
|
||||
- "--no-cache"
|
||||
- "--isolated"
|
||||
- "-"
|
||||
- "--stdin-filename"
|
||||
- F401.py
|
||||
stdin: "import os\n"
|
||||
@@ -51,4 +52,3 @@ exit_code: 1
|
||||
}
|
||||
]
|
||||
----- stderr -----
|
||||
|
||||
|
||||
@@ -0,0 +1,410 @@
|
||||
---
|
||||
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 -----
|
||||
@@ -16,7 +16,7 @@ const VERSION_FILTER: [(&str, &str); 1] = [(
|
||||
fn version_basics() {
|
||||
insta::with_settings!({filters => VERSION_FILTER.to_vec()}, {
|
||||
assert_cmd_snapshot!(
|
||||
Command::new(get_cargo_bin(BIN_NAME)).arg("version"), @r"
|
||||
Command::new(get_cargo_bin(BIN_NAME)).arg("version"), @"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -42,7 +42,7 @@ fn config_option_allowed_but_ignored() -> Result<()> {
|
||||
.arg("version")
|
||||
.arg("--config")
|
||||
.arg(&ruff_dot_toml)
|
||||
.args(["--config", "lint.isort.extra-standard-library = ['foo', 'bar']"]), @r"
|
||||
.args(["--config", "lint.isort.extra-standard-library = ['foo', 'bar']"]), @"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
@@ -60,7 +60,7 @@ fn config_option_ignored_but_validated() {
|
||||
assert_cmd_snapshot!(
|
||||
Command::new(get_cargo_bin(BIN_NAME))
|
||||
.arg("version")
|
||||
.args(["--config", "foo = bar"]), @r"
|
||||
.args(["--config", "foo = bar"]), @"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
@@ -91,7 +91,7 @@ fn config_option_ignored_but_validated() {
|
||||
fn isolated_option_allowed() {
|
||||
insta::with_settings!({filters => VERSION_FILTER.to_vec()}, {
|
||||
assert_cmd_snapshot!(
|
||||
Command::new(get_cargo_bin(BIN_NAME)).arg("version").arg("--isolated"), @r"
|
||||
Command::new(get_cargo_bin(BIN_NAME)).arg("version").arg("--isolated"), @"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
@@ -15,7 +15,7 @@ use ruff_db::files::{File, system_path_to_file};
|
||||
use ruff_db::source::source_text;
|
||||
use ruff_db::system::{InMemorySystem, MemoryFileSystem, SystemPath, SystemPathBuf, TestSystem};
|
||||
use ruff_python_ast::PythonVersion;
|
||||
use ty_project::metadata::options::{EnvironmentOptions, Options};
|
||||
use ty_project::metadata::options::{AnalysisOptions, EnvironmentOptions, Options};
|
||||
use ty_project::metadata::value::{RangedValue, RelativePathBuf};
|
||||
use ty_project::watch::{ChangeEvent, ChangedKind};
|
||||
use ty_project::{CheckMode, Db, ProjectDatabase, ProjectMetadata};
|
||||
@@ -67,6 +67,7 @@ fn tomllib_path(file: &TestFile) -> SystemPathBuf {
|
||||
SystemPathBuf::from("src").join(file.name())
|
||||
}
|
||||
|
||||
#[expect(clippy::needless_update)]
|
||||
fn setup_tomllib_case() -> Case {
|
||||
let system = TestSystem::default();
|
||||
let fs = system.memory_file_system().clone();
|
||||
@@ -85,6 +86,10 @@ fn setup_tomllib_case() -> Case {
|
||||
python_version: Some(RangedValue::cli(PythonVersion::PY312)),
|
||||
..EnvironmentOptions::default()
|
||||
}),
|
||||
analysis: Some(AnalysisOptions {
|
||||
respect_type_ignore_comments: Some(false),
|
||||
..AnalysisOptions::default()
|
||||
}),
|
||||
..Options::default()
|
||||
});
|
||||
|
||||
@@ -221,7 +226,7 @@ fn setup_micro_case(code: &str) -> Case {
|
||||
let file_path = "src/test.py";
|
||||
fs.write_file_all(
|
||||
SystemPathBuf::from(file_path),
|
||||
ruff_python_trivia::textwrap::dedent(code),
|
||||
&*ruff_python_trivia::textwrap::dedent(code),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
@@ -755,7 +760,7 @@ fn datetype(criterion: &mut Criterion) {
|
||||
max_dep_date: "2025-07-04",
|
||||
python_version: PythonVersion::PY313,
|
||||
},
|
||||
2,
|
||||
4,
|
||||
);
|
||||
|
||||
bench_project(&benchmark, criterion);
|
||||
|
||||
@@ -71,6 +71,8 @@ impl Display for Benchmark<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
#[expect(clippy::cast_precision_loss)]
|
||||
fn check_project(db: &ProjectDatabase, project_name: &str, max_diagnostics: usize) {
|
||||
let result = db.check();
|
||||
let diagnostics = result.len();
|
||||
@@ -79,6 +81,12 @@ fn check_project(db: &ProjectDatabase, project_name: &str, max_diagnostics: usiz
|
||||
diagnostics > 1 && diagnostics <= max_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(
|
||||
@@ -101,7 +109,7 @@ static ALTAIR: Benchmark = Benchmark::new(
|
||||
max_dep_date: "2025-06-17",
|
||||
python_version: PythonVersion::PY312,
|
||||
},
|
||||
1000,
|
||||
850,
|
||||
);
|
||||
|
||||
static COLOUR_SCIENCE: Benchmark = Benchmark::new(
|
||||
@@ -120,7 +128,7 @@ static COLOUR_SCIENCE: Benchmark = Benchmark::new(
|
||||
max_dep_date: "2025-06-17",
|
||||
python_version: PythonVersion::PY310,
|
||||
},
|
||||
1070,
|
||||
350,
|
||||
);
|
||||
|
||||
static FREQTRADE: Benchmark = Benchmark::new(
|
||||
@@ -163,7 +171,7 @@ static PANDAS: Benchmark = Benchmark::new(
|
||||
max_dep_date: "2025-06-17",
|
||||
python_version: PythonVersion::PY312,
|
||||
},
|
||||
4000,
|
||||
3800,
|
||||
);
|
||||
|
||||
static PYDANTIC: Benchmark = Benchmark::new(
|
||||
@@ -181,7 +189,7 @@ static PYDANTIC: Benchmark = Benchmark::new(
|
||||
max_dep_date: "2025-06-17",
|
||||
python_version: PythonVersion::PY39,
|
||||
},
|
||||
7000,
|
||||
3200,
|
||||
);
|
||||
|
||||
static SYMPY: Benchmark = Benchmark::new(
|
||||
@@ -194,7 +202,7 @@ static SYMPY: Benchmark = Benchmark::new(
|
||||
max_dep_date: "2025-06-17",
|
||||
python_version: PythonVersion::PY312,
|
||||
},
|
||||
13116,
|
||||
13400,
|
||||
);
|
||||
|
||||
static TANJUN: Benchmark = Benchmark::new(
|
||||
@@ -207,7 +215,7 @@ static TANJUN: Benchmark = Benchmark::new(
|
||||
max_dep_date: "2025-06-17",
|
||||
python_version: PythonVersion::PY312,
|
||||
},
|
||||
320,
|
||||
110,
|
||||
);
|
||||
|
||||
static STATIC_FRAME: Benchmark = Benchmark::new(
|
||||
@@ -223,7 +231,7 @@ static STATIC_FRAME: Benchmark = Benchmark::new(
|
||||
max_dep_date: "2025-08-09",
|
||||
python_version: PythonVersion::PY311,
|
||||
},
|
||||
1100,
|
||||
1700,
|
||||
);
|
||||
|
||||
#[track_caller]
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use std::fmt::Formatter;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
|
||||
@@ -49,3 +50,15 @@ impl CancellationToken {
|
||||
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")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,6 +98,44 @@ impl Diagnostic {
|
||||
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.
|
||||
///
|
||||
/// Annotations for a diagnostic are optional, but if any are added,
|
||||
@@ -1019,6 +1057,13 @@ impl DiagnosticId {
|
||||
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.
|
||||
pub fn is_lint_named(&self, name: &str) -> bool {
|
||||
matches!(self, DiagnosticId::Lint(self_name) if self_name == name)
|
||||
|
||||
@@ -1284,7 +1284,7 @@ watermelon
|
||||
let diag = env.err().primary("animals", "5", "5", "").build();
|
||||
insta::assert_snapshot!(
|
||||
env.render(&diag),
|
||||
@r"
|
||||
@"
|
||||
error[test-diagnostic]: main diagnostic message
|
||||
--> animals:5:1
|
||||
|
|
||||
@@ -1308,7 +1308,7 @@ watermelon
|
||||
.build();
|
||||
insta::assert_snapshot!(
|
||||
env.render(&diag),
|
||||
@r"
|
||||
@"
|
||||
warning[test-diagnostic]: main diagnostic message
|
||||
--> animals:5:1
|
||||
|
|
||||
@@ -1328,7 +1328,7 @@ watermelon
|
||||
.build();
|
||||
insta::assert_snapshot!(
|
||||
env.render(&diag),
|
||||
@r"
|
||||
@"
|
||||
info[test-diagnostic]: main diagnostic message
|
||||
--> animals:5:1
|
||||
|
|
||||
@@ -1355,7 +1355,7 @@ watermelon
|
||||
let diag = builder.build();
|
||||
insta::assert_snapshot!(
|
||||
env.render(&diag),
|
||||
@r"
|
||||
@"
|
||||
error[test-diagnostic]: main diagnostic message
|
||||
--> animals:1:1
|
||||
|
|
||||
@@ -1374,7 +1374,7 @@ watermelon
|
||||
let diag = builder.build();
|
||||
insta::assert_snapshot!(
|
||||
env.render(&diag),
|
||||
@r"
|
||||
@"
|
||||
error[test-diagnostic]: main diagnostic message
|
||||
--> animals:1:1
|
||||
|
|
||||
@@ -1395,7 +1395,7 @@ watermelon
|
||||
let diag = env.err().primary("non-ascii", "5", "5", "").build();
|
||||
insta::assert_snapshot!(
|
||||
env.render(&diag),
|
||||
@r"
|
||||
@"
|
||||
error[test-diagnostic]: main diagnostic message
|
||||
--> non-ascii:5:1
|
||||
|
|
||||
@@ -1414,7 +1414,7 @@ watermelon
|
||||
let diag = env.err().primary("non-ascii", "2:4", "2:8", "").build();
|
||||
insta::assert_snapshot!(
|
||||
env.render(&diag),
|
||||
@r"
|
||||
@"
|
||||
error[test-diagnostic]: main diagnostic message
|
||||
--> non-ascii:2:2
|
||||
|
|
||||
@@ -1438,7 +1438,7 @@ watermelon
|
||||
env.context(1);
|
||||
insta::assert_snapshot!(
|
||||
env.render(&diag),
|
||||
@r"
|
||||
@"
|
||||
error[test-diagnostic]: main diagnostic message
|
||||
--> animals:5:1
|
||||
|
|
||||
@@ -1455,7 +1455,7 @@ watermelon
|
||||
env.context(0);
|
||||
insta::assert_snapshot!(
|
||||
env.render(&diag),
|
||||
@r"
|
||||
@"
|
||||
error[test-diagnostic]: main diagnostic message
|
||||
--> animals:5:1
|
||||
|
|
||||
@@ -1470,7 +1470,7 @@ watermelon
|
||||
env.context(2);
|
||||
insta::assert_snapshot!(
|
||||
env.render(&diag),
|
||||
@r"
|
||||
@"
|
||||
error[test-diagnostic]: main diagnostic message
|
||||
--> animals:1:1
|
||||
|
|
||||
@@ -1487,7 +1487,7 @@ watermelon
|
||||
env.context(2);
|
||||
insta::assert_snapshot!(
|
||||
env.render(&diag),
|
||||
@r"
|
||||
@"
|
||||
error[test-diagnostic]: main diagnostic message
|
||||
--> animals:11:1
|
||||
|
|
||||
@@ -1504,7 +1504,7 @@ watermelon
|
||||
env.context(200);
|
||||
insta::assert_snapshot!(
|
||||
env.render(&diag),
|
||||
@r"
|
||||
@"
|
||||
error[test-diagnostic]: main diagnostic message
|
||||
--> animals:5:1
|
||||
|
|
||||
@@ -1537,7 +1537,7 @@ watermelon
|
||||
.build();
|
||||
insta::assert_snapshot!(
|
||||
env.render(&diag),
|
||||
@r"
|
||||
@"
|
||||
error[test-diagnostic]: main diagnostic message
|
||||
--> animals:1:1
|
||||
|
|
||||
@@ -1581,7 +1581,7 @@ watermelon
|
||||
.build();
|
||||
insta::assert_snapshot!(
|
||||
env.render(&diag),
|
||||
@r"
|
||||
@"
|
||||
error[test-diagnostic]: main diagnostic message
|
||||
--> animals:1:1
|
||||
|
|
||||
@@ -1606,7 +1606,7 @@ watermelon
|
||||
.build();
|
||||
insta::assert_snapshot!(
|
||||
env.render(&diag),
|
||||
@r"
|
||||
@"
|
||||
error[test-diagnostic]: main diagnostic message
|
||||
--> animals:1:1
|
||||
|
|
||||
@@ -1634,7 +1634,7 @@ watermelon
|
||||
.build();
|
||||
insta::assert_snapshot!(
|
||||
env.render(&diag),
|
||||
@r"
|
||||
@"
|
||||
error[test-diagnostic]: main diagnostic message
|
||||
--> animals:1:1
|
||||
|
|
||||
@@ -1662,7 +1662,7 @@ watermelon
|
||||
.build();
|
||||
insta::assert_snapshot!(
|
||||
env.render(&diag),
|
||||
@r"
|
||||
@"
|
||||
error[test-diagnostic]: main diagnostic message
|
||||
--> animals:1:1
|
||||
|
|
||||
@@ -1687,7 +1687,7 @@ watermelon
|
||||
.build();
|
||||
insta::assert_snapshot!(
|
||||
env.render(&diag),
|
||||
@r"
|
||||
@"
|
||||
error[test-diagnostic]: main diagnostic message
|
||||
--> animals:1:1
|
||||
|
|
||||
@@ -1718,7 +1718,7 @@ watermelon
|
||||
// window.
|
||||
insta::assert_snapshot!(
|
||||
env.render(&diag),
|
||||
@r"
|
||||
@"
|
||||
error[test-diagnostic]: main diagnostic message
|
||||
--> animals:1:1
|
||||
|
|
||||
@@ -1756,7 +1756,7 @@ watermelon
|
||||
let diag = env.err().primary("spacey-animals", "8", "8", "").build();
|
||||
insta::assert_snapshot!(
|
||||
env.render(&diag),
|
||||
@r"
|
||||
@"
|
||||
error[test-diagnostic]: main diagnostic message
|
||||
--> spacey-animals:8:1
|
||||
|
|
||||
@@ -1773,7 +1773,7 @@ watermelon
|
||||
let diag = env.err().primary("spacey-animals", "12", "12", "").build();
|
||||
insta::assert_snapshot!(
|
||||
env.render(&diag),
|
||||
@r"
|
||||
@"
|
||||
error[test-diagnostic]: main diagnostic message
|
||||
--> spacey-animals:12:1
|
||||
|
|
||||
@@ -1791,7 +1791,7 @@ watermelon
|
||||
let diag = env.err().primary("spacey-animals", "13", "13", "").build();
|
||||
insta::assert_snapshot!(
|
||||
env.render(&diag),
|
||||
@r"
|
||||
@"
|
||||
error[test-diagnostic]: main diagnostic message
|
||||
--> spacey-animals:13:1
|
||||
|
|
||||
@@ -1831,7 +1831,7 @@ watermelon
|
||||
// instead of special casing the snippet assembly.
|
||||
insta::assert_snapshot!(
|
||||
env.render(&diag),
|
||||
@r"
|
||||
@"
|
||||
error[test-diagnostic]: main diagnostic message
|
||||
--> spacey-animals:3:1
|
||||
|
|
||||
@@ -1860,7 +1860,7 @@ watermelon
|
||||
.build();
|
||||
insta::assert_snapshot!(
|
||||
env.render(&diag),
|
||||
@r"
|
||||
@"
|
||||
error[test-diagnostic]: main diagnostic message
|
||||
--> animals:3:1
|
||||
|
|
||||
@@ -1897,7 +1897,7 @@ watermelon
|
||||
);
|
||||
insta::assert_snapshot!(
|
||||
env.render(&diag),
|
||||
@r"
|
||||
@"
|
||||
error[test-diagnostic]: main diagnostic message
|
||||
--> animals:3:1
|
||||
|
|
||||
@@ -1934,7 +1934,7 @@ watermelon
|
||||
);
|
||||
insta::assert_snapshot!(
|
||||
env.render(&diag),
|
||||
@r"
|
||||
@"
|
||||
error[test-diagnostic]: main diagnostic message
|
||||
--> animals:3:1
|
||||
|
|
||||
@@ -1962,7 +1962,7 @@ watermelon
|
||||
diag.sub(env.sub_warn().primary("fruits", "3", "3", "").build());
|
||||
insta::assert_snapshot!(
|
||||
env.render(&diag),
|
||||
@r"
|
||||
@"
|
||||
error[test-diagnostic]: main diagnostic message
|
||||
--> animals:3:1
|
||||
|
|
||||
@@ -1998,7 +1998,7 @@ watermelon
|
||||
diag.sub(env.sub_warn().primary("animals", "11", "11", "").build());
|
||||
insta::assert_snapshot!(
|
||||
env.render(&diag),
|
||||
@r"
|
||||
@"
|
||||
error[test-diagnostic]: main diagnostic message
|
||||
--> animals:3:1
|
||||
|
|
||||
@@ -2037,7 +2037,7 @@ watermelon
|
||||
diag.sub(env.sub_warn().primary("fruits", "3", "3", "").build());
|
||||
insta::assert_snapshot!(
|
||||
env.render(&diag),
|
||||
@r"
|
||||
@"
|
||||
error[test-diagnostic]: main diagnostic message
|
||||
--> animals:3:1
|
||||
|
|
||||
@@ -2085,7 +2085,7 @@ watermelon
|
||||
diag.sub(env.sub_warn().secondary("animals", "3", "3", "").build());
|
||||
insta::assert_snapshot!(
|
||||
env.render(&diag),
|
||||
@r"
|
||||
@"
|
||||
error[test-diagnostic]: main diagnostic message
|
||||
--> animals:3:1
|
||||
|
|
||||
@@ -2121,7 +2121,7 @@ watermelon
|
||||
let diag = env.err().primary("animals", "5", "6", "").build();
|
||||
insta::assert_snapshot!(
|
||||
env.render(&diag),
|
||||
@r"
|
||||
@"
|
||||
error[test-diagnostic]: main diagnostic message
|
||||
--> animals:5:1
|
||||
|
|
||||
@@ -2144,7 +2144,7 @@ watermelon
|
||||
let diag = env.err().primary("animals", "5", "7:0", "").build();
|
||||
insta::assert_snapshot!(
|
||||
env.render(&diag),
|
||||
@r"
|
||||
@"
|
||||
error[test-diagnostic]: main diagnostic message
|
||||
--> animals:5:1
|
||||
|
|
||||
@@ -2164,7 +2164,7 @@ watermelon
|
||||
let diag = env.err().primary("animals", "5", "7:1", "").build();
|
||||
insta::assert_snapshot!(
|
||||
env.render(&diag),
|
||||
@r"
|
||||
@"
|
||||
error[test-diagnostic]: main diagnostic message
|
||||
--> animals:5:1
|
||||
|
|
||||
@@ -2184,7 +2184,7 @@ watermelon
|
||||
let diag = env.err().primary("animals", "5:3", "8:8", "").build();
|
||||
insta::assert_snapshot!(
|
||||
env.render(&diag),
|
||||
@r"
|
||||
@"
|
||||
error[test-diagnostic]: main diagnostic message
|
||||
--> animals:5:4
|
||||
|
|
||||
@@ -2206,7 +2206,7 @@ watermelon
|
||||
let diag = env.err().secondary("animals", "5:3", "8:8", "").build();
|
||||
insta::assert_snapshot!(
|
||||
env.render(&diag),
|
||||
@r"
|
||||
@"
|
||||
error[test-diagnostic]: main diagnostic message
|
||||
--> animals:5:4
|
||||
|
|
||||
@@ -2238,7 +2238,7 @@ watermelon
|
||||
.build();
|
||||
insta::assert_snapshot!(
|
||||
env.render(&diag),
|
||||
@r"
|
||||
@"
|
||||
error[test-diagnostic]: main diagnostic message
|
||||
--> animals:4:1
|
||||
|
|
||||
@@ -2267,7 +2267,7 @@ watermelon
|
||||
.build();
|
||||
insta::assert_snapshot!(
|
||||
env.render(&diag),
|
||||
@r"
|
||||
@"
|
||||
error[test-diagnostic]: main diagnostic message
|
||||
--> animals:4:1
|
||||
|
|
||||
@@ -2298,7 +2298,7 @@ watermelon
|
||||
.build();
|
||||
insta::assert_snapshot!(
|
||||
env.render(&diag),
|
||||
@r"
|
||||
@"
|
||||
error[test-diagnostic]: main diagnostic message
|
||||
--> animals:5:1
|
||||
|
|
||||
@@ -2333,7 +2333,7 @@ watermelon
|
||||
// better using only ASCII art.
|
||||
insta::assert_snapshot!(
|
||||
env.render(&diag),
|
||||
@r"
|
||||
@"
|
||||
error[test-diagnostic]: main diagnostic message
|
||||
--> animals:5:1
|
||||
|
|
||||
@@ -2361,7 +2361,7 @@ watermelon
|
||||
.build();
|
||||
insta::assert_snapshot!(
|
||||
env.render(&diag),
|
||||
@r"
|
||||
@"
|
||||
error[test-diagnostic]: main diagnostic message
|
||||
--> animals:5:1
|
||||
|
|
||||
@@ -2393,7 +2393,7 @@ watermelon
|
||||
.build();
|
||||
insta::assert_snapshot!(
|
||||
env.render(&diag),
|
||||
@r"
|
||||
@"
|
||||
error[test-diagnostic]: main diagnostic message
|
||||
--> animals:5:3
|
||||
|
|
||||
@@ -2415,7 +2415,7 @@ watermelon
|
||||
.build();
|
||||
insta::assert_snapshot!(
|
||||
env.render(&diag),
|
||||
@r"
|
||||
@"
|
||||
error[test-diagnostic]: main diagnostic message
|
||||
--> animals:5:3
|
||||
|
|
||||
@@ -2448,7 +2448,7 @@ watermelon
|
||||
.build();
|
||||
insta::assert_snapshot!(
|
||||
env.render(&diag),
|
||||
@r"
|
||||
@"
|
||||
error[test-diagnostic]: main diagnostic message
|
||||
--> animals:8:1
|
||||
|
|
||||
@@ -2488,7 +2488,7 @@ watermelon
|
||||
.build();
|
||||
insta::assert_snapshot!(
|
||||
env.render(&diag),
|
||||
@r"
|
||||
@"
|
||||
error[test-diagnostic]: main diagnostic message
|
||||
--> animals:5:1
|
||||
|
|
||||
@@ -2532,7 +2532,7 @@ watermelon
|
||||
.build();
|
||||
insta::assert_snapshot!(
|
||||
env.render(&diag),
|
||||
@r"
|
||||
@"
|
||||
error[test-diagnostic]: main diagnostic message
|
||||
--> fruits:1:1
|
||||
|
|
||||
@@ -2567,7 +2567,7 @@ watermelon
|
||||
.build();
|
||||
insta::assert_snapshot!(
|
||||
env.render(&diag),
|
||||
@r"
|
||||
@"
|
||||
error[test-diagnostic]: main diagnostic message
|
||||
--> animals:11:1
|
||||
|
|
||||
|
||||
@@ -137,7 +137,7 @@ mod tests {
|
||||
#[test]
|
||||
fn output() {
|
||||
let (env, diagnostics) = create_diagnostics(DiagnosticFormat::Concise);
|
||||
insta::assert_snapshot!(env.render_diagnostics(&diagnostics), @r"
|
||||
insta::assert_snapshot!(env.render_diagnostics(&diagnostics), @"
|
||||
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
|
||||
undef.py:1:4: error[undefined-name] Undefined name `a`
|
||||
@@ -150,7 +150,7 @@ mod tests {
|
||||
env.hide_severity(true);
|
||||
env.show_fix_status(true);
|
||||
env.fix_applicability(Applicability::DisplayOnly);
|
||||
insta::assert_snapshot!(env.render_diagnostics(&diagnostics), @r"
|
||||
insta::assert_snapshot!(env.render_diagnostics(&diagnostics), @"
|
||||
fib.py:1:8: F401 [*] `os` imported but unused
|
||||
fib.py:6:5: F841 [*] Local variable `x` is assigned to but never used
|
||||
undef.py:1:4: F821 Undefined name `a`
|
||||
@@ -164,7 +164,7 @@ mod tests {
|
||||
env.show_fix_status(true);
|
||||
env.fix_applicability(Applicability::DisplayOnly);
|
||||
env.preview(true);
|
||||
insta::assert_snapshot!(env.render_diagnostics(&diagnostics), @r"
|
||||
insta::assert_snapshot!(env.render_diagnostics(&diagnostics), @"
|
||||
fib.py:1:8: F401 [*] `os` imported but unused
|
||||
fib.py:6:5: F841 [*] Local variable `x` is assigned to but never used
|
||||
undef.py:1:4: F821 Undefined name `a`
|
||||
@@ -177,7 +177,7 @@ mod tests {
|
||||
env.hide_severity(true);
|
||||
env.show_fix_status(true);
|
||||
env.fix_applicability(Applicability::DisplayOnly);
|
||||
insta::assert_snapshot!(env.render_diagnostics(&diagnostics), @r"
|
||||
insta::assert_snapshot!(env.render_diagnostics(&diagnostics), @"
|
||||
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
|
||||
");
|
||||
@@ -186,7 +186,7 @@ mod tests {
|
||||
#[test]
|
||||
fn syntax_errors() {
|
||||
let (env, diagnostics) = create_syntax_error_diagnostics(DiagnosticFormat::Concise);
|
||||
insta::assert_snapshot!(env.render_diagnostics(&diagnostics), @r"
|
||||
insta::assert_snapshot!(env.render_diagnostics(&diagnostics), @"
|
||||
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
|
||||
");
|
||||
@@ -195,7 +195,7 @@ mod tests {
|
||||
#[test]
|
||||
fn notebook_output() {
|
||||
let (env, diagnostics) = create_notebook_diagnostics(DiagnosticFormat::Concise);
|
||||
insta::assert_snapshot!(env.render_diagnostics(&diagnostics), @r"
|
||||
insta::assert_snapshot!(env.render_diagnostics(&diagnostics), @"
|
||||
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 3:4:5: error[unused-variable] Local variable `x` is assigned to but never used
|
||||
|
||||
@@ -14,6 +14,7 @@ use crate::diagnostic::{Span, UnifiedFile};
|
||||
use crate::file_revision::FileRevision;
|
||||
use crate::files::file_root::FileRoots;
|
||||
use crate::files::private::FileStatus;
|
||||
use crate::source::SourceText;
|
||||
use crate::system::{SystemPath, SystemPathBuf, SystemVirtualPath, SystemVirtualPathBuf};
|
||||
use crate::vendored::{VendoredPath, VendoredPathBuf};
|
||||
use crate::{Db, FxDashMap, vendored};
|
||||
@@ -323,6 +324,17 @@ pub struct File {
|
||||
/// the file has been deleted is to change the status to `Deleted`.
|
||||
#[default]
|
||||
status: FileStatus,
|
||||
|
||||
/// Overrides the result of [`source_text`](crate::source::source_text).
|
||||
///
|
||||
/// This is useful when running queries after modifying a file's content but
|
||||
/// before the content is written to disk. For example, to verify that the applied fixes
|
||||
/// didn't introduce any new errors.
|
||||
///
|
||||
/// The override gets automatically removed the next time the file changes.
|
||||
#[default]
|
||||
#[returns(ref)]
|
||||
pub source_text_override: Option<SourceText>,
|
||||
}
|
||||
|
||||
// The Salsa heap is tracked separately.
|
||||
@@ -444,20 +456,28 @@ impl File {
|
||||
_ => (FileStatus::NotFound, FileRevision::zero(), None),
|
||||
};
|
||||
|
||||
let mut clear_override = false;
|
||||
|
||||
if file.status(db) != status {
|
||||
tracing::debug!("Updating the status of `{}`", file.path(db));
|
||||
file.set_status(db).to(status);
|
||||
clear_override = true;
|
||||
}
|
||||
|
||||
if file.revision(db) != revision {
|
||||
tracing::debug!("Updating the revision of `{}`", file.path(db));
|
||||
file.set_revision(db).to(revision);
|
||||
clear_override = true;
|
||||
}
|
||||
|
||||
if file.permissions(db) != permission {
|
||||
tracing::debug!("Updating the permissions of `{}`", file.path(db));
|
||||
file.set_permissions(db).to(permission);
|
||||
}
|
||||
|
||||
if clear_override && file.source_text_override(db).is_some() {
|
||||
file.set_source_text_override(db).to(None);
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if the file exists.
|
||||
@@ -526,7 +546,7 @@ impl VirtualFile {
|
||||
}
|
||||
|
||||
/// Increments the revision of the underlying [`File`].
|
||||
fn sync(&self, db: &mut dyn Db) {
|
||||
pub fn sync(&self, db: &mut dyn Db) {
|
||||
let file = self.0;
|
||||
tracing::debug!("Updating the revision of `{}`", file.path(db));
|
||||
let current_revision = file.revision(db);
|
||||
|
||||
@@ -85,6 +85,13 @@ pub fn max_parallelism() -> NonZeroUsize {
|
||||
})
|
||||
}
|
||||
|
||||
// Use a reasonably large stack size to avoid running into stack overflows too easily. The
|
||||
// size was chosen in such a way as to still be able to handle large expressions involving
|
||||
// binary operators (x + x + … + x) both during the AST walk in semantic index building as
|
||||
// well as during type checking. Using this stack size, we can handle handle expressions
|
||||
// that are several times larger than the corresponding limits in existing type checkers.
|
||||
pub const STACK_SIZE: usize = 16 * 1024 * 1024;
|
||||
|
||||
/// Trait for types that can provide Rust documentation.
|
||||
///
|
||||
/// Use `derive(RustDoc)` to automatically implement this trait for types that have a static string documentation.
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
use std::borrow::Cow;
|
||||
use std::ops::Deref;
|
||||
use std::sync::Arc;
|
||||
|
||||
use ruff_diagnostics::SourceMap;
|
||||
use ruff_notebook::Notebook;
|
||||
use ruff_python_ast::PySourceType;
|
||||
use ruff_source_file::LineIndex;
|
||||
@@ -16,6 +18,10 @@ pub fn source_text(db: &dyn Db, file: File) -> SourceText {
|
||||
let _span = tracing::trace_span!("source_text", file = %path).entered();
|
||||
let mut read_error = None;
|
||||
|
||||
if let Some(source) = file.source_text_override(db) {
|
||||
return source.clone();
|
||||
}
|
||||
|
||||
let kind = if is_notebook(db.system(), path) {
|
||||
file.read_to_notebook(db)
|
||||
.unwrap_or_else(|error| {
|
||||
@@ -90,6 +96,45 @@ impl SourceText {
|
||||
pub fn read_error(&self) -> Option<&SourceTextError> {
|
||||
self.inner.read_error.as_ref()
|
||||
}
|
||||
|
||||
/// Returns a new instance for this file with the updated source text (Python code).
|
||||
///
|
||||
/// Uses the `source_map` to preserve the cell-boundaries.
|
||||
#[must_use]
|
||||
pub fn with_text(&self, new_text: String, source_map: &SourceMap) -> Self {
|
||||
let new_kind = match &self.inner.kind {
|
||||
SourceTextKind::Text(_) => SourceTextKind::Text(new_text),
|
||||
|
||||
SourceTextKind::Notebook { notebook } => {
|
||||
let mut new_notebook = notebook.as_ref().clone();
|
||||
new_notebook.update(source_map, new_text);
|
||||
SourceTextKind::Notebook {
|
||||
notebook: new_notebook.into(),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Self {
|
||||
inner: Arc::new(SourceTextInner {
|
||||
kind: new_kind,
|
||||
read_error: self.inner.read_error.clone(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_bytes(&self) -> Cow<'_, [u8]> {
|
||||
match &self.inner.kind {
|
||||
SourceTextKind::Text(source) => Cow::Borrowed(source.as_bytes()),
|
||||
SourceTextKind::Notebook { notebook } => {
|
||||
let mut output: Vec<u8> = Vec::new();
|
||||
notebook
|
||||
.write(&mut output)
|
||||
.expect("writing to a Vec should never fail");
|
||||
|
||||
Cow::Owned(output)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for SourceText {
|
||||
@@ -117,13 +162,13 @@ impl std::fmt::Debug for SourceText {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, get_size2::GetSize)]
|
||||
#[derive(Eq, PartialEq, get_size2::GetSize, Clone)]
|
||||
struct SourceTextInner {
|
||||
kind: SourceTextKind,
|
||||
read_error: Option<SourceTextError>,
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, get_size2::GetSize)]
|
||||
#[derive(Eq, PartialEq, get_size2::GetSize, Clone)]
|
||||
enum SourceTextKind {
|
||||
Text(String),
|
||||
Notebook {
|
||||
|
||||
@@ -271,7 +271,12 @@ pub trait WritableSystem: System {
|
||||
fn create_new_file(&self, path: &SystemPath) -> Result<()>;
|
||||
|
||||
/// Writes the given content to the file at the given path.
|
||||
fn write_file(&self, path: &SystemPath, content: &str) -> Result<()>;
|
||||
fn write_file(&self, path: &SystemPath, content: &str) -> Result<()> {
|
||||
self.write_file_bytes(path, content.as_bytes())
|
||||
}
|
||||
|
||||
/// Writes the given content to the file at the given path.
|
||||
fn write_file_bytes(&self, path: &SystemPath, content: &[u8]) -> Result<()>;
|
||||
|
||||
/// Creates a directory at `path` as well as any intermediate directories.
|
||||
fn create_directory_all(&self, path: &SystemPath) -> Result<()>;
|
||||
@@ -311,6 +316,8 @@ pub trait WritableSystem: System {
|
||||
|
||||
Ok(Some(cache_path))
|
||||
}
|
||||
|
||||
fn dyn_clone(&self) -> Box<dyn WritableSystem>;
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
|
||||
@@ -122,7 +122,9 @@ impl MemoryFileSystem {
|
||||
let entry = by_path.get(&normalized).ok_or_else(not_found)?;
|
||||
|
||||
match entry {
|
||||
Entry::File(file) => Ok(file.content.clone()),
|
||||
Entry::File(file) => {
|
||||
String::from_utf8(file.content.to_vec()).map_err(|_| invalid_utf8())
|
||||
}
|
||||
Entry::Directory(_) => Err(is_a_directory()),
|
||||
}
|
||||
}
|
||||
@@ -139,7 +141,7 @@ impl MemoryFileSystem {
|
||||
.get(&path.as_ref().to_path_buf())
|
||||
.ok_or_else(not_found)?;
|
||||
|
||||
Ok(file.content.clone())
|
||||
String::from_utf8(file.content.to_vec()).map_err(|_| invalid_utf8())
|
||||
}
|
||||
|
||||
pub fn exists(&self, path: &SystemPath) -> bool {
|
||||
@@ -161,7 +163,7 @@ impl MemoryFileSystem {
|
||||
match by_path.entry(normalized) {
|
||||
btree_map::Entry::Vacant(entry) => {
|
||||
entry.insert(Entry::File(File {
|
||||
content: String::new(),
|
||||
content: Box::default(),
|
||||
last_modified: file_time_now(),
|
||||
}));
|
||||
|
||||
@@ -177,13 +179,17 @@ impl MemoryFileSystem {
|
||||
/// Stores a new file in the file system.
|
||||
///
|
||||
/// The operation overrides the content for an existing file with the same normalized `path`.
|
||||
pub fn write_file(&self, path: impl AsRef<SystemPath>, content: impl ToString) -> Result<()> {
|
||||
pub fn write_file(
|
||||
&self,
|
||||
path: impl AsRef<SystemPath>,
|
||||
content: impl AsRef<[u8]>,
|
||||
) -> Result<()> {
|
||||
let mut by_path = self.inner.by_path.write().unwrap();
|
||||
|
||||
let normalized = self.normalize_path(path.as_ref());
|
||||
|
||||
let file = get_or_create_file(&mut by_path, &normalized)?;
|
||||
file.content = content.to_string();
|
||||
file.content = content.as_ref().to_vec().into_boxed_slice();
|
||||
file.last_modified = file_time_now();
|
||||
|
||||
Ok(())
|
||||
@@ -214,7 +220,7 @@ impl MemoryFileSystem {
|
||||
pub fn write_file_all(
|
||||
&self,
|
||||
path: impl AsRef<SystemPath>,
|
||||
content: impl ToString,
|
||||
content: impl AsRef<[u8]>,
|
||||
) -> Result<()> {
|
||||
let path = path.as_ref();
|
||||
|
||||
@@ -228,19 +234,24 @@ impl MemoryFileSystem {
|
||||
/// Stores a new virtual file in the file system.
|
||||
///
|
||||
/// The operation overrides the content for an existing virtual file with the same `path`.
|
||||
pub fn write_virtual_file(&self, path: impl AsRef<SystemVirtualPath>, content: impl ToString) {
|
||||
pub fn write_virtual_file(
|
||||
&self,
|
||||
path: impl AsRef<SystemVirtualPath>,
|
||||
content: impl AsRef<[u8]>,
|
||||
) {
|
||||
let path = path.as_ref();
|
||||
let mut virtual_files = self.inner.virtual_files.write().unwrap();
|
||||
let content = content.as_ref().to_vec().into_boxed_slice();
|
||||
|
||||
match virtual_files.entry(path.to_path_buf()) {
|
||||
std::collections::hash_map::Entry::Vacant(entry) => {
|
||||
entry.insert(File {
|
||||
content: content.to_string(),
|
||||
content,
|
||||
last_modified: file_time_now(),
|
||||
});
|
||||
}
|
||||
std::collections::hash_map::Entry::Occupied(mut entry) => {
|
||||
entry.get_mut().content = content.to_string();
|
||||
entry.get_mut().content = content;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -468,7 +479,7 @@ impl Entry {
|
||||
|
||||
#[derive(Debug)]
|
||||
struct File {
|
||||
content: String,
|
||||
content: Box<[u8]>,
|
||||
last_modified: FileTime,
|
||||
}
|
||||
|
||||
@@ -497,6 +508,13 @@ fn directory_not_empty() -> std::io::Error {
|
||||
std::io::Error::other("directory not empty")
|
||||
}
|
||||
|
||||
fn invalid_utf8() -> std::io::Error {
|
||||
std::io::Error::new(
|
||||
std::io::ErrorKind::InvalidData,
|
||||
"stream did not contain valid UTF-8",
|
||||
)
|
||||
}
|
||||
|
||||
fn create_dir_all(
|
||||
paths: &mut RwLockWriteGuard<BTreeMap<Utf8PathBuf, Entry>>,
|
||||
normalized: &Utf8Path,
|
||||
@@ -533,7 +551,7 @@ fn get_or_create_file<'a>(
|
||||
|
||||
let entry = paths.entry(normalized.to_path_buf()).or_insert_with(|| {
|
||||
Entry::File(File {
|
||||
content: String::new(),
|
||||
content: Box::default(),
|
||||
last_modified: file_time_now(),
|
||||
})
|
||||
});
|
||||
@@ -844,7 +862,7 @@ mod tests {
|
||||
let fs = with_files(["c.py"]);
|
||||
|
||||
let error = fs
|
||||
.write_file(SystemPath::new("a/b.py"), "content".to_string())
|
||||
.write_file(SystemPath::new("a/b.py"), "content")
|
||||
.unwrap_err();
|
||||
|
||||
assert_eq!(error.kind(), ErrorKind::NotFound);
|
||||
@@ -855,7 +873,7 @@ mod tests {
|
||||
let fs = with_files(["a/b.py"]);
|
||||
|
||||
let error = fs
|
||||
.write_file_all(SystemPath::new("a/b.py/c"), "content".to_string())
|
||||
.write_file_all(SystemPath::new("a/b.py/c"), "content")
|
||||
.unwrap_err();
|
||||
|
||||
assert_eq!(error.kind(), ErrorKind::Other);
|
||||
@@ -878,7 +896,7 @@ mod tests {
|
||||
let fs = MemoryFileSystem::new();
|
||||
let path = SystemPath::new("a.py");
|
||||
|
||||
fs.write_file_all(path, "Test content".to_string())?;
|
||||
fs.write_file_all(path, "Test content")?;
|
||||
|
||||
assert_eq!(fs.read_to_string(path)?, "Test content");
|
||||
|
||||
@@ -915,9 +933,7 @@ mod tests {
|
||||
|
||||
fs.create_directory_all("a")?;
|
||||
|
||||
let error = fs
|
||||
.write_file(SystemPath::new("a"), "content".to_string())
|
||||
.unwrap_err();
|
||||
let error = fs.write_file(SystemPath::new("a"), "content").unwrap_err();
|
||||
|
||||
assert_eq!(error.kind(), ErrorKind::Other);
|
||||
|
||||
|
||||
@@ -361,13 +361,17 @@ impl WritableSystem for OsSystem {
|
||||
std::fs::File::create_new(path).map(drop)
|
||||
}
|
||||
|
||||
fn write_file(&self, path: &SystemPath, content: &str) -> Result<()> {
|
||||
fn write_file_bytes(&self, path: &SystemPath, content: &[u8]) -> Result<()> {
|
||||
std::fs::write(path.as_std_path(), content)
|
||||
}
|
||||
|
||||
fn create_directory_all(&self, path: &SystemPath) -> Result<()> {
|
||||
std::fs::create_dir_all(path.as_std_path())
|
||||
}
|
||||
|
||||
fn dyn_clone(&self) -> Box<dyn WritableSystem> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for OsSystem {
|
||||
|
||||
@@ -205,13 +205,17 @@ impl WritableSystem for TestSystem {
|
||||
self.system().create_new_file(path)
|
||||
}
|
||||
|
||||
fn write_file(&self, path: &SystemPath, content: &str) -> Result<()> {
|
||||
self.system().write_file(path, content)
|
||||
fn write_file_bytes(&self, path: &SystemPath, content: &[u8]) -> Result<()> {
|
||||
self.system().write_file_bytes(path, content)
|
||||
}
|
||||
|
||||
fn create_directory_all(&self, path: &SystemPath) -> Result<()> {
|
||||
self.system().create_directory_all(path)
|
||||
}
|
||||
|
||||
fn dyn_clone(&self) -> Box<dyn WritableSystem> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
/// Extension trait for databases that use a [`WritableSystem`].
|
||||
@@ -283,7 +287,11 @@ pub trait DbWithTestSystem: Db + Sized {
|
||||
///
|
||||
/// ## Panics
|
||||
/// If the db isn't using the [`InMemorySystem`].
|
||||
fn write_virtual_file(&mut self, path: impl AsRef<SystemVirtualPath>, content: impl ToString) {
|
||||
fn write_virtual_file(
|
||||
&mut self,
|
||||
path: impl AsRef<SystemVirtualPath>,
|
||||
content: impl AsRef<[u8]>,
|
||||
) {
|
||||
let path = path.as_ref();
|
||||
self.test_system()
|
||||
.memory_file_system()
|
||||
@@ -322,23 +330,23 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
#[derive(Clone, Default, Debug)]
|
||||
pub struct InMemorySystem {
|
||||
user_config_directory: Mutex<Option<SystemPathBuf>>,
|
||||
user_config_directory: Arc<Mutex<Option<SystemPathBuf>>>,
|
||||
memory_fs: MemoryFileSystem,
|
||||
}
|
||||
|
||||
impl InMemorySystem {
|
||||
pub fn new(cwd: SystemPathBuf) -> Self {
|
||||
Self {
|
||||
user_config_directory: Mutex::new(None),
|
||||
user_config_directory: Mutex::new(None).into(),
|
||||
memory_fs: MemoryFileSystem::with_current_directory(cwd),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_memory_fs(memory_fs: MemoryFileSystem) -> Self {
|
||||
Self {
|
||||
user_config_directory: Mutex::new(None),
|
||||
user_config_directory: Mutex::new(None).into(),
|
||||
memory_fs,
|
||||
}
|
||||
}
|
||||
@@ -440,10 +448,7 @@ impl System for InMemorySystem {
|
||||
}
|
||||
|
||||
fn dyn_clone(&self) -> Box<dyn System> {
|
||||
Box::new(Self {
|
||||
user_config_directory: Mutex::new(self.user_config_directory.lock().unwrap().clone()),
|
||||
memory_fs: self.memory_fs.clone(),
|
||||
})
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -452,11 +457,15 @@ impl WritableSystem for InMemorySystem {
|
||||
self.memory_fs.create_new_file(path)
|
||||
}
|
||||
|
||||
fn write_file(&self, path: &SystemPath, content: &str) -> Result<()> {
|
||||
fn write_file_bytes(&self, path: &SystemPath, content: &[u8]) -> Result<()> {
|
||||
self.memory_fs.write_file(path, content)
|
||||
}
|
||||
|
||||
fn create_directory_all(&self, path: &SystemPath) -> Result<()> {
|
||||
self.memory_fs.create_directory_all(path)
|
||||
}
|
||||
|
||||
fn dyn_clone(&self) -> Box<dyn WritableSystem> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -619,19 +619,19 @@ pub(crate) mod tests {
|
||||
fn read_directory_stdlib() {
|
||||
let mock_typeshed = mock_typeshed();
|
||||
|
||||
assert_snapshot!(readdir_snapshot(&mock_typeshed, "stdlib"), @r"
|
||||
assert_snapshot!(readdir_snapshot(&mock_typeshed, "stdlib"), @"
|
||||
vendored://stdlib/asyncio/
|
||||
vendored://stdlib/functools.pyi
|
||||
");
|
||||
assert_snapshot!(readdir_snapshot(&mock_typeshed, "stdlib/"), @r"
|
||||
assert_snapshot!(readdir_snapshot(&mock_typeshed, "stdlib/"), @"
|
||||
vendored://stdlib/asyncio/
|
||||
vendored://stdlib/functools.pyi
|
||||
");
|
||||
assert_snapshot!(readdir_snapshot(&mock_typeshed, "./stdlib"), @r"
|
||||
assert_snapshot!(readdir_snapshot(&mock_typeshed, "./stdlib"), @"
|
||||
vendored://stdlib/asyncio/
|
||||
vendored://stdlib/functools.pyi
|
||||
");
|
||||
assert_snapshot!(readdir_snapshot(&mock_typeshed, "./stdlib/"), @r"
|
||||
assert_snapshot!(readdir_snapshot(&mock_typeshed, "./stdlib/"), @"
|
||||
vendored://stdlib/asyncio/
|
||||
vendored://stdlib/functools.pyi
|
||||
");
|
||||
|
||||
@@ -13,7 +13,10 @@ impl<T, C> AsFormat<C> for &T
|
||||
where
|
||||
T: AsFormat<C>,
|
||||
{
|
||||
type Format<'a> = T::Format<'a> where Self: 'a;
|
||||
type Format<'a>
|
||||
= T::Format<'a>
|
||||
where
|
||||
Self: 'a;
|
||||
|
||||
fn format(&self) -> Self::Format<'_> {
|
||||
AsFormat::format(&**self)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ruff_linter"
|
||||
version = "0.14.10"
|
||||
version = "0.14.11"
|
||||
publish = false
|
||||
authors = { workspace = true }
|
||||
edition = { workspace = true }
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
---
|
||||
source: crates/ruff_linter/src/comments/shebang.rs
|
||||
expression: "ShebangDirective::try_extract(source)"
|
||||
snapshot_kind: text
|
||||
---
|
||||
None
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
---
|
||||
source: crates/ruff_linter/src/comments/shebang.rs
|
||||
expression: "ShebangDirective::try_extract(source)"
|
||||
snapshot_kind: text
|
||||
---
|
||||
None
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
---
|
||||
source: crates/ruff_linter/src/comments/shebang.rs
|
||||
expression: "ShebangDirective::try_extract(source)"
|
||||
snapshot_kind: text
|
||||
---
|
||||
Some(
|
||||
ShebangDirective(
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
---
|
||||
source: crates/ruff_linter/src/comments/shebang.rs
|
||||
expression: "ShebangDirective::try_extract(source)"
|
||||
snapshot_kind: text
|
||||
---
|
||||
Some(
|
||||
ShebangDirective(
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
---
|
||||
source: crates/ruff_linter/src/comments/shebang.rs
|
||||
expression: "ShebangDirective::try_extract(source)"
|
||||
snapshot_kind: text
|
||||
---
|
||||
None
|
||||
|
||||
@@ -26,6 +26,7 @@ use crate::doc_lines::{doc_lines_from_ast, doc_lines_from_tokens};
|
||||
use crate::fix::{FixResult, fix_file};
|
||||
use crate::noqa::add_noqa;
|
||||
use crate::package::PackageRoot;
|
||||
use crate::preview::is_py315_support_enabled;
|
||||
use crate::registry::Rule;
|
||||
#[cfg(any(feature = "test-rules", test))]
|
||||
use crate::rules::ruff::rules::test_rules::{self, TEST_RULES, TestRule};
|
||||
@@ -33,7 +34,7 @@ use crate::settings::types::UnsafeFixes;
|
||||
use crate::settings::{LinterSettings, TargetVersion, flags};
|
||||
use crate::source_kind::SourceKind;
|
||||
use crate::suppression::Suppressions;
|
||||
use crate::{Locator, directives, fs};
|
||||
use crate::{Locator, directives, fs, warn_user_once};
|
||||
|
||||
pub(crate) mod float;
|
||||
|
||||
@@ -450,6 +451,14 @@ pub fn lint_only(
|
||||
) -> LinterResult {
|
||||
let target_version = settings.resolve_target_version(path);
|
||||
|
||||
if matches!(target_version.linter_version(), PythonVersion::PY315)
|
||||
&& !is_py315_support_enabled(settings)
|
||||
{
|
||||
warn_user_once!(
|
||||
"Support for Python 3.15 is under development and may be unstable. Enable `preview` to remove this warning."
|
||||
);
|
||||
}
|
||||
|
||||
let parsed = source.into_parsed(source_kind, source_type, target_version.parser_version());
|
||||
|
||||
// Map row and column locations to byte slices (lazily).
|
||||
@@ -555,6 +564,14 @@ pub fn lint_fix<'a>(
|
||||
|
||||
let target_version = settings.resolve_target_version(path);
|
||||
|
||||
if matches!(target_version.linter_version(), PythonVersion::PY315)
|
||||
&& !is_py315_support_enabled(settings)
|
||||
{
|
||||
warn_user_once!(
|
||||
"Support for Python 3.15 is under development and may be unstable. Enable `preview` to remove this warning."
|
||||
);
|
||||
}
|
||||
|
||||
// Continuously fix until the source code stabilizes.
|
||||
loop {
|
||||
// Parse once.
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
---
|
||||
source: crates/ruff_linter/src/message/grouped.rs
|
||||
expression: content
|
||||
snapshot_kind: text
|
||||
---
|
||||
fib.py:
|
||||
1:8 F401 `os` imported but unused
|
||||
|
||||
@@ -1326,7 +1326,7 @@ mod tests {
|
||||
fn noqa_all() {
|
||||
let source = "# noqa";
|
||||
let directive = lex_inline_noqa(TextRange::up_to(source.text_len()), source);
|
||||
assert_debug_snapshot!(directive, @r"
|
||||
assert_debug_snapshot!(directive, @"
|
||||
Ok(
|
||||
Some(
|
||||
NoqaLexerOutput {
|
||||
@@ -1347,7 +1347,7 @@ mod tests {
|
||||
fn noqa_no_code() {
|
||||
let source = "# noqa:";
|
||||
let directive = lex_inline_noqa(TextRange::up_to(source.text_len()), source);
|
||||
assert_debug_snapshot!(directive, @r"
|
||||
assert_debug_snapshot!(directive, @"
|
||||
Err(
|
||||
MissingCodes,
|
||||
)
|
||||
@@ -1359,7 +1359,7 @@ mod tests {
|
||||
fn noqa_no_code_invalid_suffix() {
|
||||
let source = "# noqa: foo";
|
||||
let directive = lex_inline_noqa(TextRange::up_to(source.text_len()), source);
|
||||
assert_debug_snapshot!(directive, @r"
|
||||
assert_debug_snapshot!(directive, @"
|
||||
Err(
|
||||
MissingCodes,
|
||||
)
|
||||
@@ -1371,7 +1371,7 @@ mod tests {
|
||||
fn noqa_no_code_trailing_content() {
|
||||
let source = "# noqa: # Foo";
|
||||
let directive = lex_inline_noqa(TextRange::up_to(source.text_len()), source);
|
||||
assert_debug_snapshot!(directive, @r"
|
||||
assert_debug_snapshot!(directive, @"
|
||||
Err(
|
||||
MissingCodes,
|
||||
)
|
||||
@@ -1383,7 +1383,7 @@ mod tests {
|
||||
fn malformed_code_1() {
|
||||
let source = "# noqa: F";
|
||||
let directive = lex_inline_noqa(TextRange::up_to(source.text_len()), source);
|
||||
assert_debug_snapshot!(directive, @r"
|
||||
assert_debug_snapshot!(directive, @"
|
||||
Err(
|
||||
MissingCodes,
|
||||
)
|
||||
@@ -1422,7 +1422,7 @@ mod tests {
|
||||
fn malformed_code_3() {
|
||||
let source = "# noqa: RUF001F";
|
||||
let directive = lex_inline_noqa(TextRange::up_to(source.text_len()), source);
|
||||
assert_debug_snapshot!(directive, @r"
|
||||
assert_debug_snapshot!(directive, @"
|
||||
Err(
|
||||
InvalidCodeSuffix,
|
||||
)
|
||||
@@ -1492,7 +1492,7 @@ mod tests {
|
||||
fn noqa_all_case_insensitive() {
|
||||
let source = "# NOQA";
|
||||
let directive = lex_inline_noqa(TextRange::up_to(source.text_len()), source);
|
||||
assert_debug_snapshot!(directive, @r"
|
||||
assert_debug_snapshot!(directive, @"
|
||||
Ok(
|
||||
Some(
|
||||
NoqaLexerOutput {
|
||||
@@ -1625,7 +1625,7 @@ mod tests {
|
||||
fn noqa_all_no_space() {
|
||||
let source = "#noqa";
|
||||
let directive = lex_inline_noqa(TextRange::up_to(source.text_len()), source);
|
||||
assert_debug_snapshot!(directive, @r"
|
||||
assert_debug_snapshot!(directive, @"
|
||||
Ok(
|
||||
Some(
|
||||
NoqaLexerOutput {
|
||||
@@ -1704,7 +1704,7 @@ mod tests {
|
||||
fn noqa_all_multi_space() {
|
||||
let source = "# noqa";
|
||||
let directive = lex_inline_noqa(TextRange::up_to(source.text_len()), source);
|
||||
assert_debug_snapshot!(directive, @r"
|
||||
assert_debug_snapshot!(directive, @"
|
||||
Ok(
|
||||
Some(
|
||||
NoqaLexerOutput {
|
||||
@@ -1837,7 +1837,7 @@ mod tests {
|
||||
fn noqa_all_leading_comment() {
|
||||
let source = "# Some comment describing the noqa # noqa";
|
||||
let directive = lex_inline_noqa(TextRange::up_to(source.text_len()), source);
|
||||
assert_debug_snapshot!(directive, @r"
|
||||
assert_debug_snapshot!(directive, @"
|
||||
Ok(
|
||||
Some(
|
||||
NoqaLexerOutput {
|
||||
@@ -1916,7 +1916,7 @@ mod tests {
|
||||
fn noqa_all_trailing_comment() {
|
||||
let source = "# noqa # Some comment describing the noqa";
|
||||
let directive = lex_inline_noqa(TextRange::up_to(source.text_len()), source);
|
||||
assert_debug_snapshot!(directive, @r"
|
||||
assert_debug_snapshot!(directive, @"
|
||||
Ok(
|
||||
Some(
|
||||
NoqaLexerOutput {
|
||||
@@ -1995,7 +1995,7 @@ mod tests {
|
||||
fn noqa_invalid_codes() {
|
||||
let source = "# noqa: unused-import, F401, some other code";
|
||||
let directive = lex_inline_noqa(TextRange::up_to(source.text_len()), source);
|
||||
assert_debug_snapshot!(directive, @r"
|
||||
assert_debug_snapshot!(directive, @"
|
||||
Err(
|
||||
MissingCodes,
|
||||
)
|
||||
@@ -2139,7 +2139,7 @@ mod tests {
|
||||
fn noqa_code_invalid_code_suffix() {
|
||||
let source = "# noqa: F401abc";
|
||||
let directive = lex_inline_noqa(TextRange::up_to(source.text_len()), source);
|
||||
assert_debug_snapshot!(directive, @r"
|
||||
assert_debug_snapshot!(directive, @"
|
||||
Err(
|
||||
InvalidCodeSuffix,
|
||||
)
|
||||
@@ -2151,7 +2151,7 @@ mod tests {
|
||||
fn noqa_invalid_suffix() {
|
||||
let source = "# noqa[F401]";
|
||||
let directive = lex_inline_noqa(TextRange::up_to(source.text_len()), source);
|
||||
assert_debug_snapshot!(directive, @r"
|
||||
assert_debug_snapshot!(directive, @"
|
||||
Err(
|
||||
InvalidSuffix,
|
||||
)
|
||||
@@ -2163,7 +2163,7 @@ mod tests {
|
||||
fn flake8_exemption_all() {
|
||||
let source = "# flake8: noqa";
|
||||
let exemption = lex_file_exemption(TextRange::up_to(source.text_len()), source);
|
||||
assert_debug_snapshot!(exemption, @r"
|
||||
assert_debug_snapshot!(exemption, @"
|
||||
Ok(
|
||||
Some(
|
||||
NoqaLexerOutput {
|
||||
@@ -2184,7 +2184,7 @@ mod tests {
|
||||
fn flake8_noqa_no_code() {
|
||||
let source = "# flake8: noqa:";
|
||||
let exemption = lex_file_exemption(TextRange::up_to(source.text_len()), source);
|
||||
assert_debug_snapshot!(exemption, @r"
|
||||
assert_debug_snapshot!(exemption, @"
|
||||
Err(
|
||||
MissingCodes,
|
||||
)
|
||||
@@ -2196,7 +2196,7 @@ mod tests {
|
||||
fn flake8_noqa_no_code_invalid_suffix() {
|
||||
let source = "# flake8: noqa: foo";
|
||||
let exemption = lex_file_exemption(TextRange::up_to(source.text_len()), source);
|
||||
assert_debug_snapshot!(exemption, @r"
|
||||
assert_debug_snapshot!(exemption, @"
|
||||
Err(
|
||||
MissingCodes,
|
||||
)
|
||||
@@ -2208,7 +2208,7 @@ mod tests {
|
||||
fn flake8_noqa_no_code_trailing_content() {
|
||||
let source = "# flake8: noqa: # Foo";
|
||||
let exemption = lex_file_exemption(TextRange::up_to(source.text_len()), source);
|
||||
assert_debug_snapshot!(exemption, @r"
|
||||
assert_debug_snapshot!(exemption, @"
|
||||
Err(
|
||||
MissingCodes,
|
||||
)
|
||||
@@ -2220,7 +2220,7 @@ mod tests {
|
||||
fn flake8_malformed_code_1() {
|
||||
let source = "# flake8: noqa: F";
|
||||
let directive = lex_file_exemption(TextRange::up_to(source.text_len()), source);
|
||||
assert_debug_snapshot!(directive, @r"
|
||||
assert_debug_snapshot!(directive, @"
|
||||
Err(
|
||||
MissingCodes,
|
||||
)
|
||||
@@ -2259,7 +2259,7 @@ mod tests {
|
||||
fn flake8_malformed_code_3() {
|
||||
let source = "# flake8: noqa: RUF001F";
|
||||
let directive = lex_file_exemption(TextRange::up_to(source.text_len()), source);
|
||||
assert_debug_snapshot!(directive, @r"
|
||||
assert_debug_snapshot!(directive, @"
|
||||
Err(
|
||||
InvalidCodeSuffix,
|
||||
)
|
||||
@@ -2271,7 +2271,7 @@ mod tests {
|
||||
fn ruff_exemption_all() {
|
||||
let source = "# ruff: noqa";
|
||||
let exemption = lex_file_exemption(TextRange::up_to(source.text_len()), source);
|
||||
assert_debug_snapshot!(exemption, @r"
|
||||
assert_debug_snapshot!(exemption, @"
|
||||
Ok(
|
||||
Some(
|
||||
NoqaLexerOutput {
|
||||
@@ -2292,7 +2292,7 @@ mod tests {
|
||||
fn ruff_noqa_no_code() {
|
||||
let source = "# ruff: noqa:";
|
||||
let exemption = lex_file_exemption(TextRange::up_to(source.text_len()), source);
|
||||
assert_debug_snapshot!(exemption, @r"
|
||||
assert_debug_snapshot!(exemption, @"
|
||||
Err(
|
||||
MissingCodes,
|
||||
)
|
||||
@@ -2304,7 +2304,7 @@ mod tests {
|
||||
fn ruff_noqa_no_code_invalid_suffix() {
|
||||
let source = "# ruff: noqa: foo";
|
||||
let exemption = lex_file_exemption(TextRange::up_to(source.text_len()), source);
|
||||
assert_debug_snapshot!(exemption, @r"
|
||||
assert_debug_snapshot!(exemption, @"
|
||||
Err(
|
||||
MissingCodes,
|
||||
)
|
||||
@@ -2316,7 +2316,7 @@ mod tests {
|
||||
fn ruff_noqa_no_code_trailing_content() {
|
||||
let source = "# ruff: noqa: # Foo";
|
||||
let exemption = lex_file_exemption(TextRange::up_to(source.text_len()), source);
|
||||
assert_debug_snapshot!(exemption, @r"
|
||||
assert_debug_snapshot!(exemption, @"
|
||||
Err(
|
||||
MissingCodes,
|
||||
)
|
||||
@@ -2328,7 +2328,7 @@ mod tests {
|
||||
fn ruff_malformed_code_1() {
|
||||
let source = "# ruff: noqa: F";
|
||||
let directive = lex_file_exemption(TextRange::up_to(source.text_len()), source);
|
||||
assert_debug_snapshot!(directive, @r"
|
||||
assert_debug_snapshot!(directive, @"
|
||||
Err(
|
||||
MissingCodes,
|
||||
)
|
||||
@@ -2367,7 +2367,7 @@ mod tests {
|
||||
fn ruff_malformed_code_3() {
|
||||
let source = "# ruff: noqa: RUF001F";
|
||||
let directive = lex_file_exemption(TextRange::up_to(source.text_len()), source);
|
||||
assert_debug_snapshot!(directive, @r"
|
||||
assert_debug_snapshot!(directive, @"
|
||||
Err(
|
||||
InvalidCodeSuffix,
|
||||
)
|
||||
@@ -2379,7 +2379,7 @@ mod tests {
|
||||
fn flake8_exemption_all_no_space() {
|
||||
let source = "#flake8:noqa";
|
||||
let exemption = lex_file_exemption(TextRange::up_to(source.text_len()), source);
|
||||
assert_debug_snapshot!(exemption, @r"
|
||||
assert_debug_snapshot!(exemption, @"
|
||||
Ok(
|
||||
Some(
|
||||
NoqaLexerOutput {
|
||||
@@ -2400,7 +2400,7 @@ mod tests {
|
||||
fn ruff_exemption_all_no_space() {
|
||||
let source = "#ruff:noqa";
|
||||
let exemption = lex_file_exemption(TextRange::up_to(source.text_len()), source);
|
||||
assert_debug_snapshot!(exemption, @r"
|
||||
assert_debug_snapshot!(exemption, @"
|
||||
Ok(
|
||||
Some(
|
||||
NoqaLexerOutput {
|
||||
@@ -2619,7 +2619,7 @@ mod tests {
|
||||
fn ruff_exemption_invalid_code_suffix() {
|
||||
let source = "# ruff: noqa: F401abc";
|
||||
let exemption = lex_file_exemption(TextRange::up_to(source.text_len()), source);
|
||||
assert_debug_snapshot!(exemption, @r"
|
||||
assert_debug_snapshot!(exemption, @"
|
||||
Err(
|
||||
InvalidCodeSuffix,
|
||||
)
|
||||
@@ -2685,7 +2685,7 @@ mod tests {
|
||||
fn ruff_exemption_all_leading_comment() {
|
||||
let source = "# Leading comment # ruff: noqa";
|
||||
let exemption = lex_file_exemption(TextRange::up_to(source.text_len()), source);
|
||||
assert_debug_snapshot!(exemption, @r"
|
||||
assert_debug_snapshot!(exemption, @"
|
||||
Ok(
|
||||
Some(
|
||||
NoqaLexerOutput {
|
||||
@@ -2706,7 +2706,7 @@ mod tests {
|
||||
fn ruff_exemption_all_trailing_comment() {
|
||||
let source = "# ruff: noqa # Trailing comment";
|
||||
let exemption = lex_file_exemption(TextRange::up_to(source.text_len()), source);
|
||||
assert_debug_snapshot!(exemption, @r"
|
||||
assert_debug_snapshot!(exemption, @"
|
||||
Ok(
|
||||
Some(
|
||||
NoqaLexerOutput {
|
||||
@@ -2754,7 +2754,7 @@ mod tests {
|
||||
fn ruff_exemption_all_trailing_comment_no_space() {
|
||||
let source = "# ruff: noqa# Trailing comment";
|
||||
let exemption = lex_file_exemption(TextRange::up_to(source.text_len()), source);
|
||||
assert_debug_snapshot!(exemption, @r"
|
||||
assert_debug_snapshot!(exemption, @"
|
||||
Ok(
|
||||
Some(
|
||||
NoqaLexerOutput {
|
||||
@@ -2775,7 +2775,7 @@ mod tests {
|
||||
fn ruff_exemption_all_trailing_comment_no_hash() {
|
||||
let source = "# ruff: noqa Trailing comment";
|
||||
let exemption = lex_file_exemption(TextRange::up_to(source.text_len()), source);
|
||||
assert_debug_snapshot!(exemption, @r"
|
||||
assert_debug_snapshot!(exemption, @"
|
||||
Ok(
|
||||
Some(
|
||||
NoqaLexerOutput {
|
||||
@@ -2823,7 +2823,7 @@ mod tests {
|
||||
fn flake8_exemption_all_case_insensitive() {
|
||||
let source = "# flake8: NoQa";
|
||||
let exemption = lex_file_exemption(TextRange::up_to(source.text_len()), source);
|
||||
assert_debug_snapshot!(exemption, @r"
|
||||
assert_debug_snapshot!(exemption, @"
|
||||
Ok(
|
||||
Some(
|
||||
NoqaLexerOutput {
|
||||
@@ -2844,7 +2844,7 @@ mod tests {
|
||||
fn ruff_exemption_all_case_insensitive() {
|
||||
let source = "# ruff: NoQa";
|
||||
let exemption = lex_file_exemption(TextRange::up_to(source.text_len()), source);
|
||||
assert_debug_snapshot!(exemption, @r"
|
||||
assert_debug_snapshot!(exemption, @"
|
||||
Ok(
|
||||
Some(
|
||||
NoqaLexerOutput {
|
||||
|
||||
@@ -296,3 +296,8 @@ pub(crate) const fn is_s310_resolve_string_literal_bindings_enabled(
|
||||
pub(crate) const fn is_range_suppressions_enabled(settings: &LinterSettings) -> bool {
|
||||
settings.preview.is_enabled()
|
||||
}
|
||||
|
||||
// https://github.com/astral-sh/ruff/pull/22419
|
||||
pub(crate) const fn is_py315_support_enabled(settings: &LinterSettings) -> bool {
|
||||
settings.preview.is_enabled()
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_annotations/mod.rs
|
||||
snapshot_kind: text
|
||||
---
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_annotations/mod.rs
|
||||
snapshot_kind: text
|
||||
---
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_async/mod.rs
|
||||
snapshot_kind: text
|
||||
---
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_bandit/mod.rs
|
||||
snapshot_kind: text
|
||||
---
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_bandit/mod.rs
|
||||
snapshot_kind: text
|
||||
---
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_bandit/mod.rs
|
||||
snapshot_kind: text
|
||||
---
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_bandit/mod.rs
|
||||
snapshot_kind: text
|
||||
---
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_bandit/mod.rs
|
||||
snapshot_kind: text
|
||||
---
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_bandit/mod.rs
|
||||
snapshot_kind: text
|
||||
---
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_bandit/mod.rs
|
||||
snapshot_kind: text
|
||||
---
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_bandit/mod.rs
|
||||
snapshot_kind: text
|
||||
---
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_bandit/mod.rs
|
||||
snapshot_kind: text
|
||||
---
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_bandit/mod.rs
|
||||
snapshot_kind: text
|
||||
---
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user