Compare commits
185 Commits
github-292
...
blacklist_
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6c2d430430 | ||
|
|
b0242ccfa1 | ||
|
|
8ffc77d0ee | ||
|
|
adc677bc9c | ||
|
|
213e83aff2 | ||
|
|
4b91826a0b | ||
|
|
27903cdb11 | ||
|
|
3b1709ba1e | ||
|
|
33394e4a69 | ||
|
|
7b9bdc494a | ||
|
|
b06ca25421 | ||
|
|
c42f8b93d2 | ||
|
|
f59a22b6e5 | ||
|
|
b5edc6dfc9 | ||
|
|
626169e2ef | ||
|
|
e9f359ac5e | ||
|
|
318c2c80e2 | ||
|
|
92aa3a8178 | ||
|
|
22a4ab51f9 | ||
|
|
f70a49ed8b | ||
|
|
f039bf36a2 | ||
|
|
169dd72328 | ||
|
|
fd39ec4bdd | ||
|
|
7c0f17279c | ||
|
|
81d0884974 | ||
|
|
a45753f462 | ||
|
|
b08326162b | ||
|
|
3a65af4dae | ||
|
|
474aa0b196 | ||
|
|
4892167217 | ||
|
|
a5494b8541 | ||
|
|
9ac9a1c69e | ||
|
|
f06dff8af8 | ||
|
|
fe7443ce2f | ||
|
|
4bdb2dd362 | ||
|
|
53a4743631 | ||
|
|
4ffcd8366a | ||
|
|
dfb772c6f1 | ||
|
|
c21eb06922 | ||
|
|
16a350c731 | ||
|
|
fa04861724 | ||
|
|
404504ab41 | ||
|
|
621e4353e3 | ||
|
|
0c4926ff7b | ||
|
|
61653b9f27 | ||
|
|
8dd3959e74 | ||
|
|
50f9db21da | ||
|
|
1dd3cbd047 | ||
|
|
bd935cbd49 | ||
|
|
babd0a05ac | ||
|
|
87fab4a2e1 | ||
|
|
2e21920adf | ||
|
|
dedf4cbdeb | ||
|
|
92179e6369 | ||
|
|
33d2457909 | ||
|
|
373a77e8c2 | ||
|
|
73df267635 | ||
|
|
f5e5caaa25 | ||
|
|
d9ed0aae69 | ||
|
|
e0df62b841 | ||
|
|
bbc87b7177 | ||
|
|
667130a4c3 | ||
|
|
72febf98b7 | ||
|
|
e99e1fae2b | ||
|
|
eff84442bc | ||
|
|
aa51ecedc5 | ||
|
|
9ae9cc9d2f | ||
|
|
de1106b95a | ||
|
|
e636c5fcf0 | ||
|
|
12dfd57211 | ||
|
|
d188d242a0 | ||
|
|
57796c5e59 | ||
|
|
2545869797 | ||
|
|
58353a4bf4 | ||
|
|
a36139ae21 | ||
|
|
7e904111b1 | ||
|
|
344daebb1b | ||
|
|
432059de35 | ||
|
|
c50d6da8b4 | ||
|
|
1b738f88c4 | ||
|
|
1eff3dffa5 | ||
|
|
8c7317eb8d | ||
|
|
106a93eab0 | ||
|
|
78c2b0ac47 | ||
|
|
d5700d7c69 | ||
|
|
3a7bdb39c9 | ||
|
|
a82fe4a139 | ||
|
|
62ff3b62e3 | ||
|
|
1e5db58b7b | ||
|
|
a6e998d639 | ||
|
|
a8c1915e2e | ||
|
|
c515a1b31a | ||
|
|
aa97a092bd | ||
|
|
685c242761 | ||
|
|
b540407b74 | ||
|
|
3a5fbd6d74 | ||
|
|
227679b5cb | ||
|
|
c2750a59ab | ||
|
|
2a4d6ab3b2 | ||
|
|
7a80bcec58 | ||
|
|
297749a3a8 | ||
|
|
8955e32b5c | ||
|
|
cd192eddf9 | ||
|
|
675227db5c | ||
|
|
a65c6806a6 | ||
|
|
6c576872d4 | ||
|
|
9858df1ac9 | ||
|
|
7fb7268e8a | ||
|
|
0f78f27713 | ||
|
|
12a6fc7041 | ||
|
|
d2988043af | ||
|
|
cc8b13d3a7 | ||
|
|
1e081cf9a6 | ||
|
|
841bcf1cdd | ||
|
|
7062d1db16 | ||
|
|
8b561313aa | ||
|
|
cfa2924664 | ||
|
|
a3aeec6377 | ||
|
|
b983d5eb3f | ||
|
|
bb3bb24b59 | ||
|
|
872829ca72 | ||
|
|
2383228709 | ||
|
|
952307d39d | ||
|
|
024caca233 | ||
|
|
08ec11a31e | ||
|
|
bd05a8a74d | ||
|
|
229f1c34cb | ||
|
|
a7f3532395 | ||
|
|
3349ceb969 | ||
|
|
da1f83fe32 | ||
|
|
0a9d259f9c | ||
|
|
130e733023 | ||
|
|
ff2c0dd491 | ||
|
|
dfe1cad928 | ||
|
|
ffad0bcdaa | ||
|
|
bc869d4f52 | ||
|
|
a3de791f0a | ||
|
|
d9dfec30eb | ||
|
|
3f04def3a5 | ||
|
|
98177754de | ||
|
|
8d5374762c | ||
|
|
bad6bdda1f | ||
|
|
a5d302fcbf | ||
|
|
bced58ce40 | ||
|
|
10e252e2fb | ||
|
|
4dead7541f | ||
|
|
fea1af5a63 | ||
|
|
c0ad875339 | ||
|
|
8437399496 | ||
|
|
074f5634a5 | ||
|
|
694d41897a | ||
|
|
e1ebd9130d | ||
|
|
fc8ca6edd2 | ||
|
|
709dba2e71 | ||
|
|
d1c48016eb | ||
|
|
348a38d261 | ||
|
|
22e6778e17 | ||
|
|
30c71dc59a | ||
|
|
5d8591fec4 | ||
|
|
673aa6e90f | ||
|
|
51fe9f7d4b | ||
|
|
d7767b2bad | ||
|
|
40d3b40c14 | ||
|
|
376ef929b1 | ||
|
|
8828e12283 | ||
|
|
f13633cc9f | ||
|
|
889c05c87e | ||
|
|
bbbc44336e | ||
|
|
d216b2aaa8 | ||
|
|
367cc43c42 | ||
|
|
b5b26d5a3e | ||
|
|
dedf8aa5cc | ||
|
|
eb42ce9319 | ||
|
|
cdbe2ee496 | ||
|
|
d1288dc2b1 | ||
|
|
3bcffb5bdd | ||
|
|
98209be8aa | ||
|
|
a03fa93c3a | ||
|
|
4de3882088 | ||
|
|
3a98b68dc0 | ||
|
|
7e291e542d | ||
|
|
6f649d6579 | ||
|
|
508bc605a5 | ||
|
|
ffdf6e35e6 | ||
|
|
886992c6c2 |
@@ -1,5 +1,6 @@
|
||||
[alias]
|
||||
dev = "run --package ruff_dev --bin ruff_dev"
|
||||
benchmark = "bench -p ruff_benchmark --"
|
||||
|
||||
[target.'cfg(all())']
|
||||
rustflags = [
|
||||
|
||||
11
.github/dependabot.yml
vendored
Normal file
11
.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
day: "monday"
|
||||
time: "12:00"
|
||||
timezone: "America/New_York"
|
||||
commit-message:
|
||||
prefix: "ci(deps)"
|
||||
135
.github/workflows/benchmark.yaml
vendored
Normal file
135
.github/workflows/benchmark.yaml
vendored
Normal file
@@ -0,0 +1,135 @@
|
||||
name: Benchmark
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.event.pull_request.number || github.sha }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
run-benchmark:
|
||||
if: github.event_name == 'pull_request'
|
||||
name: "Run | ${{ matrix.os }}"
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
- name: "PR - Checkout Branch"
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
|
||||
- name: "PR - Install Rust toolchain"
|
||||
run: rustup show
|
||||
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
|
||||
- name: "PR - Build benchmarks"
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: bench
|
||||
args: -p ruff_benchmark --no-run
|
||||
|
||||
- name: "PR - Run benchmarks"
|
||||
run: cargo benchmark --save-baseline=pr
|
||||
|
||||
- name: "Main - Checkout Branch"
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
clean: false
|
||||
ref: main
|
||||
|
||||
- name: "Main - Install Rust toolchain"
|
||||
run: rustup show
|
||||
|
||||
- name: "Main - Build benchmarks"
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: bench
|
||||
args: -p ruff_benchmark --no-run
|
||||
|
||||
- name: "Main - Run benchmarks"
|
||||
run: cargo benchmark --save-baseline=main
|
||||
|
||||
- name: "Upload benchmark results"
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: benchmark-results-${{ matrix.os }}
|
||||
path: ./target/criterion
|
||||
|
||||
# Cleanup
|
||||
- name: Remove Criterion Artifact
|
||||
uses: JesseTG/rm@v1.0.3
|
||||
with:
|
||||
path: ./target/criterion
|
||||
|
||||
benchmark-compare:
|
||||
if: github.event_name == 'pull_request'
|
||||
runs-on: ubuntu-latest
|
||||
name: Compare
|
||||
needs:
|
||||
- run-benchmark
|
||||
|
||||
steps:
|
||||
- name: "Install Rust toolchain"
|
||||
run: rustup show
|
||||
|
||||
- name: "Install cargo-binstall"
|
||||
uses: taiki-e/install-action@cargo-binstall
|
||||
|
||||
- name: "Install critcmp"
|
||||
run: cargo binstall critcmp -y
|
||||
|
||||
- name: "Linux | Download PR benchmark results"
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: benchmark-results-ubuntu-latest
|
||||
path: ./target/criterion
|
||||
|
||||
- name: "Linux | Compare benchmark results"
|
||||
shell: bash
|
||||
run: |
|
||||
echo "### Benchmark" >> summary.md
|
||||
echo "#### Linux" >> summary.md
|
||||
echo "\`\`\`" >> summary.md
|
||||
critcmp main pr >> summary.md
|
||||
echo "\`\`\`" >> summary.md
|
||||
echo "" >> summary.md
|
||||
|
||||
- name: "Linux | Cleanup benchmark results"
|
||||
run: rm -rf ./target/criterion
|
||||
|
||||
- name: "Windows | Download PR benchmark results"
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: benchmark-results-windows-latest
|
||||
path: ./target/criterion
|
||||
|
||||
- name: "Windows | Compare benchmark results"
|
||||
shell: bash
|
||||
run: |
|
||||
echo "#### Windows" >> summary.md
|
||||
echo "\`\`\`" >> summary.md
|
||||
critcmp main pr >> summary.md
|
||||
echo "\`\`\`" >> summary.md
|
||||
echo "" >> summary.md
|
||||
|
||||
echo ${{ github.event.pull_request.number }} > pr-number
|
||||
|
||||
cat summary.md > $GITHUB_STEP_SUMMARY
|
||||
|
||||
- uses: actions/upload-artifact@v3
|
||||
name: Upload PR Number
|
||||
with:
|
||||
name: pr-number
|
||||
path: pr-number
|
||||
|
||||
- uses: actions/upload-artifact@v3
|
||||
name: Upload Summary
|
||||
with:
|
||||
name: summary
|
||||
path: summary.md
|
||||
114
.github/workflows/ci.yaml
vendored
114
.github/workflows/ci.yaml
vendored
@@ -17,20 +17,6 @@ env:
|
||||
RUSTUP_MAX_RETRIES: 10
|
||||
|
||||
jobs:
|
||||
cargo-build:
|
||||
name: "cargo build"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: "Install Rust toolchain"
|
||||
run: rustup show
|
||||
- uses: Swatinem/rust-cache@v1
|
||||
- run: cargo build --all
|
||||
- run: ./target/debug/ruff_dev generate-all
|
||||
- run: git diff --quiet README.md || echo "::error file=README.md::This file is outdated. Run 'cargo dev generate-all'."
|
||||
- run: git diff --quiet ruff.schema.json || echo "::error file=ruff.schema.json::This file is outdated. Run 'cargo dev generate-all'."
|
||||
- run: git diff --exit-code -- README.md ruff.schema.json docs
|
||||
|
||||
cargo-fmt:
|
||||
name: "cargo fmt"
|
||||
runs-on: ubuntu-latest
|
||||
@@ -48,7 +34,7 @@ jobs:
|
||||
- name: "Install Rust toolchain"
|
||||
run: |
|
||||
rustup component add clippy
|
||||
- uses: Swatinem/rust-cache@v1
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
- run: cargo clippy --workspace --all-targets --all-features -- -D warnings
|
||||
|
||||
cargo-clippy-wasm:
|
||||
@@ -60,8 +46,8 @@ jobs:
|
||||
run: |
|
||||
rustup component add clippy
|
||||
rustup target add wasm32-unknown-unknown
|
||||
- uses: Swatinem/rust-cache@v1
|
||||
- run: cargo clippy -p ruff --target wasm32-unknown-unknown --all-features -- -D warnings
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
- run: cargo clippy -p ruff_wasm --target wasm32-unknown-unknown --all-features -- -D warnings
|
||||
|
||||
cargo-test:
|
||||
strategy:
|
||||
@@ -73,9 +59,9 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
- name: "Install Rust toolchain"
|
||||
run: rustup show
|
||||
- uses: Swatinem/rust-cache@v1
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
- run: cargo install cargo-insta
|
||||
- run: pip install black[d]==22.12.0
|
||||
- run: pip install black[d]==23.1.0
|
||||
- name: "Run tests (Ubuntu)"
|
||||
if: ${{ matrix.os == 'ubuntu-latest' }}
|
||||
run: |
|
||||
@@ -93,6 +79,31 @@ jobs:
|
||||
env:
|
||||
# Setting RUSTDOCFLAGS because `cargo doc --check` isn't yet implemented (https://github.com/rust-lang/cargo/issues/10025).
|
||||
RUSTDOCFLAGS: "-D warnings"
|
||||
- uses: actions/upload-artifact@v3
|
||||
if: ${{ matrix.os == 'ubuntu-latest' }}
|
||||
with:
|
||||
name: ruff
|
||||
path: target/debug/ruff
|
||||
|
||||
|
||||
cargo-test-wasm:
|
||||
runs-on: ubuntu-latest
|
||||
name: "cargo test (wasm)"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: "Install Rust toolchain"
|
||||
run: rustup target add wasm32-unknown-unknown
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
cache: "npm"
|
||||
cache-dependency-path: playground/package-lock.json
|
||||
- uses: jetli/wasm-pack-action@v0.4.0
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
- name: "Run wasm-pack"
|
||||
run: |
|
||||
cd crates/ruff_wasm
|
||||
wasm-pack test --node
|
||||
|
||||
scripts:
|
||||
name: "test scripts"
|
||||
@@ -101,7 +112,7 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
- name: "Install Rust toolchain"
|
||||
run: rustup show
|
||||
- uses: Swatinem/rust-cache@v1
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
- run: ./scripts/add_rule.py --name DoTheThing --code PLC999 --linter pylint
|
||||
- run: cargo check
|
||||
- run: |
|
||||
@@ -109,21 +120,6 @@ jobs:
|
||||
./scripts/add_rule.py --name FirstRule --code TST001 --linter test
|
||||
- run: cargo check
|
||||
|
||||
maturin-build:
|
||||
name: "maturin build"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: "Install Rust toolchain"
|
||||
run: rustup show
|
||||
- uses: Swatinem/rust-cache@v1
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.11"
|
||||
- run: pip install maturin
|
||||
- run: maturin build -b bin
|
||||
- run: python scripts/transform_readme.py --target pypi
|
||||
|
||||
typos:
|
||||
name: "spell check"
|
||||
runs-on: ubuntu-latest
|
||||
@@ -132,3 +128,51 @@ jobs:
|
||||
- uses: crate-ci/typos@master
|
||||
with:
|
||||
files: .
|
||||
|
||||
ecosystem:
|
||||
name: "ecosystem"
|
||||
runs-on: ubuntu-latest
|
||||
needs: cargo-test
|
||||
# Only runs on pull requests, since that is the only we way we can find the base version for comparison.
|
||||
if: github.event_name == 'pull_request'
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.11"
|
||||
|
||||
- uses: actions/download-artifact@v3
|
||||
name: Download Ruff binary
|
||||
id: ruff-target
|
||||
with:
|
||||
name: ruff
|
||||
path: target/debug
|
||||
|
||||
- uses: dawidd6/action-download-artifact@v2
|
||||
name: Download base results
|
||||
with:
|
||||
name: ruff
|
||||
branch: ${{ github.event.pull_request.base.ref }}
|
||||
check_artifacts: true
|
||||
|
||||
- name: Run ecosystem check
|
||||
run: |
|
||||
# Make executable, since artifact download doesn't preserve this
|
||||
chmod +x ruff ${{ steps.ruff-target.outputs.download-path }}/ruff
|
||||
|
||||
scripts/check_ecosystem.py ruff ${{ steps.ruff-target.outputs.download-path }}/ruff | tee ecosystem-result
|
||||
cat ecosystem-result > $GITHUB_STEP_SUMMARY
|
||||
|
||||
echo ${{ github.event.number }} > pr-number
|
||||
|
||||
- uses: actions/upload-artifact@v3
|
||||
name: Upload PR Number
|
||||
with:
|
||||
name: pr-number
|
||||
path: pr-number
|
||||
|
||||
- uses: actions/upload-artifact@v3
|
||||
name: Upload Results
|
||||
with:
|
||||
name: ecosystem-result
|
||||
path: ecosystem-result
|
||||
|
||||
2
.github/workflows/docs.yaml
vendored
2
.github/workflows/docs.yaml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
- uses: actions/setup-python@v4
|
||||
- name: "Install Rust toolchain"
|
||||
run: rustup show
|
||||
- uses: Swatinem/rust-cache@v1
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
- name: "Install dependencies"
|
||||
run: |
|
||||
pip install -r docs/requirements.txt
|
||||
|
||||
4
.github/workflows/flake8-to-ruff.yaml
vendored
4
.github/workflows/flake8-to-ruff.yaml
vendored
@@ -133,7 +133,7 @@ jobs:
|
||||
target: ${{ matrix.target }}
|
||||
manylinux: auto
|
||||
args: --no-default-features --release --out dist -m ./${{ env.CRATE_NAME }}/Cargo.toml
|
||||
- uses: uraimo/run-on-arch-action@v2.5.0
|
||||
- uses: uraimo/run-on-arch-action@v2
|
||||
if: matrix.target != 'ppc64'
|
||||
name: Install built wheel
|
||||
with:
|
||||
@@ -206,7 +206,7 @@ jobs:
|
||||
target: ${{ matrix.platform.target }}
|
||||
manylinux: musllinux_1_2
|
||||
args: --release --out dist -m ./${{ env.CRATE_NAME }}/Cargo.toml
|
||||
- uses: uraimo/run-on-arch-action@master
|
||||
- uses: uraimo/run-on-arch-action@v2
|
||||
name: Install built wheel
|
||||
with:
|
||||
arch: ${{ matrix.platform.arch }}
|
||||
|
||||
2
.github/workflows/playground.yaml
vendored
2
.github/workflows/playground.yaml
vendored
@@ -28,7 +28,7 @@ jobs:
|
||||
- uses: jetli/wasm-pack-action@v0.4.0
|
||||
- uses: jetli/wasm-bindgen-action@v0.2.0
|
||||
- name: "Run wasm-pack"
|
||||
run: wasm-pack build --target web --out-dir ../../playground/src/pkg crates/ruff
|
||||
run: wasm-pack build --target web --out-dir ../../playground/src/pkg crates/ruff_wasm
|
||||
- name: "Install Node dependencies"
|
||||
run: npm ci
|
||||
working-directory: playground
|
||||
|
||||
84
.github/workflows/pr-comment.yaml
vendored
Normal file
84
.github/workflows/pr-comment.yaml
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
name: PR Check Comment
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: [CI, Benchmark]
|
||||
types: [completed]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
workflow_run_id:
|
||||
description: The ecosystem workflow that triggers the workflow run
|
||||
required: true
|
||||
|
||||
permissions:
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
comment:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: dawidd6/action-download-artifact@v2
|
||||
name: Download PR Number
|
||||
with:
|
||||
name: pr-number
|
||||
run_id: ${{ github.event.workflow_run.id || github.event.inputs.workflow_run_id }}
|
||||
if_no_artifact_found: ignore
|
||||
|
||||
- name: Extract PR Number
|
||||
id: pr-number
|
||||
run: |
|
||||
if [[ -f pr-number ]]
|
||||
then
|
||||
echo "pr-number=$(<pr-number)" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- uses: dawidd6/action-download-artifact@v2
|
||||
name: "Download Ecosystem Result"
|
||||
id: download-ecosystem-result
|
||||
if: steps.pr-number.outputs.pr-number
|
||||
with:
|
||||
name: ecosystem-result
|
||||
workflow: ci.yaml
|
||||
pr: ${{ steps.pr-number.outputs.pr-number }}
|
||||
path: pr/ecosystem
|
||||
if_no_artifact_found: ignore
|
||||
|
||||
- uses: dawidd6/action-download-artifact@v2
|
||||
name: "Download Benchmark Result"
|
||||
id: download-benchmark-result
|
||||
if: steps.pr-number.outputs.pr-number
|
||||
with:
|
||||
name: summary
|
||||
workflow: benchmark.yaml
|
||||
pr: ${{ steps.pr-number.outputs.pr-number }}
|
||||
path: pr/benchmark
|
||||
if_no_artifact_found: ignore
|
||||
|
||||
- name: Generate Comment
|
||||
id: generate-comment
|
||||
if: steps.download-ecosystem-result.outputs.found_artifact == 'true' || steps.download-benchmark-result.outputs.found_artifact == 'true'
|
||||
run: |
|
||||
echo 'comment<<EOF' >> $GITHUB_OUTPUT
|
||||
echo '## PR Check Results' >> $GITHUB_OUTPUT
|
||||
|
||||
if [[ -f pr/ecosystem/ecosystem-result ]]
|
||||
then
|
||||
echo "### Ecosystem" >> $GITHUB_OUTPUT
|
||||
cat pr/ecosystem/ecosystem-result >> $GITHUB_OUTPUT
|
||||
echo "" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
if [[ -f pr/benchmark/summary.md ]]
|
||||
then
|
||||
cat pr/benchmark/summary.md >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
echo 'EOF' >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Create or update comment
|
||||
if: steps.generate-comment.outputs.comment
|
||||
uses: thollander/actions-comment-pull-request@v2
|
||||
with:
|
||||
pr_number: ${{ steps.pr-number.outputs.pr-number }}
|
||||
message: ${{ steps.generate-comment.outputs.comment }}
|
||||
comment_tag: PR Check Results
|
||||
4
.github/workflows/ruff.yaml
vendored
4
.github/workflows/ruff.yaml
vendored
@@ -208,7 +208,7 @@ jobs:
|
||||
target: ${{ matrix.platform.target }}
|
||||
manylinux: auto
|
||||
args: --release --out dist
|
||||
- uses: uraimo/run-on-arch-action@v2.5.0
|
||||
- uses: uraimo/run-on-arch-action@v2
|
||||
if: matrix.platform.arch != 'ppc64'
|
||||
name: Install built wheel
|
||||
with:
|
||||
@@ -309,7 +309,7 @@ jobs:
|
||||
target: ${{ matrix.platform.target }}
|
||||
manylinux: musllinux_1_2
|
||||
args: --release --out dist
|
||||
- uses: uraimo/run-on-arch-action@master
|
||||
- uses: uraimo/run-on-arch-action@v2
|
||||
name: Install built wheel
|
||||
with:
|
||||
arch: ${{ matrix.platform.arch }}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
fail_fast: true
|
||||
repos:
|
||||
- repo: https://github.com/abravalheri/validate-pyproject
|
||||
rev: v0.10.1
|
||||
rev: v0.12.1
|
||||
hooks:
|
||||
- id: validate-pyproject
|
||||
|
||||
@@ -28,17 +28,17 @@ repos:
|
||||
- id: cargo-fmt
|
||||
name: cargo fmt
|
||||
entry: cargo fmt --
|
||||
language: rust
|
||||
language: system
|
||||
types: [rust]
|
||||
- id: clippy
|
||||
name: clippy
|
||||
entry: cargo clippy --workspace --all-targets --all-features -- -D warnings
|
||||
language: rust
|
||||
language: system
|
||||
pass_filenames: false
|
||||
- id: ruff
|
||||
name: ruff
|
||||
entry: cargo run -p ruff_cli -- check --no-cache --force-exclude --fix --exit-non-zero-on-fix
|
||||
language: rust
|
||||
language: system
|
||||
types_or: [python, pyi]
|
||||
require_serial: true
|
||||
exclude: |
|
||||
@@ -49,7 +49,7 @@ repos:
|
||||
- id: dev-generate-all
|
||||
name: dev-generate-all
|
||||
entry: cargo dev generate-all
|
||||
language: rust
|
||||
language: system
|
||||
pass_filenames: false
|
||||
exclude: target
|
||||
|
||||
|
||||
@@ -145,4 +145,4 @@ default.
|
||||
`pyproject.toml` files are now resolved hierarchically, such that for each Python file, we find
|
||||
the first `pyproject.toml` file in its path, and use that to determine its lint settings.
|
||||
|
||||
See the [README](https://github.com/charliermarsh/ruff#pyprojecttoml-discovery) for more.
|
||||
See the [documentation](https://beta.ruff.rs/docs/configuration/#python-file-discovery) for more.
|
||||
|
||||
@@ -104,7 +104,7 @@ At a high level, the steps involved in adding a new lint rule are as follows:
|
||||
|
||||
1. Determine a name for the new rule as per our [rule naming convention](#rule-naming-convention).
|
||||
1. Create a file for your rule (e.g., `crates/ruff/src/rules/flake8_bugbear/rules/abstract_base_class.rs`).
|
||||
1. In that file, define a violation struct. You can grep for `define_violation!` to see examples.
|
||||
1. In that file, define a violation struct. You can grep for `#[violation]` to see examples.
|
||||
1. Map the violation struct to a rule code in `crates/ruff/src/registry.rs` (e.g., `E402`).
|
||||
1. Define the logic for triggering the violation in `crates/ruff/src/checkers/ast.rs` (for AST-based
|
||||
checks), `crates/ruff/src/checkers/tokens.rs` (for token-based checks), `crates/ruff/src/checkers/lines.rs`
|
||||
@@ -115,7 +115,7 @@ At a high level, the steps involved in adding a new lint rule are as follows:
|
||||
|
||||
To define the violation, start by creating a dedicated file for your rule under the appropriate
|
||||
rule linter (e.g., `crates/ruff/src/rules/flake8_bugbear/rules/abstract_base_class.rs`). That file should
|
||||
contain a struct defined via `define_violation!`, along with a function that creates the violation
|
||||
contain a struct defined via `#[violation]`, along with a function that creates the violation
|
||||
based on any required inputs. (Many of the existing examples live in `crates/ruff/src/violations.rs`,
|
||||
but we're looking to place new rules in their own files.)
|
||||
|
||||
|
||||
366
Cargo.lock
generated
366
Cargo.lock
generated
@@ -289,9 +289,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.1.6"
|
||||
version = "4.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0b0588d44d4d63a87dbd75c136c166bbfd9a86a31cb89e09906521c7d3f5e3"
|
||||
checksum = "c3d7ae14b20b94cb02149ed21a86c423859cbe18dc7ed69845cace50e52b40a5"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"clap_derive",
|
||||
@@ -308,18 +308,19 @@ version = "4.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd125be87bf4c255ebc50de0b7f4d2a6201e8ac3dc86e39c0ad081dc5e7236fe"
|
||||
dependencies = [
|
||||
"clap 4.1.6",
|
||||
"clap 4.1.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_complete_command"
|
||||
version = "0.4.0"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4160b4a4f72ef58bd766bad27c09e6ef1cc9d82a22f6a0f55d152985a4a48e31"
|
||||
checksum = "183495371ea78d4c9ff638bfc6497d46fed2396e4f9c50aebc1278a4a9919a3d"
|
||||
dependencies = [
|
||||
"clap 4.1.6",
|
||||
"clap 4.1.8",
|
||||
"clap_complete",
|
||||
"clap_complete_fig",
|
||||
"clap_complete_nushell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -328,15 +329,25 @@ version = "4.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "63a06158a72dbb088f864887b4409fd22600ba379f3cee3040f842234cc5c2d0"
|
||||
dependencies = [
|
||||
"clap 4.1.6",
|
||||
"clap 4.1.8",
|
||||
"clap_complete",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_complete_nushell"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c7fa41f5e6aa83bd151b70fd0ceaee703d68cd669522795dc812df9edad1252c"
|
||||
dependencies = [
|
||||
"clap 4.1.8",
|
||||
"clap_complete",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.1.0"
|
||||
version = "4.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "684a277d672e91966334af371f1a7b5833f9aa00b07c84e92fbce95e00208ce8"
|
||||
checksum = "44bec8e5c9d09e439c4335b1af0abaab56dcf3b94999a936e1bb47b9134288f0"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro-error",
|
||||
@@ -427,9 +438,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "console_log"
|
||||
version = "0.2.0"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "501a375961cef1a0d44767200e66e4a559283097e91d0730b1d75dfb2f8a1494"
|
||||
checksum = "878ad067d4089144a36ee412d665916c665430eb84c0057b9987f424a5d15c03"
|
||||
dependencies = [
|
||||
"log",
|
||||
"web-sys",
|
||||
@@ -554,6 +565,16 @@ dependencies = [
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ctor"
|
||||
version = "0.1.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cxx"
|
||||
version = "1.0.91"
|
||||
@@ -598,17 +619,6 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derivative"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "diff"
|
||||
version = "0.1.13"
|
||||
@@ -770,10 +780,10 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
|
||||
|
||||
[[package]]
|
||||
name = "flake8-to-ruff"
|
||||
version = "0.0.253"
|
||||
version = "0.0.257"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap 4.1.6",
|
||||
"clap 4.1.8",
|
||||
"colored",
|
||||
"configparser",
|
||||
"once_cell",
|
||||
@@ -1080,12 +1090,6 @@ version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
|
||||
|
||||
[[package]]
|
||||
name = "joinery"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72167d68f5fce3b8655487b8038691a3c9984ee769590f93f2a631f4ad64e4f5"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.61"
|
||||
@@ -1369,15 +1373,6 @@ dependencies = [
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nom8"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae01545c9c7fc4486ab7debaf2aad7003ac19431791868fb2e8066df97fad2f8"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "notify"
|
||||
version = "5.1.0"
|
||||
@@ -1405,7 +1400,6 @@ dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1415,7 +1409,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02e0d21255c828d6f128a1e41534206671e8c3ea0c62f32291e808dc82cff17d"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1447,27 +1440,6 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_enum"
|
||||
version = "0.5.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3e0072973714303aa6e3631c7e8e777970cf4bdd25dc4932e41031027b8bcc4e"
|
||||
dependencies = [
|
||||
"num_enum_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_enum_derive"
|
||||
version = "0.5.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0629cbd6b897944899b1f10496d9c4a7ac5878d45fd61bc22e9e79bfbbc29597"
|
||||
dependencies = [
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.17.1"
|
||||
@@ -1486,6 +1458,15 @@ version = "6.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee"
|
||||
|
||||
[[package]]
|
||||
name = "output_vt100"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "628223faebab4e3e40667ee0b2336d34a5b960ff60ea743ddfdbcf7770bcfb66"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.12.1"
|
||||
@@ -1533,6 +1514,12 @@ dependencies = [
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pathdiff"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd"
|
||||
|
||||
[[package]]
|
||||
name = "peg"
|
||||
version = "0.8.1"
|
||||
@@ -1560,6 +1547,18 @@ version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9fa00462b37ead6d11a82c9d568b26682d78e0477dc02d1966c013af80969739"
|
||||
|
||||
[[package]]
|
||||
name = "pep440_rs"
|
||||
version = "0.2.0"
|
||||
source = "git+https://github.com/konstin/pep440-rs.git?rev=a8fef4ec47f4c25b070b39cdbe6a0b9847e49941#a8fef4ec47f4c25b070b39cdbe6a0b9847e49941"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"regex",
|
||||
"serde",
|
||||
"tracing",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.2.0"
|
||||
@@ -1758,13 +1757,15 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-crate"
|
||||
name = "pretty_assertions"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "66618389e4ec1c7afe67d51a9bf34ff9236480f8d51e7489b7d5ab0303c13f34"
|
||||
checksum = "a25e9bcb20aa780fd0bb16b72403a9064d6b3f22f026946029acb941a50af755"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"toml_edit",
|
||||
"ctor",
|
||||
"diff",
|
||||
"output_vt100",
|
||||
"yansi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1870,9 +1871,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.6.1"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7"
|
||||
checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b"
|
||||
dependencies = [
|
||||
"either",
|
||||
"rayon-core",
|
||||
@@ -1880,9 +1881,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.10.2"
|
||||
version = "1.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "356a0625f1954f730c0201cdab48611198dc6ce21f4acff55089b5a78e6e835b"
|
||||
checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d"
|
||||
dependencies = [
|
||||
"crossbeam-channel",
|
||||
"crossbeam-deque",
|
||||
@@ -1981,22 +1982,16 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.0.253"
|
||||
version = "0.0.257"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bisection",
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
"chrono",
|
||||
"clap 4.1.6",
|
||||
"clap 4.1.8",
|
||||
"colored",
|
||||
"console_error_panic_hook",
|
||||
"console_log",
|
||||
"criterion",
|
||||
"derivative",
|
||||
"dirs",
|
||||
"fern",
|
||||
"getrandom",
|
||||
"glob",
|
||||
"globset",
|
||||
"ignore",
|
||||
@@ -2004,7 +1999,6 @@ dependencies = [
|
||||
"insta",
|
||||
"is-macro",
|
||||
"itertools",
|
||||
"js-sys",
|
||||
"libcst",
|
||||
"log",
|
||||
"natord",
|
||||
@@ -2013,10 +2007,16 @@ dependencies = [
|
||||
"num-traits",
|
||||
"once_cell",
|
||||
"path-absolutize",
|
||||
"pathdiff",
|
||||
"pep440_rs",
|
||||
"pretty_assertions",
|
||||
"regex",
|
||||
"result-like",
|
||||
"ruff_cache",
|
||||
"ruff_diagnostics",
|
||||
"ruff_macros",
|
||||
"ruff_python",
|
||||
"ruff_python_ast",
|
||||
"ruff_python_stdlib",
|
||||
"ruff_rustpython",
|
||||
"rustc-hash",
|
||||
"rustpython-common",
|
||||
@@ -2024,7 +2024,7 @@ dependencies = [
|
||||
"schemars",
|
||||
"semver",
|
||||
"serde",
|
||||
"serde-wasm-bindgen",
|
||||
"serde_json",
|
||||
"shellexpand",
|
||||
"smallvec",
|
||||
"strum",
|
||||
@@ -2032,15 +2032,38 @@ dependencies = [
|
||||
"test-case",
|
||||
"textwrap",
|
||||
"thiserror",
|
||||
"titlecase",
|
||||
"toml",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-test",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruff_benchmark"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"criterion",
|
||||
"mimalloc",
|
||||
"once_cell",
|
||||
"ruff",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tikv-jemallocator",
|
||||
"ureq",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruff_cache"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"filetime",
|
||||
"globset",
|
||||
"itertools",
|
||||
"regex",
|
||||
"ruff_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruff_cli"
|
||||
version = "0.0.253"
|
||||
version = "0.0.257"
|
||||
dependencies = [
|
||||
"annotate-snippets 0.9.1",
|
||||
"anyhow",
|
||||
@@ -2050,7 +2073,7 @@ dependencies = [
|
||||
"bitflags",
|
||||
"cachedir",
|
||||
"chrono",
|
||||
"clap 4.1.6",
|
||||
"clap 4.1.8",
|
||||
"clap_complete_command",
|
||||
"clearscreen",
|
||||
"colored",
|
||||
@@ -2066,6 +2089,9 @@ dependencies = [
|
||||
"rayon",
|
||||
"regex",
|
||||
"ruff",
|
||||
"ruff_cache",
|
||||
"ruff_diagnostics",
|
||||
"ruff_python_stdlib",
|
||||
"rustc-hash",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@@ -2083,13 +2109,15 @@ name = "ruff_dev"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap 4.1.6",
|
||||
"clap 4.1.8",
|
||||
"itertools",
|
||||
"libcst",
|
||||
"once_cell",
|
||||
"pretty_assertions",
|
||||
"regex",
|
||||
"ruff",
|
||||
"ruff_cli",
|
||||
"ruff_diagnostics",
|
||||
"rustpython-common",
|
||||
"rustpython-parser",
|
||||
"schemars",
|
||||
@@ -2099,6 +2127,15 @@ dependencies = [
|
||||
"textwrap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruff_diagnostics"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"ruff_python_ast",
|
||||
"rustpython-parser",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruff_formatter"
|
||||
version = "0.0.0"
|
||||
@@ -2125,12 +2162,25 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruff_python"
|
||||
name = "ruff_python_ast"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bitflags",
|
||||
"is-macro",
|
||||
"itertools",
|
||||
"log",
|
||||
"nohash-hasher",
|
||||
"num-bigint",
|
||||
"num-traits",
|
||||
"once_cell",
|
||||
"regex",
|
||||
"ruff_python_stdlib",
|
||||
"ruff_rustpython",
|
||||
"rustc-hash",
|
||||
"rustpython-common",
|
||||
"rustpython-parser",
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2138,13 +2188,14 @@ name = "ruff_python_formatter"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap 4.1.6",
|
||||
"clap 4.1.8",
|
||||
"insta",
|
||||
"is-macro",
|
||||
"itertools",
|
||||
"once_cell",
|
||||
"ruff_formatter",
|
||||
"ruff_python",
|
||||
"ruff_python_ast",
|
||||
"ruff_python_stdlib",
|
||||
"ruff_rustpython",
|
||||
"ruff_testing_macros",
|
||||
"ruff_text_size",
|
||||
@@ -2155,6 +2206,14 @@ dependencies = [
|
||||
"test-case",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruff_python_stdlib"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"rustc-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruff_rustpython"
|
||||
version = "0.0.0"
|
||||
@@ -2170,7 +2229,6 @@ name = "ruff_testing_macros"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"glob",
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
@@ -2186,6 +2244,25 @@ dependencies = [
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruff_wasm"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"console_error_panic_hook",
|
||||
"console_log",
|
||||
"getrandom",
|
||||
"js-sys",
|
||||
"log",
|
||||
"ruff",
|
||||
"ruff_python_ast",
|
||||
"ruff_rustpython",
|
||||
"rustpython-parser",
|
||||
"serde",
|
||||
"serde-wasm-bindgen",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-test",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust-stemmers"
|
||||
version = "1.2.0"
|
||||
@@ -2231,7 +2308,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rustpython-ast"
|
||||
version = "0.2.0"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=aa8336ee94492b52458ed8e1517238e5c6c2914c#aa8336ee94492b52458ed8e1517238e5c6c2914c"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=c15f670f2c30cfae6b41a1874893590148c74bc4#c15f670f2c30cfae6b41a1874893590148c74bc4"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"rustpython-compiler-core",
|
||||
@@ -2240,7 +2317,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rustpython-common"
|
||||
version = "0.2.0"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=aa8336ee94492b52458ed8e1517238e5c6c2914c#aa8336ee94492b52458ed8e1517238e5c6c2914c"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=c15f670f2c30cfae6b41a1874893590148c74bc4#c15f670f2c30cfae6b41a1874893590148c74bc4"
|
||||
dependencies = [
|
||||
"ascii",
|
||||
"bitflags",
|
||||
@@ -2265,24 +2342,21 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rustpython-compiler-core"
|
||||
version = "0.2.0"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=aa8336ee94492b52458ed8e1517238e5c6c2914c#aa8336ee94492b52458ed8e1517238e5c6c2914c"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=c15f670f2c30cfae6b41a1874893590148c74bc4#c15f670f2c30cfae6b41a1874893590148c74bc4"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"bitflags",
|
||||
"bstr 0.2.17",
|
||||
"itertools",
|
||||
"lz4_flex",
|
||||
"num-bigint",
|
||||
"num-complex",
|
||||
"num_enum",
|
||||
"serde",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustpython-parser"
|
||||
version = "0.2.0"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=aa8336ee94492b52458ed8e1517238e5c6c2914c#aa8336ee94492b52458ed8e1517238e5c6c2914c"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=c15f670f2c30cfae6b41a1874893590148c74bc4#c15f670f2c30cfae6b41a1874893590148c74bc4"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"anyhow",
|
||||
@@ -2297,7 +2371,7 @@ dependencies = [
|
||||
"rustc-hash",
|
||||
"rustpython-ast",
|
||||
"rustpython-compiler-core",
|
||||
"thiserror",
|
||||
"serde",
|
||||
"tiny-keccak",
|
||||
"unic-emoji-char",
|
||||
"unic-ucd-ident",
|
||||
@@ -2327,9 +2401,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "schemars"
|
||||
version = "0.8.11"
|
||||
version = "0.8.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a5fb6c61f29e723026dc8e923d94c694313212abbecbbe5f55a7748eec5b307"
|
||||
checksum = "02c613288622e5f0c3fdc5dbd4db1c5fbe752746b1d1a56a0630b78fd00de44f"
|
||||
dependencies = [
|
||||
"dyn-clone",
|
||||
"schemars_derive",
|
||||
@@ -2339,9 +2413,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "schemars_derive"
|
||||
version = "0.8.11"
|
||||
version = "0.8.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f188d036977451159430f3b8dc82ec76364a42b7e289c2b18a9a18f4470058e9"
|
||||
checksum = "109da1e6b197438deb6db99952990c7f959572794b80ff93707d55a232545e7c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -2394,9 +2468,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde-wasm-bindgen"
|
||||
version = "0.4.5"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3b4c031cd0d9014307d82b8abf653c0290fbdaeb4c02d00c63cf52f728628bf"
|
||||
checksum = "f3b143e2833c57ab9ad3ea280d21fd34e285a42837aeb0ee301f4f41890fa00e"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"serde",
|
||||
@@ -2431,6 +2505,7 @@ version = "1.0.93"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
@@ -2553,9 +2628,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.108"
|
||||
version = "1.0.109"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d56e159d99e6c2b93995d171050271edb50ecc5288fbc7cc17de8fdce4e58c14"
|
||||
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -2626,18 +2701,18 @@ checksum = "95059e91184749cb66be6dc994f67f182b6d897cb3df74a5bf66b5e709295fd8"
|
||||
|
||||
[[package]]
|
||||
name = "test-case"
|
||||
version = "2.2.2"
|
||||
version = "3.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21d6cf5a7dffb3f9dceec8e6b8ca528d9bd71d36c9f074defb548ce161f598c0"
|
||||
checksum = "679b019fb241da62cc449b33b224d19ebe1c6767b495569765115dd7f7f9fba4"
|
||||
dependencies = [
|
||||
"test-case-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "test-case-macros"
|
||||
version = "2.2.2"
|
||||
name = "test-case-core"
|
||||
version = "3.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e45b7bf6e19353ddd832745c8fcf77a17a93171df7151187f26623f2b75b5b26"
|
||||
checksum = "72dc21b5887f4032c4656502d085dc28f2afbb686f25f216472bb0526f4b1b88"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"proc-macro-error",
|
||||
@@ -2646,6 +2721,19 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "test-case-macros"
|
||||
version = "3.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3786898e0be151a96f730fd529b0e8a10f5990fa2a7ea14e37ca27613c05190"
|
||||
dependencies = [
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"test-case-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.16.0"
|
||||
@@ -2752,22 +2840,11 @@ version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||
|
||||
[[package]]
|
||||
name = "titlecase"
|
||||
version = "2.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38397a8cdb017cfeb48bf6c154d6de975ac69ffeed35980fde199d2ee0842042"
|
||||
dependencies = [
|
||||
"joinery",
|
||||
"lazy_static",
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.6.0"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4fb9d890e4dc9298b70f740f615f2e05b9db37dce531f6b24fb77ac993f9f217"
|
||||
checksum = "f7afcae9e3f0fe2c370fd4657108972cbb2fa9db1b9f84849cefd80741b01cb6"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
@@ -2777,24 +2854,24 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml_datetime"
|
||||
version = "0.5.1"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4553f467ac8e3d374bc9a177a26801e5d0f9b211aa1673fb137a403afd1c9cf5"
|
||||
checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_edit"
|
||||
version = "0.18.1"
|
||||
version = "0.19.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56c59d8dd7d0dcbc6428bf7aa2f0e823e26e43b3c9aca15bbc9475d23e5fa12b"
|
||||
checksum = "9a1eb0622d28f4b9c90adc4ea4b2b46b47663fde9ac5fafcb14a1369d5508825"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"nom8",
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
"winnow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2805,9 +2882,21 @@ checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"pin-project-lite",
|
||||
"tracing-attributes",
|
||||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-attributes"
|
||||
version = "0.1.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-core"
|
||||
version = "0.1.30"
|
||||
@@ -2949,7 +3038,7 @@ checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
|
||||
[[package]]
|
||||
name = "unicode_names2"
|
||||
version = "0.6.0"
|
||||
source = "git+https://github.com/youknowone/unicode_names2.git?tag=v0.6.0+character-alias#4ce16aa85cbcdd9cc830410f1a72ef9a235f2fde"
|
||||
source = "git+https://github.com/youknowone/unicode_names2.git?rev=4ce16aa85cbcdd9cc830410f1a72ef9a235f2fde#4ce16aa85cbcdd9cc830410f1a72ef9a235f2fde"
|
||||
dependencies = [
|
||||
"phf",
|
||||
]
|
||||
@@ -3285,6 +3374,15 @@ version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "faf09497b8f8b5ac5d3bb4d05c0a99be20f26fd3d5f2db7b0716e946d5103658"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yaml-rust"
|
||||
version = "0.4.5"
|
||||
@@ -3294,6 +3392,12 @@ dependencies = [
|
||||
"linked-hash-map",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yansi"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
|
||||
|
||||
[[package]]
|
||||
name = "yansi-term"
|
||||
version = "0.1.2"
|
||||
|
||||
57
Cargo.toml
57
Cargo.toml
@@ -3,29 +3,52 @@ members = ["crates/*"]
|
||||
|
||||
[workspace.package]
|
||||
edition = "2021"
|
||||
rust-version = "1.67.0"
|
||||
rust-version = "1.67"
|
||||
homepage = "https://beta.ruff.rs/docs/"
|
||||
documentation = "https://beta.ruff.rs/docs/"
|
||||
repository = "https://github.com/charliermarsh/ruff"
|
||||
authors = ["Charlie Marsh <charlie.r.marsh@gmail.com>"]
|
||||
|
||||
[workspace.dependencies]
|
||||
anyhow = { version = "1.0.66" }
|
||||
clap = { version = "4.0.1", features = ["derive"] }
|
||||
itertools = { version = "0.10.5" }
|
||||
anyhow = { version = "1.0.69" }
|
||||
bitflags = { version = "1.3.2" }
|
||||
chrono = { version = "0.4.23", default-features = false, features = ["clock"] }
|
||||
clap = { version = "4.1.8", features = ["derive"] }
|
||||
colored = { version = "2.0.0" }
|
||||
filetime = { version = "0.2.20" }
|
||||
glob = { version = "0.3.1" }
|
||||
globset = { version = "0.4.10" }
|
||||
ignore = { version = "0.4.20" }
|
||||
insta = { version = "1.28.0" }
|
||||
is-macro = { version = "0.2.2" }
|
||||
itertools = { version = "0.10.5" }
|
||||
libcst = { git = "https://github.com/charliermarsh/LibCST", rev = "80e4c1399f95e5beb532fdd1e209ad2dbb470438" }
|
||||
once_cell = { version = "1.16.0" }
|
||||
regex = { version = "1.6.0" }
|
||||
log = { version = "0.4.17" }
|
||||
once_cell = { version = "1.17.1" }
|
||||
path-absolutize = { version = "3.0.14" }
|
||||
proc-macro2 = { version = "1.0.51" }
|
||||
quote = { version = "1.0.23" }
|
||||
regex = { version = "1.7.1" }
|
||||
rustc-hash = { version = "1.1.0" }
|
||||
rustpython-common = { git = "https://github.com/RustPython/RustPython.git", rev = "aa8336ee94492b52458ed8e1517238e5c6c2914c" }
|
||||
rustpython-parser = { features = ["lalrpop"], git = "https://github.com/RustPython/RustPython.git", rev = "aa8336ee94492b52458ed8e1517238e5c6c2914c" }
|
||||
schemars = { version = "0.8.11" }
|
||||
serde = { version = "1.0.147", features = ["derive"] }
|
||||
serde_json = { version = "1.0.87" }
|
||||
rustpython-common = { git = "https://github.com/RustPython/RustPython.git", rev = "c15f670f2c30cfae6b41a1874893590148c74bc4" }
|
||||
rustpython-parser = { features = [
|
||||
"lalrpop",
|
||||
"serde",
|
||||
], git = "https://github.com/RustPython/RustPython.git", rev = "c15f670f2c30cfae6b41a1874893590148c74bc4" }
|
||||
schemars = { version = "0.8.12" }
|
||||
serde = { version = "1.0.152", features = ["derive"] }
|
||||
serde_json = { version = "1.0.93", features = ["preserve_order"] }
|
||||
shellexpand = { version = "3.0.0" }
|
||||
similar = { version = "2.2.1" }
|
||||
strum = { version = "0.24.1", features = ["strum_macros"] }
|
||||
strum_macros = { version = "0.24.3" }
|
||||
toml = { version = "0.6.0" }
|
||||
syn = { version = "1.0.109" }
|
||||
test-case = { version = "3.0.0" }
|
||||
textwrap = { version = "0.16.0" }
|
||||
toml = { version = "0.7.2" }
|
||||
|
||||
[profile.release]
|
||||
panic = "abort"
|
||||
lto = "thin"
|
||||
lto = "fat"
|
||||
codegen-units = 1
|
||||
opt-level = 3
|
||||
|
||||
@@ -39,3 +62,9 @@ opt-level = 3
|
||||
# https://github.com/bytecodealliance/wasm-tools/blob/b5c3d98e40590512a3b12470ef358d5c7b983b15/crates/wasmparser/src/limits.rs#L29
|
||||
[profile.dev.package.rustpython-parser]
|
||||
opt-level = 1
|
||||
|
||||
# Use the `--profile release-debug` flag to show symbols in release mode.
|
||||
# e.g. `cargo build --profile release-debug`
|
||||
[profile.release-debug]
|
||||
inherits = "release"
|
||||
debug = 1
|
||||
|
||||
26
LICENSE
26
LICENSE
@@ -393,7 +393,6 @@ are:
|
||||
THE SOFTWARE.
|
||||
"""
|
||||
|
||||
|
||||
- autoflake, licensed as follows:
|
||||
"""
|
||||
Copyright (C) 2012-2018 Steven Myint
|
||||
@@ -417,6 +416,31 @@ are:
|
||||
SOFTWARE.
|
||||
"""
|
||||
|
||||
- autotyping, licensed as follows:
|
||||
"""
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 Jelle Zijlstra
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
"""
|
||||
|
||||
- Flake8, licensed as follows:
|
||||
"""
|
||||
== Flake8 License (MIT) ==
|
||||
|
||||
58
README.md
58
README.md
@@ -137,7 +137,7 @@ Ruff can also be used as a [pre-commit](https://pre-commit.com) hook:
|
||||
```yaml
|
||||
- repo: https://github.com/charliermarsh/ruff-pre-commit
|
||||
# Ruff version.
|
||||
rev: 'v0.0.253'
|
||||
rev: 'v0.0.257'
|
||||
hooks:
|
||||
- id: ruff
|
||||
```
|
||||
@@ -227,6 +227,54 @@ stylistic rules made obsolete by the use of an autoformatter, like
|
||||
If you're just getting started with Ruff, **the default rule set is a great place to start**: it
|
||||
catches a wide variety of common errors (like unused imports) with zero configuration.
|
||||
|
||||
Beyond the defaults, Ruff re-implements some of the most popular Flake8 plugins and related code
|
||||
quality tools, including:
|
||||
|
||||
- [autoflake](https://pypi.org/project/autoflake/)
|
||||
- [eradicate](https://pypi.org/project/eradicate/)
|
||||
- [flake8-2020](https://pypi.org/project/flake8-2020/)
|
||||
- [flake8-annotations](https://pypi.org/project/flake8-annotations/)
|
||||
- [flake8-bandit](https://pypi.org/project/flake8-bandit/) ([#1646](https://github.com/charliermarsh/ruff/issues/1646))
|
||||
- [flake8-blind-except](https://pypi.org/project/flake8-blind-except/)
|
||||
- [flake8-boolean-trap](https://pypi.org/project/flake8-boolean-trap/)
|
||||
- [flake8-bugbear](https://pypi.org/project/flake8-bugbear/)
|
||||
- [flake8-builtins](https://pypi.org/project/flake8-builtins/)
|
||||
- [flake8-commas](https://pypi.org/project/flake8-commas/)
|
||||
- [flake8-comprehensions](https://pypi.org/project/flake8-comprehensions/)
|
||||
- [flake8-datetimez](https://pypi.org/project/flake8-datetimez/)
|
||||
- [flake8-debugger](https://pypi.org/project/flake8-debugger/)
|
||||
- [flake8-django](https://pypi.org/project/flake8-django/) ([#2817](https://github.com/charliermarsh/ruff/issues/2817))
|
||||
- [flake8-docstrings](https://pypi.org/project/flake8-docstrings/)
|
||||
- [flake8-eradicate](https://pypi.org/project/flake8-eradicate/)
|
||||
- [flake8-errmsg](https://pypi.org/project/flake8-errmsg/)
|
||||
- [flake8-executable](https://pypi.org/project/flake8-executable/)
|
||||
- [flake8-implicit-str-concat](https://pypi.org/project/flake8-implicit-str-concat/)
|
||||
- [flake8-import-conventions](https://github.com/joaopalmeiro/flake8-import-conventions)
|
||||
- [flake8-logging-format](https://pypi.org/project/flake8-logging-format/)
|
||||
- [flake8-no-pep420](https://pypi.org/project/flake8-no-pep420)
|
||||
- [flake8-pie](https://pypi.org/project/flake8-pie/)
|
||||
- [flake8-print](https://pypi.org/project/flake8-print/)
|
||||
- [flake8-pyi](https://pypi.org/project/flake8-pyi/)
|
||||
- [flake8-pytest-style](https://pypi.org/project/flake8-pytest-style/)
|
||||
- [flake8-quotes](https://pypi.org/project/flake8-quotes/)
|
||||
- [flake8-raise](https://pypi.org/project/flake8-raise/)
|
||||
- [flake8-return](https://pypi.org/project/flake8-return/)
|
||||
- [flake8-self](https://pypi.org/project/flake8-self/)
|
||||
- [flake8-simplify](https://pypi.org/project/flake8-simplify/)
|
||||
- [flake8-super](https://pypi.org/project/flake8-super/)
|
||||
- [flake8-tidy-imports](https://pypi.org/project/flake8-tidy-imports/)
|
||||
- [flake8-type-checking](https://pypi.org/project/flake8-type-checking/)
|
||||
- [flake8-use-pathlib](https://pypi.org/project/flake8-use-pathlib/)
|
||||
- [isort](https://pypi.org/project/isort/)
|
||||
- [mccabe](https://pypi.org/project/mccabe/)
|
||||
- [pandas-vet](https://pypi.org/project/pandas-vet/)
|
||||
- [pep8-naming](https://pypi.org/project/pep8-naming/)
|
||||
- [pydocstyle](https://pypi.org/project/pydocstyle/)
|
||||
- [pygrep-hooks](https://github.com/pre-commit/pygrep-hooks) ([#980](https://github.com/charliermarsh/ruff/issues/980))
|
||||
- [pyupgrade](https://pypi.org/project/pyupgrade/)
|
||||
- [tryceratops](https://pypi.org/project/tryceratops/)
|
||||
- [yesqa](https://pypi.org/project/yesqa/)
|
||||
|
||||
<!-- End section: Rules -->
|
||||
|
||||
For a complete enumeration of the supported rules, see [_Rules_](https://beta.ruff.rs/docs/rules/).
|
||||
@@ -280,6 +328,7 @@ Ruff is used in a number of major open-source projects, including:
|
||||
- [Zulip](https://github.com/zulip/zulip)
|
||||
- [Bokeh](https://github.com/bokeh/bokeh)
|
||||
- [Pydantic](https://github.com/pydantic/pydantic)
|
||||
- [PostHog](https://github.com/PostHog/posthog)
|
||||
- [Dagster](https://github.com/dagster-io/dagster)
|
||||
- [Dagger](https://github.com/dagger/dagger)
|
||||
- [Sphinx](https://github.com/sphinx-doc/sphinx)
|
||||
@@ -306,6 +355,13 @@ Ruff is used in a number of major open-source projects, including:
|
||||
- [meson-python](https://github.com/mesonbuild/meson-python)
|
||||
- [ZenML](https://github.com/zenml-io/zenml)
|
||||
- [delta-rs](https://github.com/delta-io/delta-rs)
|
||||
- [Starlite](https://github.com/starlite-api/starlite)
|
||||
- [telemetry-airflow (Mozilla)](https://github.com/mozilla/telemetry-airflow)
|
||||
- [Stable Baselines3](https://github.com/DLR-RM/stable-baselines3)
|
||||
- [PaddlePaddle](https://github.com/PaddlePaddle/Paddle)
|
||||
- [nox](https://github.com/wntrblm/nox)
|
||||
- [Neon](https://github.com/neondatabase/neon)
|
||||
- [The Algorithms](https://github.com/TheAlgorithms/Python)
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
[package]
|
||||
name = "flake8-to-ruff"
|
||||
version = "0.0.253"
|
||||
version = "0.0.257"
|
||||
edition = { workspace = true }
|
||||
rust-version = { workspace = true }
|
||||
|
||||
[dependencies]
|
||||
ruff = { path = "../ruff", default-features = false }
|
||||
|
||||
anyhow = { workspace = true }
|
||||
clap = { workspace = true }
|
||||
colored = { version = "2.0.0" }
|
||||
colored = { workspace = true }
|
||||
configparser = { version = "3.0.2" }
|
||||
once_cell = { workspace = true }
|
||||
regex = { workspace = true }
|
||||
ruff = { path = "../ruff", default-features = false }
|
||||
rustc-hash = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
|
||||
@@ -85,8 +85,9 @@ flake8-to-ruff path/to/.flake8 --plugin flake8-builtins --plugin flake8-quotes
|
||||
ignore unsupported options in the `.flake8` file (or equivalent). (Similarly, Ruff has a few
|
||||
configuration options that don't exist in Flake8.)
|
||||
1. Ruff will omit any rule codes that are unimplemented or unsupported by Ruff, including rule
|
||||
codes from unsupported plugins. (See the [Ruff README](https://github.com/charliermarsh/ruff#user-content-how-does-ruff-compare-to-flake8)
|
||||
for the complete list of supported plugins.)
|
||||
codes from unsupported plugins. (See the
|
||||
[documentation](https://beta.ruff.rs/docs/faq/#how-does-ruff-compare-to-flake8) for the complete
|
||||
list of supported plugins.)
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -46,8 +46,15 @@ fn main() -> Result<()> {
|
||||
.map(|tool| ExternalConfig {
|
||||
black: tool.black.as_ref(),
|
||||
isort: tool.isort.as_ref(),
|
||||
..Default::default()
|
||||
})
|
||||
.unwrap_or_default();
|
||||
let external_config = ExternalConfig {
|
||||
project: pyproject
|
||||
.as_ref()
|
||||
.and_then(|pyproject| pyproject.project.as_ref()),
|
||||
..external_config
|
||||
};
|
||||
|
||||
// Create Ruff's pyproject.toml section.
|
||||
let pyproject = flake8_to_ruff::convert(&config, &external_config, args.plugin)?;
|
||||
|
||||
@@ -1,83 +1,77 @@
|
||||
[package]
|
||||
name = "ruff"
|
||||
version = "0.0.253"
|
||||
authors = ["Charlie Marsh <charlie.r.marsh@gmail.com>"]
|
||||
edition = { workspace = true }
|
||||
rust-version = { workspace = true }
|
||||
documentation = "https://github.com/charliermarsh/ruff"
|
||||
homepage = "https://github.com/charliermarsh/ruff"
|
||||
repository = "https://github.com/charliermarsh/ruff"
|
||||
version = "0.0.257"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
documentation.workspace = true
|
||||
homepage.workspace = true
|
||||
repository.workspace = true
|
||||
readme = "README.md"
|
||||
license = "MIT"
|
||||
|
||||
[lib]
|
||||
name = "ruff"
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
ruff_cache = { path = "../ruff_cache" }
|
||||
ruff_diagnostics = { path = "../ruff_diagnostics", features = ["serde"] }
|
||||
ruff_macros = { path = "../ruff_macros" }
|
||||
ruff_python = { path = "../ruff_python" }
|
||||
ruff_python_ast = { path = "../ruff_python_ast" }
|
||||
ruff_python_stdlib = { path = "../ruff_python_stdlib" }
|
||||
ruff_rustpython = { path = "../ruff_rustpython" }
|
||||
|
||||
anyhow = { workspace = true }
|
||||
bisection = { version = "0.1.0" }
|
||||
bitflags = { version = "1.3.2" }
|
||||
cfg-if = { version = "1.0.0" }
|
||||
chrono = { version = "0.4.21", default-features = false, features = ["clock"] }
|
||||
clap = { workspace = true, features = ["derive", "env", "string"] }
|
||||
colored = { version = "2.0.0" }
|
||||
derivative = { version = "2.2.0" }
|
||||
bitflags = { workspace = true }
|
||||
chrono = { workspace = true }
|
||||
clap = { workspace = true, features = ["derive", "string"], optional = true }
|
||||
colored = { workspace = true }
|
||||
dirs = { version = "4.0.0" }
|
||||
fern = { version = "0.6.1" }
|
||||
glob = { version = "0.3.0" }
|
||||
globset = { version = "0.4.9" }
|
||||
ignore = { version = "0.4.18" }
|
||||
imperative = { version = "1.0.3" }
|
||||
glob = { workspace = true }
|
||||
globset = { workspace = true }
|
||||
ignore = { workspace = true }
|
||||
imperative = { version = "1.0.4" }
|
||||
is-macro = { workspace = true }
|
||||
itertools = { workspace = true }
|
||||
libcst = { workspace = true }
|
||||
log = { version = "0.4.17" }
|
||||
log = { workspace = true }
|
||||
natord = { version = "1.0.9" }
|
||||
nohash-hasher = { version = "0.2.0" }
|
||||
num-bigint = { version = "0.4.3" }
|
||||
num-traits = "0.2.15"
|
||||
num-traits = { version = "0.2.15" }
|
||||
once_cell = { workspace = true }
|
||||
path-absolutize = { version = "3.0.14", features = ["once_cell_cache", "use_unix_paths_on_wasm"] }
|
||||
path-absolutize = { workspace = true, features = [
|
||||
"once_cell_cache",
|
||||
"use_unix_paths_on_wasm",
|
||||
] }
|
||||
pathdiff = { version = "0.2.1" }
|
||||
pep440_rs = { git = "https://github.com/konstin/pep440-rs.git", features = [
|
||||
"serde",
|
||||
], rev = "a8fef4ec47f4c25b070b39cdbe6a0b9847e49941" }
|
||||
regex = { workspace = true }
|
||||
result-like = "0.4.6"
|
||||
result-like = { version = "0.4.6" }
|
||||
rustc-hash = { workspace = true }
|
||||
rustpython-common = { workspace = true }
|
||||
rustpython-parser = { workspace = true }
|
||||
schemars = { workspace = true }
|
||||
semver = { version = "1.0.16" }
|
||||
serde = { workspace = true }
|
||||
shellexpand = { version = "3.0.0" }
|
||||
shellexpand = { workspace = true }
|
||||
smallvec = { version = "1.10.0" }
|
||||
strum = { workspace = true }
|
||||
strum_macros = { workspace = true }
|
||||
textwrap = { version = "0.16.0" }
|
||||
thiserror = { version = "1.0" }
|
||||
titlecase = { version = "2.2.1" }
|
||||
textwrap = { workspace = true }
|
||||
thiserror = { version = "1.0.38" }
|
||||
toml = { workspace = true }
|
||||
|
||||
# https://docs.rs/getrandom/0.2.7/getrandom/#webassembly-support
|
||||
[target.'cfg(all(target_family = "wasm", target_os = "unknown"))'.dependencies]
|
||||
getrandom = { version = "0.2.7", features = ["js"] }
|
||||
console_error_panic_hook = { version = "0.1.7" }
|
||||
console_log = { version = "0.2.0" }
|
||||
serde-wasm-bindgen = { version = "0.4" }
|
||||
js-sys = { version = "0.3.60" }
|
||||
wasm-bindgen = { version = "0.2.83" }
|
||||
serde_json = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
insta = { version = "1.19.0", features = ["yaml", "redactions"] }
|
||||
test-case = { version = "2.2.2" }
|
||||
wasm-bindgen-test = { version = "0.3.33" }
|
||||
|
||||
[target.'cfg(not(target_family = "wasm"))'.dev-dependencies]
|
||||
criterion = { version = "0.4.0" }
|
||||
insta = { workspace = true, features = ["yaml", "redactions"] }
|
||||
pretty_assertions = "1.3.0"
|
||||
test-case = { workspace = true }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
logical_lines = []
|
||||
jupyter_notebook = []
|
||||
|
||||
@@ -2,3 +2,6 @@ avoid-*
|
||||
do-not-*
|
||||
uses-*
|
||||
*-used
|
||||
rewrite-*
|
||||
prefer-*
|
||||
consider-*
|
||||
|
||||
42
crates/ruff/resources/test/fixtures/flake8_annotations/simple_magic_methods.py
vendored
Normal file
42
crates/ruff/resources/test/fixtures/flake8_annotations/simple_magic_methods.py
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
class Foo:
|
||||
def __str__(self):
|
||||
...
|
||||
|
||||
def __repr__(self):
|
||||
...
|
||||
|
||||
def __len__(self):
|
||||
...
|
||||
|
||||
def __length_hint__(self):
|
||||
...
|
||||
|
||||
def __init__(self):
|
||||
...
|
||||
|
||||
def __del__(self):
|
||||
...
|
||||
|
||||
def __bool__(self):
|
||||
...
|
||||
|
||||
def __bytes__(self):
|
||||
...
|
||||
|
||||
def __format__(self, format_spec):
|
||||
...
|
||||
|
||||
def __contains__(self, item):
|
||||
...
|
||||
|
||||
def __complex__(self):
|
||||
...
|
||||
|
||||
def __int__(self):
|
||||
...
|
||||
|
||||
def __float__(self):
|
||||
...
|
||||
|
||||
def __index__(self):
|
||||
...
|
||||
6
crates/ruff/resources/test/fixtures/flake8_bandit/S001.py
vendored
Normal file
6
crates/ruff/resources/test/fixtures/flake8_bandit/S001.py
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
import pickle
|
||||
from telnetlib import Telnet
|
||||
|
||||
pickle.loads()
|
||||
|
||||
Telnet("localhost", 23)
|
||||
11
crates/ruff/resources/test/fixtures/flake8_bugbear/B028.py
vendored
Normal file
11
crates/ruff/resources/test/fixtures/flake8_bugbear/B028.py
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
import warnings
|
||||
|
||||
"""
|
||||
Should emit:
|
||||
B028 - on lines 8 and 9
|
||||
"""
|
||||
|
||||
warnings.warn(DeprecationWarning("test"))
|
||||
warnings.warn(DeprecationWarning("test"), source=None)
|
||||
warnings.warn(DeprecationWarning("test"), source=None, stacklevel=2)
|
||||
warnings.warn(DeprecationWarning("test"), stacklevel=1)
|
||||
47
crates/ruff/resources/test/fixtures/flake8_bugbear/B030.py
vendored
Normal file
47
crates/ruff/resources/test/fixtures/flake8_bugbear/B030.py
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
"""
|
||||
Should emit:
|
||||
B030:
|
||||
- line 12, column 8
|
||||
- line 17, column 9
|
||||
- line 22, column 21
|
||||
- line 27, column 37
|
||||
"""
|
||||
|
||||
try:
|
||||
pass
|
||||
except 1: # error
|
||||
pass
|
||||
|
||||
try:
|
||||
pass
|
||||
except (1, ValueError): # error
|
||||
pass
|
||||
|
||||
try:
|
||||
pass
|
||||
except (ValueError, (RuntimeError, (KeyError, TypeError))): # error
|
||||
pass
|
||||
|
||||
try:
|
||||
pass
|
||||
except (ValueError, *(RuntimeError, (KeyError, TypeError))): # error
|
||||
pass
|
||||
|
||||
|
||||
try:
|
||||
pass
|
||||
except (ValueError, *(RuntimeError, TypeError)): # ok
|
||||
pass
|
||||
|
||||
try:
|
||||
pass
|
||||
except (ValueError, *[RuntimeError, *(TypeError,)]): # ok
|
||||
pass
|
||||
|
||||
def what_to_catch():
|
||||
return ...
|
||||
|
||||
try:
|
||||
pass
|
||||
except what_to_catch(): # ok
|
||||
pass
|
||||
@@ -1,6 +1,19 @@
|
||||
x = [1, 2, 3]
|
||||
y = [("a", 1), ("b", 2), ("c", 3)]
|
||||
z = [(1,), (2,), (3,)]
|
||||
d = {"a": 1, "b": 2, "c": 3}
|
||||
|
||||
[i for i in x]
|
||||
{i for i in x}
|
||||
{k: v for k, v in y}
|
||||
{k: v for k, v in d.items()}
|
||||
|
||||
[i for i, in z]
|
||||
[i for i, j in y]
|
||||
[i for i in x if i > 1]
|
||||
[i for i in x for j in x]
|
||||
|
||||
{v: k for k, v in y}
|
||||
{k.foo: k for k in y}
|
||||
{k["foo"]: k for k in y}
|
||||
{k: v if v else None for k, v in y}
|
||||
|
||||
@@ -8,3 +8,9 @@ any({x.id for x in bar})
|
||||
# PIE 802
|
||||
any([x.id for x in bar])
|
||||
all([x.id for x in bar])
|
||||
any( # first comment
|
||||
[x.id for x in bar], # second comment
|
||||
) # third comment
|
||||
all( # first comment
|
||||
[x.id for x in bar], # second comment
|
||||
) # third comment
|
||||
|
||||
@@ -6,6 +6,8 @@ obj.endswith("foo") or obj.endswith("bar")
|
||||
obj.startswith(foo) or obj.startswith(bar)
|
||||
# error
|
||||
obj.startswith(foo) or obj.startswith("foo")
|
||||
# error
|
||||
obj.endswith(foo) or obj.startswith(foo) or obj.startswith("foo")
|
||||
|
||||
# ok
|
||||
obj.startswith(("foo", "bar"))
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
import math
|
||||
import os
|
||||
import sys
|
||||
from math import inf
|
||||
|
||||
import numpy as np
|
||||
|
||||
def f12(
|
||||
x,
|
||||
y: str = os.pathsep, # Error PYI011 Only simple default values allowed for typed arguments
|
||||
@@ -61,3 +68,49 @@ def f22(
|
||||
x: complex = -42.5j # Error PYI011 Only simple default values allowed for typed arguments
|
||||
+ 4.3j,
|
||||
) -> None: ...
|
||||
def f23(
|
||||
x: bool = True, # OK
|
||||
) -> None: ...
|
||||
def f24(
|
||||
x: float = 3.14, # OK
|
||||
) -> None: ...
|
||||
def f25(
|
||||
x: float = -3.14, # OK
|
||||
) -> None: ...
|
||||
def f26(
|
||||
x: complex = -3.14j, # OK
|
||||
) -> None: ...
|
||||
def f27(
|
||||
x: complex = -3 - 3.14j, # OK
|
||||
) -> None: ...
|
||||
def f28(
|
||||
x: float = math.tau, # OK
|
||||
) -> None: ...
|
||||
def f29(
|
||||
x: float = math.inf, # OK
|
||||
) -> None: ...
|
||||
def f30(
|
||||
x: float = -math.inf, # OK
|
||||
) -> None: ...
|
||||
def f31(
|
||||
x: float = inf, # Error PYI011 Only simple default values allowed for typed arguments
|
||||
) -> None: ...
|
||||
def f32(
|
||||
x: float = np.inf, # Error PYI011 Only simple default values allowed for typed arguments
|
||||
) -> None: ...
|
||||
def f33(
|
||||
x: float = math.nan, # OK
|
||||
) -> None: ...
|
||||
def f34(
|
||||
x: float = -math.nan, # Error PYI011 Only simple default values allowed for typed arguments
|
||||
) -> None: ...
|
||||
def f35(
|
||||
x: complex = math.inf # Error PYI011 Only simple default values allowed for typed arguments
|
||||
+ 1j,
|
||||
) -> None: ...
|
||||
def f36(
|
||||
*, x: str = sys.version, # OK
|
||||
) -> None: ...
|
||||
def f37(
|
||||
*, x: str = "" + "", # Error PYI011 Only simple default values allowed for typed arguments
|
||||
) -> None: ...
|
||||
|
||||
@@ -43,3 +43,6 @@ def f21(
|
||||
def f22(
|
||||
x=-42.5j + 4.3j, # Error PYI014
|
||||
) -> None: ...
|
||||
def f23(
|
||||
x=True, # OK
|
||||
) -> None: ...
|
||||
|
||||
33
crates/ruff/resources/test/fixtures/flake8_pyi/PYI033.py
vendored
Normal file
33
crates/ruff/resources/test/fixtures/flake8_pyi/PYI033.py
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
# From https://github.com/PyCQA/flake8-pyi/blob/4212bec43dbc4020a59b90e2957c9488575e57ba/tests/type_comments.pyi
|
||||
|
||||
from collections.abc import Sequence
|
||||
from typing import TypeAlias
|
||||
|
||||
A: TypeAlias = None # type: int # Y033 Do not use type comments in stubs (e.g. use "x: int" instead of "x = ... # type: int")
|
||||
B: TypeAlias = None # type: str # And here's an extra comment about why it's that type # Y033 Do not use type comments in stubs (e.g. use "x: int" instead of "x = ... # type: int")
|
||||
C: TypeAlias = None #type: int # Y033 Do not use type comments in stubs (e.g. use "x: int" instead of "x = ... # type: int")
|
||||
D: TypeAlias = None # type: int # Y033 Do not use type comments in stubs (e.g. use "x: int" instead of "x = ... # type: int")
|
||||
E: TypeAlias = None# type: int # Y033 Do not use type comments in stubs (e.g. use "x: int" instead of "x = ... # type: int")
|
||||
F: TypeAlias = None#type:int # Y033 Do not use type comments in stubs (e.g. use "x: int" instead of "x = ... # type: int")
|
||||
|
||||
def func(
|
||||
arg1, # type: dict[str, int] # Y033 Do not use type comments in stubs (e.g. use "x: int" instead of "x = ... # type: int")
|
||||
arg2 # type: Sequence[bytes] # And here's some more info about this arg # Y033 Do not use type comments in stubs (e.g. use "x: int" instead of "x = ... # type: int")
|
||||
): ...
|
||||
|
||||
class Foo:
|
||||
Attr: TypeAlias = None # type: set[str] # Y033 Do not use type comments in stubs (e.g. use "x: int" instead of "x = ... # type: int")
|
||||
|
||||
G: TypeAlias = None # type: ignore
|
||||
H: TypeAlias = None # type: ignore[attr-defined]
|
||||
I: TypeAlias = None #type: ignore
|
||||
J: TypeAlias = None # type: ignore
|
||||
K: TypeAlias = None# type: ignore
|
||||
L: TypeAlias = None#type:ignore
|
||||
|
||||
# Whole line commented out # type: int
|
||||
M: TypeAlias = None # type: can't parse me!
|
||||
|
||||
class Bar:
|
||||
N: TypeAlias = None # type: can't parse me either!
|
||||
# This whole line is commented out and indented # type: str
|
||||
33
crates/ruff/resources/test/fixtures/flake8_pyi/PYI033.pyi
vendored
Normal file
33
crates/ruff/resources/test/fixtures/flake8_pyi/PYI033.pyi
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
# From https://github.com/PyCQA/flake8-pyi/blob/4212bec43dbc4020a59b90e2957c9488575e57ba/tests/type_comments.pyi
|
||||
|
||||
from collections.abc import Sequence
|
||||
from typing import TypeAlias
|
||||
|
||||
A: TypeAlias = None # type: int # Y033 Do not use type comments in stubs (e.g. use "x: int" instead of "x = ... # type: int")
|
||||
B: TypeAlias = None # type: str # And here's an extra comment about why it's that type # Y033 Do not use type comments in stubs (e.g. use "x: int" instead of "x = ... # type: int")
|
||||
C: TypeAlias = None #type: int # Y033 Do not use type comments in stubs (e.g. use "x: int" instead of "x = ... # type: int")
|
||||
D: TypeAlias = None # type: int # Y033 Do not use type comments in stubs (e.g. use "x: int" instead of "x = ... # type: int")
|
||||
E: TypeAlias = None# type: int # Y033 Do not use type comments in stubs (e.g. use "x: int" instead of "x = ... # type: int")
|
||||
F: TypeAlias = None#type:int # Y033 Do not use type comments in stubs (e.g. use "x: int" instead of "x = ... # type: int")
|
||||
|
||||
def func(
|
||||
arg1, # type: dict[str, int] # Y033 Do not use type comments in stubs (e.g. use "x: int" instead of "x = ... # type: int")
|
||||
arg2 # type: Sequence[bytes] # And here's some more info about this arg # Y033 Do not use type comments in stubs (e.g. use "x: int" instead of "x = ... # type: int")
|
||||
): ...
|
||||
|
||||
class Foo:
|
||||
Attr: TypeAlias = None # type: set[str] # Y033 Do not use type comments in stubs (e.g. use "x: int" instead of "x = ... # type: int")
|
||||
|
||||
G: TypeAlias = None # type: ignore
|
||||
H: TypeAlias = None # type: ignore[attr-defined]
|
||||
I: TypeAlias = None #type: ignore
|
||||
J: TypeAlias = None # type: ignore
|
||||
K: TypeAlias = None# type: ignore
|
||||
L: TypeAlias = None#type:ignore
|
||||
|
||||
# Whole line commented out # type: int
|
||||
M: TypeAlias = None # type: can't parse me!
|
||||
|
||||
class Bar:
|
||||
N: TypeAlias = None # type: can't parse me either!
|
||||
# This whole line is commented out and indented # type: str
|
||||
@@ -293,3 +293,30 @@ def x(y):
|
||||
|
||||
def foo(baz: str) -> str:
|
||||
return baz
|
||||
|
||||
|
||||
def end_of_statement():
|
||||
def example():
|
||||
if True:
|
||||
return ""
|
||||
|
||||
|
||||
def example():
|
||||
if True:
|
||||
return ""
|
||||
|
||||
|
||||
def example():
|
||||
if True:
|
||||
return "" # type: ignore
|
||||
|
||||
|
||||
def example():
|
||||
if True:
|
||||
return "" ;
|
||||
|
||||
|
||||
def example():
|
||||
if True:
|
||||
return "" \
|
||||
; # type: ignore
|
||||
|
||||
@@ -6,22 +6,6 @@ def x():
|
||||
return a # error
|
||||
|
||||
|
||||
def x():
|
||||
a = 1
|
||||
print(a)
|
||||
a = 2
|
||||
return a # error
|
||||
|
||||
|
||||
def x():
|
||||
a = 1
|
||||
if True:
|
||||
return a # error
|
||||
a = 2
|
||||
print(a)
|
||||
return a
|
||||
|
||||
|
||||
# Can be refactored false positives
|
||||
# https://github.com/afonasev/flake8-return/issues/47#issuecomment-1122571066
|
||||
def get_bar_if_exists(obj):
|
||||
@@ -165,44 +149,6 @@ def my_func():
|
||||
return foo
|
||||
|
||||
|
||||
# Refactored incorrect false positives
|
||||
# See test cases above marked: "Can be refactored false positives"
|
||||
# https://github.com/afonasev/flake8-return/issues/47#issuecomment-1122571066
|
||||
def get_bar_if_exists(obj):
|
||||
if hasattr(obj, "bar"):
|
||||
return str(obj.bar)
|
||||
return ""
|
||||
|
||||
|
||||
# https://github.com/afonasev/flake8-return/issues/47#issue-641117366
|
||||
def x():
|
||||
formatted = _USER_AGENT_FORMATTER.format(format_string, **values)
|
||||
# clean up after any blank components
|
||||
return formatted.replace("()", "").replace(" ", " ").strip()
|
||||
|
||||
|
||||
# https://github.com/afonasev/flake8-return/issues/47#issue-641117366
|
||||
def user_agent_username(username=None):
|
||||
|
||||
if not username:
|
||||
return ""
|
||||
|
||||
username = username.replace(" ", "_") # Avoid spaces or %20.
|
||||
try:
|
||||
username.encode("ascii") # just test,
|
||||
# but not actually use it
|
||||
except UnicodeEncodeError:
|
||||
username = quote(username.encode("utf-8"))
|
||||
else:
|
||||
# % is legal in the default $wgLegalTitleChars
|
||||
# This is so that ops know the real pywikibot will not
|
||||
# allow a useragent in the username to allow through a
|
||||
# hand-coded percent-encoded value.
|
||||
if "%" in username:
|
||||
username = quote(username)
|
||||
return username
|
||||
|
||||
|
||||
# https://github.com/afonasev/flake8-return/issues/116#issue-1367575481
|
||||
def no_exception_loop():
|
||||
success = False
|
||||
@@ -260,3 +206,44 @@ def nonlocal_assignment():
|
||||
nonlocal X
|
||||
X = 1
|
||||
return X
|
||||
|
||||
|
||||
def decorator() -> Flask:
|
||||
app = Flask(__name__)
|
||||
|
||||
@app.route('/hello')
|
||||
def hello() -> str:
|
||||
"""Hello endpoint."""
|
||||
return 'Hello, World!'
|
||||
|
||||
return app
|
||||
|
||||
|
||||
def default():
|
||||
y = 1
|
||||
|
||||
def f(x = y) -> X:
|
||||
return x
|
||||
|
||||
return y
|
||||
|
||||
|
||||
def get_queryset(option_1, option_2):
|
||||
queryset: Any = None
|
||||
queryset = queryset.filter(a=1)
|
||||
if option_1:
|
||||
queryset = queryset.annotate(b=Value(2))
|
||||
if option_2:
|
||||
queryset = queryset.filter(c=3)
|
||||
return queryset
|
||||
|
||||
|
||||
def get_queryset():
|
||||
queryset = Model.filter(a=1)
|
||||
queryset = queryset.filter(c=3)
|
||||
return queryset
|
||||
|
||||
|
||||
def get_queryset():
|
||||
queryset = Model.filter(a=1)
|
||||
return queryset # error
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
"yoda" <= compare # SIM300
|
||||
"yoda" < compare # SIM300
|
||||
42 > age # SIM300
|
||||
-42 > age # SIM300
|
||||
+42 > age # SIM300
|
||||
YODA == age # SIM300
|
||||
YODA > age # SIM300
|
||||
YODA >= age # SIM300
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
from typing import TYPE_CHECKING, Any, ClassVar
|
||||
|
||||
|
||||
import attrs
|
||||
|
||||
from ....import unknown
|
||||
from ..protocol import commands, definitions, responses
|
||||
from ..server import example
|
||||
from .. import server
|
||||
|
||||
3
crates/ruff/resources/test/fixtures/flake8_type_checking/TCH004_14.pyi
vendored
Normal file
3
crates/ruff/resources/test/fixtures/flake8_type_checking/TCH004_14.pyi
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
from typing import Tuple
|
||||
|
||||
x: Tuple
|
||||
38
crates/ruff/resources/test/fixtures/flake8_type_checking/runtime_evaluated_base_classes_1.py
vendored
Normal file
38
crates/ruff/resources/test/fixtures/flake8_type_checking/runtime_evaluated_base_classes_1.py
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import pathlib
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import pydantic
|
||||
from pydantic import BaseModel
|
||||
|
||||
if TYPE_CHECKING:
|
||||
import datetime # TCH004
|
||||
from array import array # TCH004
|
||||
|
||||
import pandas # TCH004
|
||||
import pyproj
|
||||
|
||||
|
||||
class A(pydantic.BaseModel):
|
||||
x: datetime.datetime
|
||||
|
||||
|
||||
class B(BaseModel):
|
||||
x: pandas.DataFrame
|
||||
|
||||
|
||||
class C(BaseModel):
|
||||
x: pathlib.Path
|
||||
|
||||
|
||||
class E:
|
||||
pass
|
||||
|
||||
|
||||
class F(E):
|
||||
x: pyproj.Transformer
|
||||
|
||||
|
||||
class G(BaseModel):
|
||||
x: array
|
||||
28
crates/ruff/resources/test/fixtures/flake8_type_checking/runtime_evaluated_base_classes_2.py
vendored
Normal file
28
crates/ruff/resources/test/fixtures/flake8_type_checking/runtime_evaluated_base_classes_2.py
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import geopandas as gpd # TCH002
|
||||
import pydantic
|
||||
import pyproj # TCH002
|
||||
from pydantic import BaseModel
|
||||
|
||||
import numpy
|
||||
|
||||
|
||||
class A(BaseModel):
|
||||
x: pandas.DataFrame
|
||||
|
||||
|
||||
class B(pydantic.BaseModel):
|
||||
x: numpy.ndarray
|
||||
|
||||
|
||||
class C:
|
||||
pass
|
||||
|
||||
|
||||
class D(C):
|
||||
x: pyproj.Transformer
|
||||
|
||||
|
||||
class E(C):
|
||||
x: gpd.GeoDataFrame
|
||||
24
crates/ruff/resources/test/fixtures/flake8_type_checking/runtime_evaluated_base_classes_3.py
vendored
Normal file
24
crates/ruff/resources/test/fixtures/flake8_type_checking/runtime_evaluated_base_classes_3.py
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import datetime
|
||||
import pathlib
|
||||
from uuid import UUID # TCH003
|
||||
|
||||
import pydantic
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class A(pydantic.BaseModel):
|
||||
x: datetime.datetime
|
||||
|
||||
|
||||
class B(BaseModel):
|
||||
x: pathlib.Path
|
||||
|
||||
|
||||
class C:
|
||||
pass
|
||||
|
||||
|
||||
class D(C):
|
||||
x: UUID
|
||||
46
crates/ruff/resources/test/fixtures/flake8_type_checking/runtime_evaluated_decorators_1.py
vendored
Normal file
46
crates/ruff/resources/test/fixtures/flake8_type_checking/runtime_evaluated_decorators_1.py
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import pathlib
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import attrs
|
||||
from attrs import frozen
|
||||
|
||||
import numpy
|
||||
|
||||
if TYPE_CHECKING:
|
||||
import datetime # TCH004
|
||||
from array import array # TCH004
|
||||
|
||||
import pandas # TCH004
|
||||
import pyproj
|
||||
|
||||
|
||||
@attrs.define(auto_attribs=True)
|
||||
class A:
|
||||
x: datetime.datetime
|
||||
|
||||
|
||||
@attrs.define
|
||||
class B:
|
||||
x: pandas.DataFrame
|
||||
|
||||
|
||||
@frozen(auto_attribs=True)
|
||||
class C:
|
||||
x: pathlib.Path
|
||||
|
||||
|
||||
@frozen
|
||||
class D:
|
||||
x: array
|
||||
|
||||
|
||||
@dataclass
|
||||
class E:
|
||||
x: pyproj.Transformer
|
||||
|
||||
|
||||
@attrs.define
|
||||
class F:
|
||||
x: numpy.ndarray
|
||||
30
crates/ruff/resources/test/fixtures/flake8_type_checking/runtime_evaluated_decorators_2.py
vendored
Normal file
30
crates/ruff/resources/test/fixtures/flake8_type_checking/runtime_evaluated_decorators_2.py
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
|
||||
import attrs
|
||||
import pandas
|
||||
import pyproj
|
||||
from attrs import frozen
|
||||
|
||||
import numpy # TCH002
|
||||
|
||||
|
||||
@attrs.define(auto_attribs=True)
|
||||
class A:
|
||||
x: pyproj.Transformer
|
||||
|
||||
|
||||
@attrs.define
|
||||
class B:
|
||||
x: pandas.DataFrame
|
||||
|
||||
|
||||
@frozen
|
||||
class C:
|
||||
x: pandas.DataFrame
|
||||
|
||||
|
||||
@dataclass
|
||||
class D:
|
||||
x: numpy.ndarray
|
||||
24
crates/ruff/resources/test/fixtures/flake8_type_checking/runtime_evaluated_decorators_3.py
vendored
Normal file
24
crates/ruff/resources/test/fixtures/flake8_type_checking/runtime_evaluated_decorators_3.py
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import datetime
|
||||
from array import array
|
||||
from dataclasses import dataclass
|
||||
from uuid import UUID # TCH003
|
||||
|
||||
import attrs
|
||||
from attrs import frozen
|
||||
|
||||
|
||||
@attrs.define(auto_attribs=True)
|
||||
class A:
|
||||
x: datetime.datetime
|
||||
|
||||
|
||||
@frozen
|
||||
class B:
|
||||
x: array
|
||||
|
||||
|
||||
@dataclass
|
||||
class C:
|
||||
x: UUID
|
||||
@@ -1,5 +1,10 @@
|
||||
import sys, math
|
||||
from os import path, uname
|
||||
from json import detect_encoding
|
||||
from json import dump
|
||||
from json import dumps as json_dumps
|
||||
from json import load
|
||||
from json import loads as json_loads
|
||||
from logging.handlers import StreamHandler, FileHandler
|
||||
|
||||
# comment 1
|
||||
@@ -10,9 +15,10 @@ from third_party import lib4
|
||||
|
||||
from foo import bar # comment 3
|
||||
from foo2 import bar2 # comment 4
|
||||
from foo3 import bar3, baz3 # comment 5
|
||||
|
||||
# comment 5
|
||||
# comment 6
|
||||
from bar import (
|
||||
a, # comment 6
|
||||
b, # comment 7
|
||||
)
|
||||
a, # comment 7
|
||||
b, # comment 8
|
||||
)
|
||||
|
||||
10
crates/ruff/resources/test/fixtures/isort/ruff_skip_file.py
vendored
Normal file
10
crates/ruff/resources/test/fixtures/isort/ruff_skip_file.py
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
# ruff: isort: skip_file
|
||||
import e
|
||||
import f
|
||||
|
||||
# isort: split
|
||||
|
||||
import a
|
||||
import b
|
||||
import c
|
||||
import d
|
||||
@@ -6,6 +6,14 @@ def f():
|
||||
# isort: on
|
||||
|
||||
|
||||
def f():
|
||||
# ruff: isort: off
|
||||
import sys
|
||||
import os
|
||||
import collections
|
||||
# ruff: isort: on
|
||||
|
||||
|
||||
def f():
|
||||
import sys
|
||||
import os # isort: skip
|
||||
|
||||
32
crates/ruff/resources/test/fixtures/jupyter/R.ipynb
vendored
Normal file
32
crates/ruff/resources/test/fixtures/jupyter/R.ipynb
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"print(paste(\"Hello\",\"WoRld\"))\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "R",
|
||||
"language": "R",
|
||||
"name": "ir"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": "r",
|
||||
"file_extension": ".r",
|
||||
"mimetype": "text/x-r-source",
|
||||
"name": "R",
|
||||
"pygments_lexer": "r",
|
||||
"version": "3.2.3"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
24
crates/ruff/resources/test/fixtures/jupyter/invalid_extension.ipynb
vendored
Normal file
24
crates/ruff/resources/test/fixtures/jupyter/invalid_extension.ipynb
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env python
|
||||
# coding: utf-8
|
||||
|
||||
# In[1]:
|
||||
|
||||
|
||||
def unused_variable():
|
||||
x = 1
|
||||
y = 2
|
||||
print(f"cell one: {y}")
|
||||
|
||||
unused_variable()
|
||||
|
||||
|
||||
# Let's do another mistake
|
||||
|
||||
# In[2]:
|
||||
|
||||
|
||||
def mutable_argument(z=set()):
|
||||
print(f"cell two: {z}")
|
||||
|
||||
mutable_argument()
|
||||
|
||||
1
crates/ruff/resources/test/fixtures/jupyter/not_json.ipynb
vendored
Normal file
1
crates/ruff/resources/test/fixtures/jupyter/not_json.ipynb
vendored
Normal file
@@ -0,0 +1 @@
|
||||
broken "§=($/=(")
|
||||
88
crates/ruff/resources/test/fixtures/jupyter/valid.ipynb
vendored
Normal file
88
crates/ruff/resources/test/fixtures/jupyter/valid.ipynb
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"cell one: 2\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"def unused_variable():\n",
|
||||
" x = 1\n",
|
||||
" y = 2\n",
|
||||
" print(f\"cell one: {y}\")\n",
|
||||
"\n",
|
||||
"unused_variable()"
|
||||
],
|
||||
"metadata": {
|
||||
"collapsed": false,
|
||||
"ExecuteTime": {
|
||||
"start_time": "2023-03-08T23:01:09.705831Z",
|
||||
"end_time": "2023-03-08T23:01:09.782916Z"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"Let's do another mistake"
|
||||
],
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {
|
||||
"collapsed": true,
|
||||
"ExecuteTime": {
|
||||
"start_time": "2023-03-08T23:01:09.733809Z",
|
||||
"end_time": "2023-03-08T23:01:09.915760Z"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"cell two: set()\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"def mutable_argument(z=set()):\n",
|
||||
" print(f\"cell two: {z}\")\n",
|
||||
"\n",
|
||||
"mutable_argument()\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 2
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython2",
|
||||
"version": "2.7.6"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0
|
||||
}
|
||||
1
crates/ruff/resources/test/fixtures/jupyter/wrong_schema.ipynb
vendored
Normal file
1
crates/ruff/resources/test/fixtures/jupyter/wrong_schema.ipynb
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{}
|
||||
14
crates/ruff/resources/test/fixtures/pycodestyle/E21.py
vendored
Normal file
14
crates/ruff/resources/test/fixtures/pycodestyle/E21.py
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
#: E211
|
||||
spam (1)
|
||||
#: E211 E211
|
||||
dict ['key'] = list [index]
|
||||
#: E211
|
||||
dict['key'] ['subkey'] = list[index]
|
||||
#: Okay
|
||||
spam(1)
|
||||
dict['key'] = list[index]
|
||||
|
||||
|
||||
# This is not prohibited by PEP8, but avoid it.
|
||||
class Foo (Bar, Baz):
|
||||
pass
|
||||
15
crates/ruff/resources/test/fixtures/pycodestyle/E23.py
vendored
Normal file
15
crates/ruff/resources/test/fixtures/pycodestyle/E23.py
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
#: E231
|
||||
a = (1,2)
|
||||
#: E231
|
||||
a[b1,:]
|
||||
#: E231
|
||||
a = [{'a':''}]
|
||||
#: Okay
|
||||
a = (4,)
|
||||
b = (5, )
|
||||
c = {'text': text[5:]}
|
||||
|
||||
result = {
|
||||
'key1': 'value',
|
||||
'key2': 'value',
|
||||
}
|
||||
@@ -54,3 +54,7 @@ if type(a) != type(b) or type(a) == type(ccc):
|
||||
pass
|
||||
|
||||
assert type(res) == type(None)
|
||||
|
||||
types = StrEnum
|
||||
if x == types.X:
|
||||
pass
|
||||
|
||||
3
crates/ruff/resources/test/fixtures/pydocstyle/D209_D400.py
vendored
Normal file
3
crates/ruff/resources/test/fixtures/pydocstyle/D209_D400.py
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
def lorem():
|
||||
"""lorem ipsum dolor sit amet consectetur adipiscing elit
|
||||
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"""
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
from functools import cached_property
|
||||
|
||||
from gi.repository import GObject
|
||||
|
||||
# Bad examples
|
||||
|
||||
def bad_liouiwnlkjl():
|
||||
@@ -76,6 +78,11 @@ class Thingy:
|
||||
"""This property method docstring does not need to be written in imperative mood."""
|
||||
return self._beep
|
||||
|
||||
@GObject.Property
|
||||
def good_custom_property(self):
|
||||
"""This property method docstring does not need to be written in imperative mood."""
|
||||
return self._beep
|
||||
|
||||
@cached_property
|
||||
def good_cached_property(self):
|
||||
"""This property method docstring does not need to be written in imperative mood."""
|
||||
|
||||
@@ -113,3 +113,13 @@ def f(x, *args, **kwargs):
|
||||
**kwargs: keyword arguments
|
||||
"""
|
||||
return x
|
||||
|
||||
|
||||
class Test:
|
||||
def f(self, /, arg1: int) -> None:
|
||||
"""
|
||||
Some beauty description.
|
||||
|
||||
Args:
|
||||
arg1: some description of arg
|
||||
"""
|
||||
|
||||
1
crates/ruff/resources/test/fixtures/pydocstyle/bom.py
vendored
Normal file
1
crates/ruff/resources/test/fixtures/pydocstyle/bom.py
vendored
Normal file
@@ -0,0 +1 @@
|
||||
''' SAM macro definitions '''
|
||||
@@ -58,6 +58,15 @@ def no_underline_and_no_description(): # noqa: D416
|
||||
"""
|
||||
|
||||
|
||||
@expect(_D213)
|
||||
@expect("D407: Missing dashed underline after section ('Returns')")
|
||||
@expect("D414: Section has no content ('Returns')")
|
||||
def no_underline_and_no_newline(): # noqa: D416
|
||||
"""Toggle the gizmo.
|
||||
|
||||
Returns"""
|
||||
|
||||
|
||||
@expect(_D213)
|
||||
@expect("D410: Missing blank line after section ('Returns')")
|
||||
@expect("D414: Section has no content ('Returns')")
|
||||
@@ -495,3 +504,12 @@ Testing this incorrectly indented docstring.
|
||||
x: Test argument.
|
||||
|
||||
"""
|
||||
|
||||
|
||||
def implicit_string_concatenation():
|
||||
"""Toggle the gizmo.
|
||||
|
||||
Returns
|
||||
A value of some sort.
|
||||
|
||||
""""Extra content"
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"{1:{0}}".format(1, 2) # No issues
|
||||
"{1:{0}}".format(1, 2, 3) # F523
|
||||
"{0}{2}".format(1, 2) # F523, # F524
|
||||
"{1.arg[1]!r:0{2['arg']}{1}}".format(1, 2, 3, 4) # F523
|
||||
|
||||
# With no indexes
|
||||
"{}".format(1, 2) # F523
|
||||
|
||||
23
crates/ruff/resources/test/fixtures/pyflakes/F821_11.py
vendored
Normal file
23
crates/ruff/resources/test/fixtures/pyflakes/F821_11.py
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
"""Test case: strings used within calls within type annotations."""
|
||||
|
||||
from typing import Callable
|
||||
|
||||
import bpy
|
||||
from mypy_extensions import VarArg
|
||||
|
||||
from foo import Bar
|
||||
|
||||
|
||||
class LightShow(bpy.types.Operator):
|
||||
label = "Create Character"
|
||||
name = "lightshow.letter_creation"
|
||||
|
||||
filepath: bpy.props.StringProperty(subtype="FILE_PATH") # OK
|
||||
|
||||
|
||||
def f(x: Callable[[VarArg("os")], None]): # F821
|
||||
pass
|
||||
|
||||
|
||||
f(Callable[["Bar"], None])
|
||||
f(Callable[["Baz"], None])
|
||||
25
crates/ruff/resources/test/fixtures/pyflakes/F821_12.py
vendored
Normal file
25
crates/ruff/resources/test/fixtures/pyflakes/F821_12.py
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
"""Test case: strings used within calls within type annotations."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Callable
|
||||
|
||||
import bpy
|
||||
from mypy_extensions import VarArg
|
||||
|
||||
from foo import Bar
|
||||
|
||||
|
||||
class LightShow(bpy.types.Operator):
|
||||
label = "Create Character"
|
||||
name = "lightshow.letter_creation"
|
||||
|
||||
filepath: bpy.props.StringProperty(subtype="FILE_PATH") # OK
|
||||
|
||||
|
||||
def f(x: Callable[[VarArg("os")], None]): # F821
|
||||
pass
|
||||
|
||||
|
||||
f(Callable[["Bar"], None])
|
||||
f(Callable[["Baz"], None])
|
||||
24
crates/ruff/resources/test/fixtures/pylint/assert_on_string_literal.py
vendored
Normal file
24
crates/ruff/resources/test/fixtures/pylint/assert_on_string_literal.py
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
def test_division():
|
||||
a = 9 / 3
|
||||
assert "No ZeroDivisionError were raised" # [assert-on-string-literal]
|
||||
|
||||
|
||||
def test_division():
|
||||
a = 9 / 3
|
||||
assert a == 3
|
||||
|
||||
|
||||
try:
|
||||
assert "bad" # [assert-on-string-literal]
|
||||
except:
|
||||
assert "bad again" # [assert-on-string-literal]
|
||||
|
||||
a = 12
|
||||
assert f"hello {a}" # [assert-on-string-literal]
|
||||
assert f"{a}" # [assert-on-string-literal]
|
||||
assert f"" # [assert-on-string-literal]
|
||||
assert "" # [assert-on-string-literal]
|
||||
assert b"hello" # [assert-on-string-literal]
|
||||
assert "", b"hi" # [assert-on-string-literal]
|
||||
assert "WhyNotHere?", "HereIsOk" # [assert-on-string-literal]
|
||||
assert 12, "ok here"
|
||||
14
crates/ruff/resources/test/fixtures/pylint/binary_op_exception.py
vendored
Normal file
14
crates/ruff/resources/test/fixtures/pylint/binary_op_exception.py
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
try:
|
||||
1 / 0
|
||||
except ZeroDivisionError or ValueError as e: # [binary-op-exception]
|
||||
pass
|
||||
|
||||
try:
|
||||
raise ValueError
|
||||
except ZeroDivisionError and ValueError as e: # [binary-op-exception]
|
||||
print(e)
|
||||
|
||||
try:
|
||||
pass
|
||||
except (ValueError, Exception, IOError):
|
||||
pass
|
||||
23
crates/ruff/resources/test/fixtures/pylint/compare_to_empty_string.py
vendored
Normal file
23
crates/ruff/resources/test/fixtures/pylint/compare_to_empty_string.py
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
x = "a string"
|
||||
y = "another string"
|
||||
z = ""
|
||||
|
||||
|
||||
def errors():
|
||||
if x is "" or x == "":
|
||||
print("x is an empty string")
|
||||
|
||||
if y is not "" or y != "":
|
||||
print("y is not an empty string")
|
||||
|
||||
if "" != z:
|
||||
print("z is an empty string")
|
||||
|
||||
|
||||
def ok():
|
||||
if x and not y:
|
||||
print("x is not an empty string, but y is an empty string")
|
||||
|
||||
|
||||
data.loc[data["a"] != ""]
|
||||
data.loc[data["a"] != "", :]
|
||||
95
crates/ruff/resources/test/fixtures/pylint/continue_in_finally.py
vendored
Normal file
95
crates/ruff/resources/test/fixtures/pylint/continue_in_finally.py
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
while True:
|
||||
try:
|
||||
pass
|
||||
finally:
|
||||
continue # [continue-in-finally]
|
||||
|
||||
while True:
|
||||
try:
|
||||
pass
|
||||
except Exception:
|
||||
continue
|
||||
finally:
|
||||
try:
|
||||
pass
|
||||
finally:
|
||||
continue # [continue-in-finally]
|
||||
pass
|
||||
|
||||
while True:
|
||||
try:
|
||||
pass
|
||||
finally:
|
||||
test = "aa"
|
||||
match test:
|
||||
case "aa":
|
||||
continue # [continue-in-finally]
|
||||
|
||||
while True:
|
||||
try:
|
||||
pass
|
||||
finally:
|
||||
with "aa" as f:
|
||||
continue # [continue-in-finally]
|
||||
|
||||
while True:
|
||||
try:
|
||||
pass
|
||||
finally:
|
||||
if True:
|
||||
continue # [continue-in-finally]
|
||||
continue # [continue-in-finally]
|
||||
|
||||
def test():
|
||||
while True:
|
||||
continue
|
||||
try:
|
||||
pass
|
||||
finally:
|
||||
continue # [continue-in-finally]
|
||||
|
||||
|
||||
while True:
|
||||
try:
|
||||
pass
|
||||
finally:
|
||||
continue # [continue-in-finally]
|
||||
|
||||
def test():
|
||||
while True:
|
||||
continue
|
||||
|
||||
|
||||
while True:
|
||||
try:
|
||||
pass
|
||||
finally:
|
||||
for i in range(12):
|
||||
continue
|
||||
continue # [continue-in-finally]
|
||||
|
||||
while True:
|
||||
pass
|
||||
else:
|
||||
continue # [continue-in-finally]
|
||||
|
||||
def test():
|
||||
continue
|
||||
while True:
|
||||
continue
|
||||
|
||||
|
||||
while True:
|
||||
try:
|
||||
pass
|
||||
finally:
|
||||
if True:
|
||||
pass
|
||||
elif False:
|
||||
continue # [continue-in-finally]
|
||||
else:
|
||||
continue # [continue-in-finally]
|
||||
for i in range(10):
|
||||
pass
|
||||
else:
|
||||
continue # [continue-in-finally]
|
||||
BIN
crates/ruff/resources/test/fixtures/pylint/invalid_characters.py
vendored
Normal file
BIN
crates/ruff/resources/test/fixtures/pylint/invalid_characters.py
vendored
Normal file
Binary file not shown.
12
crates/ruff/resources/test/fixtures/pylint/invalid_envvar_default.py
vendored
Normal file
12
crates/ruff/resources/test/fixtures/pylint/invalid_envvar_default.py
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
import os
|
||||
|
||||
tempVar = os.getenv("TEST", 12) # [invalid-envvar-default]
|
||||
goodVar = os.getenv("TESTING", None)
|
||||
dictVarBad = os.getenv("AAA", {"a", 7}) # [invalid-envvar-default]
|
||||
print(os.getenv("TEST", False)) # [invalid-envvar-default]
|
||||
os.getenv("AA", "GOOD")
|
||||
os.getenv("AA", f"GOOD")
|
||||
os.getenv("AA", "GOOD" + "BAD")
|
||||
os.getenv("AA", "GOOD" + 1)
|
||||
os.getenv("AA", "GOOD %s" % "BAD")
|
||||
os.getenv("B", Z)
|
||||
15
crates/ruff/resources/test/fixtures/pylint/invalid_envvar_value.py
vendored
Normal file
15
crates/ruff/resources/test/fixtures/pylint/invalid_envvar_value.py
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
import os
|
||||
|
||||
os.getenv(1) # [invalid-envvar-value]
|
||||
os.getenv("a")
|
||||
os.getenv("test")
|
||||
os.getenv(key="testingAgain")
|
||||
os.getenv(key=11) # [invalid-envvar-value]
|
||||
os.getenv(["hello"]) # [invalid-envvar-value]
|
||||
os.getenv(key="foo", default="bar")
|
||||
os.getenv(key=f"foo", default="bar")
|
||||
os.getenv(key="foo" + "bar", default=1)
|
||||
os.getenv(key=1 + "bar", default=1) # [invalid-envvar-value]
|
||||
|
||||
AA = "aa"
|
||||
os.getenv(AA)
|
||||
@@ -11,6 +11,9 @@ if 10 == 100: # [comparison-of-constants] R0133
|
||||
if 1 == 3: # [comparison-of-constants] R0133
|
||||
pass
|
||||
|
||||
if 1 == -3: # [comparison-of-constants] R0133
|
||||
pass
|
||||
|
||||
x = 0
|
||||
if 4 == 3 == x: # [comparison-of-constants] R0133
|
||||
pass
|
||||
@@ -35,6 +38,12 @@ if argc != 1: # correct
|
||||
if argc != 2: # [magic-value-comparison]
|
||||
pass
|
||||
|
||||
if argc != -2: # [magic-value-comparison]
|
||||
pass
|
||||
|
||||
if argc != +2: # [magic-value-comparison]
|
||||
pass
|
||||
|
||||
if __name__ == "__main__": # correct
|
||||
pass
|
||||
|
||||
|
||||
50
crates/ruff/resources/test/fixtures/pylint/useless_return.py
vendored
Normal file
50
crates/ruff/resources/test/fixtures/pylint/useless_return.py
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
import sys
|
||||
|
||||
|
||||
def print_python_version():
|
||||
print(sys.version)
|
||||
return None # [useless-return]
|
||||
|
||||
|
||||
def print_python_version():
|
||||
print(sys.version)
|
||||
return None # [useless-return]
|
||||
|
||||
|
||||
def print_python_version():
|
||||
print(sys.version)
|
||||
return None # [useless-return]
|
||||
|
||||
|
||||
class SomeClass:
|
||||
def print_python_version(self):
|
||||
print(sys.version)
|
||||
return None # [useless-return]
|
||||
|
||||
|
||||
def print_python_version():
|
||||
if 2 * 2 == 4:
|
||||
return
|
||||
print(sys.version)
|
||||
|
||||
|
||||
def print_python_version():
|
||||
if 2 * 2 == 4:
|
||||
return None
|
||||
return
|
||||
|
||||
|
||||
def print_python_version():
|
||||
if 2 * 2 == 4:
|
||||
return None
|
||||
|
||||
|
||||
def print_python_version():
|
||||
"""This function returns None."""
|
||||
return None
|
||||
|
||||
|
||||
def print_python_version():
|
||||
"""This function returns None."""
|
||||
print(sys.version)
|
||||
return None # [useless-return]
|
||||
@@ -25,22 +25,7 @@ avoid-escape = true
|
||||
max-complexity = 10
|
||||
|
||||
[tool.ruff.pep8-naming]
|
||||
ignore-names = [
|
||||
"setUp",
|
||||
"tearDown",
|
||||
"setUpClass",
|
||||
"tearDownClass",
|
||||
"setUpModule",
|
||||
"tearDownModule",
|
||||
"asyncSetUp",
|
||||
"asyncTearDown",
|
||||
"setUpTestData",
|
||||
"failureException",
|
||||
"longMessage",
|
||||
"maxDiff",
|
||||
]
|
||||
classmethod-decorators = ["classmethod", "pydantic.validator"]
|
||||
staticmethod-decorators = ["staticmethod"]
|
||||
classmethod-decorators = ["pydantic.validator"]
|
||||
|
||||
[tool.ruff.flake8-tidy-imports]
|
||||
ban-relative-imports = "parents"
|
||||
|
||||
@@ -46,3 +46,8 @@ def f(x: Union[("str", "int"), float]) -> None:
|
||||
def f() -> None:
|
||||
x: Optional[str]
|
||||
x = Optional[str]
|
||||
|
||||
x = Union[str, int]
|
||||
x = Union["str", "int"]
|
||||
x: Union[str, int]
|
||||
x: Union["str", "int"]
|
||||
|
||||
@@ -12,11 +12,17 @@ Ipsum
|
||||
""".encode(
|
||||
"utf-8"
|
||||
)
|
||||
# b"""
|
||||
# Lorem
|
||||
#
|
||||
# Ipsum
|
||||
# """
|
||||
(
|
||||
"Lorem "
|
||||
"Ipsum".encode()
|
||||
)
|
||||
(
|
||||
"Lorem " # Comment
|
||||
"Ipsum".encode() # Comment
|
||||
)
|
||||
(
|
||||
"Lorem " "Ipsum".encode()
|
||||
)
|
||||
|
||||
# `encode` on variables should not be processed.
|
||||
string = "hello there"
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
from io import open
|
||||
|
||||
with open("f.txt") as f:
|
||||
print(f.read())
|
||||
|
||||
import io
|
||||
|
||||
with io.open("f.txt", mode="r", buffering=-1, **kwargs) as f:
|
||||
print(f.read())
|
||||
|
||||
from io import open
|
||||
|
||||
with open("f.txt") as f:
|
||||
print(f.read())
|
||||
|
||||
10
crates/ruff/resources/test/fixtures/pyupgrade/UP024_4.py
vendored
Normal file
10
crates/ruff/resources/test/fixtures/pyupgrade/UP024_4.py
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
import socket
|
||||
|
||||
from kombu import Connection, exceptions
|
||||
|
||||
try:
|
||||
conn = Connection(settings.CELERY_BROKER_URL)
|
||||
conn.ensure_connection(max_retries=2)
|
||||
conn._close()
|
||||
except (socket.error, exceptions.OperationalError):
|
||||
return HttpResponseServerError("cache: cannot connect to broker.")
|
||||
@@ -1,24 +1,29 @@
|
||||
# These should be changed
|
||||
# Error (`from unittest import mock`)
|
||||
if True:
|
||||
import mock
|
||||
|
||||
# Error (`from unittest import mock`)
|
||||
if True:
|
||||
import mock, sys
|
||||
|
||||
# This goes to from unitest import mock
|
||||
# Error (`from unittest.mock import *`)
|
||||
if True:
|
||||
from mock import *
|
||||
|
||||
# Error (`from unittest import mock`)
|
||||
import mock.mock
|
||||
|
||||
# Mock should go on a new line as `from unittest import mock`
|
||||
# Error (`from unittest import mock`)
|
||||
import contextlib, mock, sys
|
||||
|
||||
# Mock should go on a new line as `from unittest import mock`
|
||||
# Error (`from unittest import mock`)
|
||||
import mock, sys
|
||||
x = "This code should be preserved one line below the mock"
|
||||
|
||||
# Mock should go on a new line as `from unittest import mock`
|
||||
# Error (`from unittest import mock`)
|
||||
from mock import mock
|
||||
|
||||
# Should keep trailing comma
|
||||
# Error (keep trailing comma)
|
||||
from mock import (
|
||||
mock,
|
||||
a,
|
||||
@@ -32,7 +37,7 @@ from mock import (
|
||||
mock,
|
||||
)
|
||||
|
||||
# Should not get a trailing comma
|
||||
# Error (avoid trailing comma)
|
||||
from mock import (
|
||||
mock,
|
||||
a,
|
||||
@@ -57,16 +62,16 @@ if True:
|
||||
c
|
||||
)
|
||||
|
||||
# These should not change:
|
||||
# OK
|
||||
import os, io
|
||||
|
||||
# Mock should go on a new line as `from unittest import mock`
|
||||
# Error (`from unittest import mock`)
|
||||
import mock, mock
|
||||
|
||||
# Mock should go on a new line as `from unittest import mock as foo`
|
||||
# Error (`from unittest import mock as foo`)
|
||||
import mock as foo
|
||||
|
||||
# Mock should go on a new line as `from unittest import mock as foo`
|
||||
# Error (`from unittest import mock as foo`)
|
||||
from mock import mock as foo
|
||||
|
||||
if True:
|
||||
@@ -81,8 +86,8 @@ if True:
|
||||
from mock import mock as foo, mock as bar, mock
|
||||
|
||||
|
||||
# This should be unchanged.
|
||||
# OK.
|
||||
x = mock.Mock()
|
||||
|
||||
# This should change to `mock.Mock`().
|
||||
# Error (`mock.Mock()`).
|
||||
x = mock.mock.Mock()
|
||||
|
||||
@@ -73,3 +73,13 @@ print("%s \N{snowman}" % (a,))
|
||||
print("%(foo)s \N{snowman}" % {"foo": 1})
|
||||
|
||||
print(("foo %s " "bar %s") % (x, y))
|
||||
|
||||
# Single-value expressions
|
||||
print('Hello %s' % "World")
|
||||
print('Hello %s' % f"World")
|
||||
print('Hello %s (%s)' % bar)
|
||||
print('Hello %s (%s)' % bar.baz)
|
||||
print('Hello %s (%s)' % bar['bop'])
|
||||
print('Hello %(arg)s' % bar)
|
||||
print('Hello %(arg)s' % bar.baz)
|
||||
print('Hello %(arg)s' % bar['bop'])
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
# OK
|
||||
"%s" % unknown_type
|
||||
|
||||
b"%s" % (b"bytestring",)
|
||||
|
||||
"%*s" % (5, "hi")
|
||||
@@ -57,3 +55,9 @@ pytest.param('"%8s" % (None,)', id="unsafe width-string conversion"),
|
||||
"""
|
||||
% (x,)
|
||||
)
|
||||
|
||||
'Hello %s' % bar
|
||||
|
||||
'Hello %s' % bar.baz
|
||||
|
||||
'Hello %s' % bar['bop']
|
||||
|
||||
@@ -86,3 +86,14 @@ async def c():
|
||||
|
||||
async def c():
|
||||
return "{}".format(1 + await 3)
|
||||
|
||||
|
||||
def d(osname, version, release):
|
||||
return"{}-{}.{}".format(osname, version, release)
|
||||
|
||||
|
||||
def e():
|
||||
yield"{}".format(1)
|
||||
|
||||
|
||||
assert"{}".format(1)
|
||||
|
||||
@@ -41,7 +41,7 @@ if True:
|
||||
Good,
|
||||
)
|
||||
|
||||
from typing import Callable, Match, Pattern, List
|
||||
from typing import Callable, Match, Pattern, List, OrderedDict, AbstractSet, ContextManager
|
||||
|
||||
if True: from collections import (
|
||||
Mapping, Counter)
|
||||
|
||||
9
crates/ruff/resources/test/fixtures/pyupgrade/UP038.py
vendored
Normal file
9
crates/ruff/resources/test/fixtures/pyupgrade/UP038.py
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
isinstance(1, (int, float)) # UP038
|
||||
issubclass("yes", (int, float, str)) # UP038
|
||||
|
||||
isinstance(1, int) # OK
|
||||
issubclass("yes", int) # OK
|
||||
isinstance(1, int | float) # OK
|
||||
issubclass("yes", int | str) # OK
|
||||
isinstance(1, ()) # OK
|
||||
isinstance(1, (int, *(str, bytes))) # OK
|
||||
19
crates/ruff/resources/test/fixtures/ruff/RUF007.py
vendored
Normal file
19
crates/ruff/resources/test/fixtures/ruff/RUF007.py
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
input = [1, 2, 3]
|
||||
otherInput = [2, 3, 4]
|
||||
|
||||
# OK
|
||||
zip(input, otherInput) # different inputs
|
||||
zip(input, otherInput[1:]) # different inputs
|
||||
zip(input, input[2:]) # not successive
|
||||
zip(input[:-1], input[2:]) # not successive
|
||||
list(zip(input, otherInput)) # nested call
|
||||
zip(input, input[1::2]) # not successive
|
||||
|
||||
# Errors
|
||||
zip(input, input[1:])
|
||||
zip(input, input[1::1])
|
||||
zip(input[:-1], input[1:])
|
||||
zip(input[1:], input[2:])
|
||||
zip(input[1:-1], input[2:])
|
||||
list(zip(input, input[1:]))
|
||||
list(zip(input[:-1], input[1:]))
|
||||
25
crates/ruff/resources/test/fixtures/ruff/RUF100_3.py
vendored
Normal file
25
crates/ruff/resources/test/fixtures/ruff/RUF100_3.py
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
# noqa
|
||||
# noqa # comment
|
||||
print() # noqa
|
||||
print() # noqa # comment
|
||||
print() # noqa # comment
|
||||
print() # noqa comment
|
||||
print() # noqa comment
|
||||
print(a) # noqa
|
||||
print(a) # noqa # comment
|
||||
print(a) # noqa # comment
|
||||
print(a) # noqa comment
|
||||
print(a) # noqa comment
|
||||
|
||||
# noqa: E501, F821
|
||||
# noqa: E501, F821 # comment
|
||||
print() # noqa: E501, F821
|
||||
print() # noqa: E501, F821 # comment
|
||||
print() # noqa: E501, F821 # comment
|
||||
print() # noqa: E501, F821 comment
|
||||
print() # noqa: E501, F821 comment
|
||||
print(a) # noqa: E501, F821
|
||||
print(a) # noqa: E501, F821 # comment
|
||||
print(a) # noqa: E501, F821 # comment
|
||||
print(a) # noqa: E501, F821 comment
|
||||
print(a) # noqa: E501, F821 comment
|
||||
@@ -45,3 +45,10 @@ def still_good():
|
||||
return process()
|
||||
except MyException:
|
||||
logger.exception("process failed")
|
||||
|
||||
def good_noexcept():
|
||||
try:
|
||||
pass
|
||||
return process()
|
||||
finally:
|
||||
logger.exception("process failed")
|
||||
|
||||
@@ -9,30 +9,30 @@ Running from the repo root should pick up and enforce the appropriate settings f
|
||||
|
||||
```console
|
||||
∴ cargo run -p ruff_cli -- check crates/ruff/resources/test/project/
|
||||
crates/ruff/resources/test/project/examples/.dotfiles/script.py:1:1: I001 Import block is un-sorted or un-formatted
|
||||
crates/ruff/resources/test/project/examples/.dotfiles/script.py:1:8: F401 `numpy` imported but unused
|
||||
crates/ruff/resources/test/project/examples/.dotfiles/script.py:2:17: F401 `app.app_file` imported but unused
|
||||
crates/ruff/resources/test/project/examples/docs/docs/file.py:1:1: I001 Import block is un-sorted or un-formatted
|
||||
crates/ruff/resources/test/project/examples/docs/docs/file.py:8:5: F841 Local variable `x` is assigned to but never used
|
||||
crates/ruff/resources/test/project/project/file.py:1:8: F401 `os` imported but unused
|
||||
crates/ruff/resources/test/project/project/import_file.py:1:1: I001 Import block is un-sorted or un-formatted
|
||||
crates/ruff/resources/test/project/examples/.dotfiles/script.py:1:1: I001 [*] Import block is un-sorted or un-formatted
|
||||
crates/ruff/resources/test/project/examples/.dotfiles/script.py:1:8: F401 [*] `numpy` imported but unused
|
||||
crates/ruff/resources/test/project/examples/.dotfiles/script.py:2:17: F401 [*] `app.app_file` imported but unused
|
||||
crates/ruff/resources/test/project/examples/docs/docs/file.py:1:1: I001 [*] Import block is un-sorted or un-formatted
|
||||
crates/ruff/resources/test/project/examples/docs/docs/file.py:8:5: F841 [*] Local variable `x` is assigned to but never used
|
||||
crates/ruff/resources/test/project/project/file.py:1:8: F401 [*] `os` imported but unused
|
||||
crates/ruff/resources/test/project/project/import_file.py:1:1: I001 [*] Import block is un-sorted or un-formatted
|
||||
Found 7 errors.
|
||||
7 potentially fixable with the --fix option.
|
||||
[*] 7 potentially fixable with the --fix option.
|
||||
```
|
||||
|
||||
Running from the project directory itself should exhibit the same behavior:
|
||||
|
||||
```console
|
||||
∴ (cd crates/ruff/resources/test/project/ && cargo run -p ruff_cli -- check .)
|
||||
examples/.dotfiles/script.py:1:1: I001 Import block is un-sorted or un-formatted
|
||||
examples/.dotfiles/script.py:1:8: F401 `numpy` imported but unused
|
||||
examples/.dotfiles/script.py:2:17: F401 `app.app_file` imported but unused
|
||||
examples/docs/docs/file.py:1:1: I001 Import block is un-sorted or un-formatted
|
||||
examples/docs/docs/file.py:8:5: F841 Local variable `x` is assigned to but never used
|
||||
project/file.py:1:8: F401 `os` imported but unused
|
||||
project/import_file.py:1:1: I001 Import block is un-sorted or un-formatted
|
||||
examples/.dotfiles/script.py:1:1: I001 [*] Import block is un-sorted or un-formatted
|
||||
examples/.dotfiles/script.py:1:8: F401 [*] `numpy` imported but unused
|
||||
examples/.dotfiles/script.py:2:17: F401 [*] `app.app_file` imported but unused
|
||||
examples/docs/docs/file.py:1:1: I001 [*] Import block is un-sorted or un-formatted
|
||||
examples/docs/docs/file.py:8:5: F841 [*] Local variable `x` is assigned to but never used
|
||||
project/file.py:1:8: F401 [*] `os` imported but unused
|
||||
project/import_file.py:1:1: I001 [*] Import block is un-sorted or un-formatted
|
||||
Found 7 errors.
|
||||
7 potentially fixable with the --fix option.
|
||||
[*] 7 potentially fixable with the --fix option.
|
||||
```
|
||||
|
||||
Running from the sub-package directory should exhibit the same behavior, but omit the top-level
|
||||
@@ -40,10 +40,10 @@ files:
|
||||
|
||||
```console
|
||||
∴ (cd crates/ruff/resources/test/project/examples/docs && cargo run -p ruff_cli -- check .)
|
||||
docs/file.py:1:1: I001 Import block is un-sorted or un-formatted
|
||||
docs/file.py:8:5: F841 Local variable `x` is assigned to but never used
|
||||
docs/file.py:1:1: I001 [*] Import block is un-sorted or un-formatted
|
||||
docs/file.py:8:5: F841 [*] Local variable `x` is assigned to but never used
|
||||
Found 2 errors.
|
||||
2 potentially fixable with the --fix option.
|
||||
[*] 2 potentially fixable with the --fix option.
|
||||
```
|
||||
|
||||
`--config` should force Ruff to use the specified `pyproject.toml` for all files, and resolve
|
||||
@@ -51,17 +51,17 @@ file paths from the current working directory:
|
||||
|
||||
```console
|
||||
∴ (cargo run -p ruff_cli -- check --config=crates/ruff/resources/test/project/pyproject.toml crates/ruff/resources/test/project/)
|
||||
crates/ruff/resources/test/project/examples/.dotfiles/script.py:1:8: F401 `numpy` imported but unused
|
||||
crates/ruff/resources/test/project/examples/.dotfiles/script.py:2:17: F401 `app.app_file` imported but unused
|
||||
crates/ruff/resources/test/project/examples/docs/docs/concepts/file.py:1:8: F401 `os` imported but unused
|
||||
crates/ruff/resources/test/project/examples/docs/docs/file.py:1:1: I001 Import block is un-sorted or un-formatted
|
||||
crates/ruff/resources/test/project/examples/docs/docs/file.py:1:8: F401 `os` imported but unused
|
||||
crates/ruff/resources/test/project/examples/docs/docs/file.py:3:8: F401 `numpy` imported but unused
|
||||
crates/ruff/resources/test/project/examples/docs/docs/file.py:4:27: F401 `docs.concepts.file` imported but unused
|
||||
crates/ruff/resources/test/project/examples/excluded/script.py:1:8: F401 `os` imported but unused
|
||||
crates/ruff/resources/test/project/project/file.py:1:8: F401 `os` imported but unused
|
||||
crates/ruff/resources/test/project/examples/.dotfiles/script.py:1:8: F401 [*] `numpy` imported but unused
|
||||
crates/ruff/resources/test/project/examples/.dotfiles/script.py:2:17: F401 [*] `app.app_file` imported but unused
|
||||
crates/ruff/resources/test/project/examples/docs/docs/concepts/file.py:1:8: F401 [*] `os` imported but unused
|
||||
crates/ruff/resources/test/project/examples/docs/docs/file.py:1:1: I001 [*] Import block is un-sorted or un-formatted
|
||||
crates/ruff/resources/test/project/examples/docs/docs/file.py:1:8: F401 [*] `os` imported but unused
|
||||
crates/ruff/resources/test/project/examples/docs/docs/file.py:3:8: F401 [*] `numpy` imported but unused
|
||||
crates/ruff/resources/test/project/examples/docs/docs/file.py:4:27: F401 [*] `docs.concepts.file` imported but unused
|
||||
crates/ruff/resources/test/project/examples/excluded/script.py:1:8: F401 [*] `os` imported but unused
|
||||
crates/ruff/resources/test/project/project/file.py:1:8: F401 [*] `os` imported but unused
|
||||
Found 9 errors.
|
||||
9 potentially fixable with the --fix option.
|
||||
[*] 9 potentially fixable with the --fix option.
|
||||
```
|
||||
|
||||
Running from a parent directory should "ignore" the `exclude` (hence, `concepts/file.py` gets
|
||||
@@ -69,21 +69,21 @@ included in the output):
|
||||
|
||||
```console
|
||||
∴ (cd crates/ruff/resources/test/project/examples && cargo run -p ruff_cli -- check --config=docs/ruff.toml .)
|
||||
docs/docs/concepts/file.py:5:5: F841 Local variable `x` is assigned to but never used
|
||||
docs/docs/file.py:1:1: I001 Import block is un-sorted or un-formatted
|
||||
docs/docs/file.py:8:5: F841 Local variable `x` is assigned to but never used
|
||||
excluded/script.py:5:5: F841 Local variable `x` is assigned to but never used
|
||||
docs/docs/concepts/file.py:5:5: F841 [*] Local variable `x` is assigned to but never used
|
||||
docs/docs/file.py:1:1: I001 [*] Import block is un-sorted or un-formatted
|
||||
docs/docs/file.py:8:5: F841 [*] Local variable `x` is assigned to but never used
|
||||
excluded/script.py:5:5: F841 [*] Local variable `x` is assigned to but never used
|
||||
Found 4 errors.
|
||||
4 potentially fixable with the --fix option.
|
||||
[*] 4 potentially fixable with the --fix option.
|
||||
```
|
||||
|
||||
Passing an excluded directory directly should report errors in the contained files:
|
||||
|
||||
```console
|
||||
∴ cargo run -p ruff_cli -- check crates/ruff/resources/test/project/examples/excluded/
|
||||
crates/ruff/resources/test/project/examples/excluded/script.py:1:8: F401 `os` imported but unused
|
||||
crates/ruff/resources/test/project/examples/excluded/script.py:1:8: F401 [*] `os` imported but unused
|
||||
Found 1 error.
|
||||
1 potentially fixable with the --fix option.
|
||||
[*] 1 potentially fixable with the --fix option.
|
||||
```
|
||||
|
||||
Unless we `--force-exclude`:
|
||||
|
||||
@@ -1,279 +0,0 @@
|
||||
use std::ops::Deref;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
use rustc_hash::FxHashMap;
|
||||
use rustpython_parser::ast::{Arguments, Expr, Keyword, Located, Location, Stmt};
|
||||
|
||||
fn id() -> usize {
|
||||
static COUNTER: AtomicUsize = AtomicUsize::new(1);
|
||||
COUNTER.fetch_add(1, Ordering::Relaxed)
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum Node<'a> {
|
||||
Stmt(&'a Stmt),
|
||||
Expr(&'a Expr),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct Range {
|
||||
pub location: Location,
|
||||
pub end_location: Location,
|
||||
}
|
||||
|
||||
impl Range {
|
||||
pub const fn new(location: Location, end_location: Location) -> Self {
|
||||
Self {
|
||||
location,
|
||||
end_location,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_located<T, U>(located: &Located<T, U>) -> Self {
|
||||
Range::new(located.location, located.end_location.unwrap())
|
||||
}
|
||||
|
||||
pub fn contains(&self, other: &Range) -> bool {
|
||||
self.location <= other.location && self.end_location >= other.end_location
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FunctionDef<'a> {
|
||||
// Properties derived from StmtKind::FunctionDef.
|
||||
pub name: &'a str,
|
||||
pub args: &'a Arguments,
|
||||
pub body: &'a [Stmt],
|
||||
pub decorator_list: &'a [Expr],
|
||||
// pub returns: Option<&'a Expr>,
|
||||
// pub type_comment: Option<&'a str>,
|
||||
// Scope-specific properties.
|
||||
// TODO(charlie): Create AsyncFunctionDef to mirror the AST.
|
||||
pub async_: bool,
|
||||
pub globals: FxHashMap<&'a str, &'a Stmt>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ClassDef<'a> {
|
||||
// Properties derived from StmtKind::ClassDef.
|
||||
pub name: &'a str,
|
||||
pub bases: &'a [Expr],
|
||||
pub keywords: &'a [Keyword],
|
||||
// pub body: &'a [Stmt],
|
||||
pub decorator_list: &'a [Expr],
|
||||
// Scope-specific properties.
|
||||
pub globals: FxHashMap<&'a str, &'a Stmt>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Lambda<'a> {
|
||||
pub args: &'a Arguments,
|
||||
pub body: &'a Expr,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ScopeKind<'a> {
|
||||
Class(ClassDef<'a>),
|
||||
Function(FunctionDef<'a>),
|
||||
Generator,
|
||||
Module,
|
||||
Lambda(Lambda<'a>),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Scope<'a> {
|
||||
pub id: usize,
|
||||
pub kind: ScopeKind<'a>,
|
||||
pub import_starred: bool,
|
||||
pub uses_locals: bool,
|
||||
/// A map from bound name to binding index, for live bindings.
|
||||
pub bindings: FxHashMap<&'a str, usize>,
|
||||
/// A map from bound name to binding index, for bindings that were created
|
||||
/// in the scope but rebound (and thus overridden) later on in the same
|
||||
/// scope.
|
||||
pub rebounds: FxHashMap<&'a str, Vec<usize>>,
|
||||
}
|
||||
|
||||
impl<'a> Scope<'a> {
|
||||
pub fn new(kind: ScopeKind<'a>) -> Self {
|
||||
Scope {
|
||||
id: id(),
|
||||
kind,
|
||||
import_starred: false,
|
||||
uses_locals: false,
|
||||
bindings: FxHashMap::default(),
|
||||
rebounds: FxHashMap::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pyflakes defines the following binding hierarchy (via inheritance):
|
||||
// Binding
|
||||
// ExportBinding
|
||||
// Annotation
|
||||
// Argument
|
||||
// Assignment
|
||||
// NamedExprAssignment
|
||||
// Definition
|
||||
// FunctionDefinition
|
||||
// ClassDefinition
|
||||
// Builtin
|
||||
// Importation
|
||||
// SubmoduleImportation
|
||||
// ImportationFrom
|
||||
// StarImportation
|
||||
// FutureImportation
|
||||
|
||||
#[derive(Clone, Debug, is_macro::Is)]
|
||||
pub enum BindingKind<'a> {
|
||||
Annotation,
|
||||
Argument,
|
||||
Assignment,
|
||||
Binding,
|
||||
LoopVar,
|
||||
Global,
|
||||
Nonlocal,
|
||||
Builtin,
|
||||
ClassDefinition,
|
||||
FunctionDefinition,
|
||||
Export(Vec<String>),
|
||||
FutureImportation,
|
||||
StarImportation(Option<usize>, Option<String>),
|
||||
Importation(&'a str, &'a str),
|
||||
FromImportation(&'a str, String),
|
||||
SubmoduleImportation(&'a str, &'a str),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Binding<'a> {
|
||||
pub kind: BindingKind<'a>,
|
||||
pub range: Range,
|
||||
/// The context in which the binding was created.
|
||||
pub context: ExecutionContext,
|
||||
/// The statement in which the [`Binding`] was defined.
|
||||
pub source: Option<RefEquality<'a, Stmt>>,
|
||||
/// Tuple of (scope index, range) indicating the scope and range at which
|
||||
/// the binding was last used in a runtime context.
|
||||
pub runtime_usage: Option<(usize, Range)>,
|
||||
/// Tuple of (scope index, range) indicating the scope and range at which
|
||||
/// the binding was last used in a typing-time context.
|
||||
pub typing_usage: Option<(usize, Range)>,
|
||||
/// Tuple of (scope index, range) indicating the scope and range at which
|
||||
/// the binding was last used in a synthetic context. This is used for
|
||||
/// (e.g.) `__future__` imports, explicit re-exports, and other bindings
|
||||
/// that should be considered used even if they're never referenced.
|
||||
pub synthetic_usage: Option<(usize, Range)>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Debug, Clone)]
|
||||
pub enum ExecutionContext {
|
||||
Runtime,
|
||||
Typing,
|
||||
}
|
||||
|
||||
impl<'a> Binding<'a> {
|
||||
pub fn mark_used(&mut self, scope: usize, range: Range, context: ExecutionContext) {
|
||||
match context {
|
||||
ExecutionContext::Runtime => self.runtime_usage = Some((scope, range)),
|
||||
ExecutionContext::Typing => self.typing_usage = Some((scope, range)),
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn used(&self) -> bool {
|
||||
self.runtime_usage.is_some()
|
||||
|| self.synthetic_usage.is_some()
|
||||
|| self.typing_usage.is_some()
|
||||
}
|
||||
|
||||
pub const fn is_definition(&self) -> bool {
|
||||
matches!(
|
||||
self.kind,
|
||||
BindingKind::ClassDefinition
|
||||
| BindingKind::FunctionDefinition
|
||||
| BindingKind::Builtin
|
||||
| BindingKind::FutureImportation
|
||||
| BindingKind::StarImportation(..)
|
||||
| BindingKind::Importation(..)
|
||||
| BindingKind::FromImportation(..)
|
||||
| BindingKind::SubmoduleImportation(..)
|
||||
)
|
||||
}
|
||||
|
||||
pub fn redefines(&self, existing: &'a Binding) -> bool {
|
||||
match &self.kind {
|
||||
BindingKind::Importation(.., full_name) => {
|
||||
if let BindingKind::SubmoduleImportation(.., existing) = &existing.kind {
|
||||
return full_name == existing;
|
||||
}
|
||||
}
|
||||
BindingKind::FromImportation(.., full_name) => {
|
||||
if let BindingKind::SubmoduleImportation(.., existing) = &existing.kind {
|
||||
return full_name == existing;
|
||||
}
|
||||
}
|
||||
BindingKind::SubmoduleImportation(.., full_name) => match &existing.kind {
|
||||
BindingKind::Importation(.., existing)
|
||||
| BindingKind::SubmoduleImportation(.., existing) => {
|
||||
return full_name == existing;
|
||||
}
|
||||
BindingKind::FromImportation(.., existing) => {
|
||||
return full_name == existing;
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
BindingKind::Annotation => {
|
||||
return false;
|
||||
}
|
||||
BindingKind::FutureImportation => {
|
||||
return false;
|
||||
}
|
||||
BindingKind::StarImportation(..) => {
|
||||
return false;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
existing.is_definition()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct RefEquality<'a, T>(pub &'a T);
|
||||
|
||||
impl<'a, T> std::hash::Hash for RefEquality<'a, T> {
|
||||
fn hash<H>(&self, state: &mut H)
|
||||
where
|
||||
H: std::hash::Hasher,
|
||||
{
|
||||
(self.0 as *const T).hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b, T> PartialEq<RefEquality<'b, T>> for RefEquality<'a, T> {
|
||||
fn eq(&self, other: &RefEquality<'b, T>) -> bool {
|
||||
std::ptr::eq(self.0, other.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> Eq for RefEquality<'a, T> {}
|
||||
|
||||
impl<'a, T> Deref for RefEquality<'a, T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &T {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&RefEquality<'a, Stmt>> for &'a Stmt {
|
||||
fn from(r: &RefEquality<'a, Stmt>) -> Self {
|
||||
r.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&RefEquality<'a, Expr>> for &'a Expr {
|
||||
fn from(r: &RefEquality<'a, Expr>) -> Self {
|
||||
r.0
|
||||
}
|
||||
}
|
||||
|
||||
pub type CallPath<'a> = smallvec::SmallVec<[&'a str; 8]>;
|
||||
@@ -6,14 +6,14 @@ use libcst_native::{
|
||||
use rustpython_parser::ast::{ExcepthandlerKind, Expr, Keyword, Location, Stmt, StmtKind};
|
||||
use rustpython_parser::{lexer, Mode, Tok};
|
||||
|
||||
use crate::ast::helpers;
|
||||
use crate::ast::helpers::to_absolute;
|
||||
use crate::ast::types::Range;
|
||||
use crate::ast::whitespace::LinesWithTrailingNewline;
|
||||
use ruff_diagnostics::Fix;
|
||||
use ruff_python_ast::helpers;
|
||||
use ruff_python_ast::helpers::to_absolute;
|
||||
use ruff_python_ast::newlines::NewlineWithTrailingNewline;
|
||||
use ruff_python_ast::source_code::{Indexer, Locator, Stylist};
|
||||
|
||||
use crate::cst::helpers::compose_module_path;
|
||||
use crate::cst::matchers::match_module;
|
||||
use crate::fix::Fix;
|
||||
use crate::source_code::{Indexer, Locator, Stylist};
|
||||
|
||||
/// Determine if a body contains only a single statement, taking into account
|
||||
/// deleted.
|
||||
@@ -100,7 +100,7 @@ fn is_lone_child(child: &Stmt, parent: &Stmt, deleted: &[&Stmt]) -> Result<bool>
|
||||
/// of a multi-statement line.
|
||||
fn trailing_semicolon(stmt: &Stmt, locator: &Locator) -> Option<Location> {
|
||||
let contents = locator.skip(stmt.end_location.unwrap());
|
||||
for (row, line) in LinesWithTrailingNewline::from(contents).enumerate() {
|
||||
for (row, line) in NewlineWithTrailingNewline::from(contents).enumerate() {
|
||||
let trimmed = line.trim();
|
||||
if trimmed.starts_with(';') {
|
||||
let column = line
|
||||
@@ -123,7 +123,7 @@ fn trailing_semicolon(stmt: &Stmt, locator: &Locator) -> Option<Location> {
|
||||
fn next_stmt_break(semicolon: Location, locator: &Locator) -> Location {
|
||||
let start_location = Location::new(semicolon.row(), semicolon.column() + 1);
|
||||
let contents = locator.skip(start_location);
|
||||
for (row, line) in LinesWithTrailingNewline::from(contents).enumerate() {
|
||||
for (row, line) in NewlineWithTrailingNewline::from(contents).enumerate() {
|
||||
let trimmed = line.trim();
|
||||
// Skip past any continuations.
|
||||
if trimmed.starts_with('\\') {
|
||||
@@ -227,7 +227,7 @@ pub fn remove_unused_imports<'a>(
|
||||
indexer: &Indexer,
|
||||
stylist: &Stylist,
|
||||
) -> Result<Fix> {
|
||||
let module_text = locator.slice(&Range::from_located(stmt));
|
||||
let module_text = locator.slice(stmt);
|
||||
let mut tree = match_module(module_text)?;
|
||||
|
||||
let Some(Statement::Simple(body)) = tree.body.first_mut() else {
|
||||
@@ -450,8 +450,9 @@ mod tests {
|
||||
use rustpython_parser as parser;
|
||||
use rustpython_parser::ast::Location;
|
||||
|
||||
use ruff_python_ast::source_code::Locator;
|
||||
|
||||
use crate::autofix::helpers::{next_stmt_break, trailing_semicolon};
|
||||
use crate::source_code::Locator;
|
||||
|
||||
#[test]
|
||||
fn find_semicolon() -> Result<()> {
|
||||
|
||||
@@ -4,11 +4,12 @@ use itertools::Itertools;
|
||||
use rustc_hash::FxHashMap;
|
||||
use rustpython_parser::ast::Location;
|
||||
|
||||
use crate::ast::types::Range;
|
||||
use crate::fix::Fix;
|
||||
use ruff_diagnostics::{Diagnostic, Fix};
|
||||
use ruff_python_ast::source_code::Locator;
|
||||
use ruff_python_ast::types::Range;
|
||||
|
||||
use crate::linter::FixTable;
|
||||
use crate::registry::Diagnostic;
|
||||
use crate::source_code::Locator;
|
||||
use crate::registry::{AsRule, Rule};
|
||||
|
||||
pub mod helpers;
|
||||
|
||||
@@ -27,7 +28,7 @@ fn apply_fixes<'a>(
|
||||
locator: &'a Locator<'a>,
|
||||
) -> (String, FixTable) {
|
||||
let mut output = String::with_capacity(locator.len());
|
||||
let mut last_pos: Location = Location::new(1, 0);
|
||||
let mut last_pos: Option<Location> = None;
|
||||
let mut applied: BTreeSet<&Fix> = BTreeSet::default();
|
||||
let mut fixed = FxHashMap::default();
|
||||
|
||||
@@ -38,7 +39,7 @@ fn apply_fixes<'a>(
|
||||
.as_ref()
|
||||
.map(|fix| (diagnostic.kind.rule(), fix))
|
||||
})
|
||||
.sorted_by_key(|(.., fix)| fix.location)
|
||||
.sorted_by(|(rule1, fix1), (rule2, fix2)| cmp_fix(*rule1, *rule2, fix1, fix2))
|
||||
{
|
||||
// If we already applied an identical fix as part of another correction, skip
|
||||
// any re-application.
|
||||
@@ -49,25 +50,25 @@ fn apply_fixes<'a>(
|
||||
|
||||
// Best-effort approach: if this fix overlaps with a fix we've already applied,
|
||||
// skip it.
|
||||
if last_pos > fix.location {
|
||||
if last_pos.map_or(false, |last_pos| last_pos >= fix.location) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Add all contents from `last_pos` to `fix.location`.
|
||||
let slice = locator.slice(&Range::new(last_pos, fix.location));
|
||||
let slice = locator.slice(Range::new(last_pos.unwrap_or_default(), fix.location));
|
||||
output.push_str(slice);
|
||||
|
||||
// Add the patch itself.
|
||||
output.push_str(&fix.content);
|
||||
|
||||
// Track that the fix was applied.
|
||||
last_pos = fix.end_location;
|
||||
last_pos = Some(fix.end_location);
|
||||
applied.insert(fix);
|
||||
*fixed.entry(rule).or_default() += 1;
|
||||
}
|
||||
|
||||
// Add the remaining content.
|
||||
let slice = locator.skip(last_pos);
|
||||
let slice = locator.skip(last_pos.unwrap_or_default());
|
||||
output.push_str(slice);
|
||||
|
||||
(output, fixed)
|
||||
@@ -78,7 +79,7 @@ pub(crate) fn apply_fix(fix: &Fix, locator: &Locator) -> String {
|
||||
let mut output = String::with_capacity(locator.len());
|
||||
|
||||
// Add all contents from `last_pos` to `fix.location`.
|
||||
let slice = locator.slice(&Range::new(Location::new(1, 0), fix.location));
|
||||
let slice = locator.slice(Range::new(Location::new(1, 0), fix.location));
|
||||
output.push_str(slice);
|
||||
|
||||
// Add the patch itself.
|
||||
@@ -91,47 +92,54 @@ pub(crate) fn apply_fix(fix: &Fix, locator: &Locator) -> String {
|
||||
output
|
||||
}
|
||||
|
||||
/// Compare two fixes.
|
||||
fn cmp_fix(rule1: Rule, rule2: Rule, fix1: &Fix, fix2: &Fix) -> std::cmp::Ordering {
|
||||
fix1.location
|
||||
.cmp(&fix2.location)
|
||||
.then_with(|| match (&rule1, &rule2) {
|
||||
// Apply `EndsInPeriod` fixes before `NewLineAfterLastParagraph` fixes.
|
||||
(Rule::EndsInPeriod, Rule::NewLineAfterLastParagraph) => std::cmp::Ordering::Less,
|
||||
(Rule::NewLineAfterLastParagraph, Rule::EndsInPeriod) => std::cmp::Ordering::Greater,
|
||||
_ => std::cmp::Ordering::Equal,
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use rustpython_parser::ast::Location;
|
||||
|
||||
use ruff_diagnostics::Diagnostic;
|
||||
use ruff_diagnostics::Fix;
|
||||
use ruff_python_ast::source_code::Locator;
|
||||
|
||||
use crate::autofix::{apply_fix, apply_fixes};
|
||||
use crate::fix::Fix;
|
||||
use crate::registry::Diagnostic;
|
||||
use crate::rules::pycodestyle::rules::NoNewLineAtEndOfFile;
|
||||
use crate::rules::pycodestyle::rules::MissingNewlineAtEndOfFile;
|
||||
|
||||
use crate::source_code::Locator;
|
||||
|
||||
#[test]
|
||||
fn empty_file() {
|
||||
let fixes: Vec<Diagnostic> = vec![];
|
||||
let locator = Locator::new(r#""#);
|
||||
let (contents, fixed) = apply_fixes(fixes.iter(), &locator);
|
||||
assert_eq!(contents, "");
|
||||
assert_eq!(fixed.values().sum::<usize>(), 0);
|
||||
}
|
||||
|
||||
impl From<Fix> for Diagnostic {
|
||||
fn from(fix: Fix) -> Self {
|
||||
Diagnostic {
|
||||
fn create_diagnostics(fixes: impl IntoIterator<Item = Fix>) -> Vec<Diagnostic> {
|
||||
fixes
|
||||
.into_iter()
|
||||
.map(|fix| Diagnostic {
|
||||
// The choice of rule here is arbitrary.
|
||||
kind: NoNewLineAtEndOfFile.into(),
|
||||
kind: MissingNewlineAtEndOfFile.into(),
|
||||
location: fix.location,
|
||||
end_location: fix.end_location,
|
||||
fix: Some(fix),
|
||||
parent: None,
|
||||
}
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_file() {
|
||||
let locator = Locator::new(r#""#);
|
||||
let diagnostics = create_diagnostics([]);
|
||||
let (contents, fixed) = apply_fixes(diagnostics.iter(), &locator);
|
||||
assert_eq!(contents, "");
|
||||
assert_eq!(fixed.values().sum::<usize>(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn apply_one_replacement() {
|
||||
let fixes: Vec<Diagnostic> = vec![Fix {
|
||||
content: "Bar".to_string(),
|
||||
location: Location::new(1, 8),
|
||||
end_location: Location::new(1, 14),
|
||||
}
|
||||
.into()];
|
||||
let locator = Locator::new(
|
||||
r#"
|
||||
class A(object):
|
||||
@@ -139,7 +147,12 @@ class A(object):
|
||||
"#
|
||||
.trim(),
|
||||
);
|
||||
let (contents, fixed) = apply_fixes(fixes.iter(), &locator);
|
||||
let diagnostics = create_diagnostics([Fix {
|
||||
content: "Bar".to_string(),
|
||||
location: Location::new(1, 8),
|
||||
end_location: Location::new(1, 14),
|
||||
}]);
|
||||
let (contents, fixed) = apply_fixes(diagnostics.iter(), &locator);
|
||||
assert_eq!(
|
||||
contents,
|
||||
r#"
|
||||
@@ -153,12 +166,6 @@ class A(Bar):
|
||||
|
||||
#[test]
|
||||
fn apply_one_removal() {
|
||||
let fixes: Vec<Diagnostic> = vec![Fix {
|
||||
content: String::new(),
|
||||
location: Location::new(1, 7),
|
||||
end_location: Location::new(1, 15),
|
||||
}
|
||||
.into()];
|
||||
let locator = Locator::new(
|
||||
r#"
|
||||
class A(object):
|
||||
@@ -166,7 +173,12 @@ class A(object):
|
||||
"#
|
||||
.trim(),
|
||||
);
|
||||
let (contents, fixed) = apply_fixes(fixes.iter(), &locator);
|
||||
let diagnostics = create_diagnostics([Fix {
|
||||
content: String::new(),
|
||||
location: Location::new(1, 7),
|
||||
end_location: Location::new(1, 15),
|
||||
}]);
|
||||
let (contents, fixed) = apply_fixes(diagnostics.iter(), &locator);
|
||||
assert_eq!(
|
||||
contents,
|
||||
r#"
|
||||
@@ -180,33 +192,31 @@ class A:
|
||||
|
||||
#[test]
|
||||
fn apply_two_removals() {
|
||||
let fixes: Vec<Diagnostic> = vec![
|
||||
Fix {
|
||||
content: String::new(),
|
||||
location: Location::new(1, 7),
|
||||
end_location: Location::new(1, 16),
|
||||
}
|
||||
.into(),
|
||||
Fix {
|
||||
content: String::new(),
|
||||
location: Location::new(1, 16),
|
||||
end_location: Location::new(1, 23),
|
||||
}
|
||||
.into(),
|
||||
];
|
||||
let locator = Locator::new(
|
||||
r#"
|
||||
class A(object, object):
|
||||
class A(object, object, object):
|
||||
...
|
||||
"#
|
||||
.trim(),
|
||||
);
|
||||
let (contents, fixed) = apply_fixes(fixes.iter(), &locator);
|
||||
let diagnostics = create_diagnostics([
|
||||
Fix {
|
||||
content: String::new(),
|
||||
location: Location::new(1, 8),
|
||||
end_location: Location::new(1, 16),
|
||||
},
|
||||
Fix {
|
||||
content: String::new(),
|
||||
location: Location::new(1, 22),
|
||||
end_location: Location::new(1, 30),
|
||||
},
|
||||
]);
|
||||
let (contents, fixed) = apply_fixes(diagnostics.iter(), &locator);
|
||||
|
||||
assert_eq!(
|
||||
contents,
|
||||
r#"
|
||||
class A:
|
||||
class A(object):
|
||||
...
|
||||
"#
|
||||
.trim()
|
||||
@@ -216,20 +226,6 @@ class A:
|
||||
|
||||
#[test]
|
||||
fn ignore_overlapping_fixes() {
|
||||
let fixes: Vec<Diagnostic> = vec![
|
||||
Fix {
|
||||
content: String::new(),
|
||||
location: Location::new(1, 7),
|
||||
end_location: Location::new(1, 15),
|
||||
}
|
||||
.into(),
|
||||
Fix {
|
||||
content: "ignored".to_string(),
|
||||
location: Location::new(1, 9),
|
||||
end_location: Location::new(1, 11),
|
||||
}
|
||||
.into(),
|
||||
];
|
||||
let locator = Locator::new(
|
||||
r#"
|
||||
class A(object):
|
||||
@@ -237,7 +233,19 @@ class A(object):
|
||||
"#
|
||||
.trim(),
|
||||
);
|
||||
let (contents, fixed) = apply_fixes(fixes.iter(), &locator);
|
||||
let diagnostics = create_diagnostics([
|
||||
Fix {
|
||||
content: String::new(),
|
||||
location: Location::new(1, 7),
|
||||
end_location: Location::new(1, 15),
|
||||
},
|
||||
Fix {
|
||||
content: "ignored".to_string(),
|
||||
location: Location::new(1, 9),
|
||||
end_location: Location::new(1, 11),
|
||||
},
|
||||
]);
|
||||
let (contents, fixed) = apply_fixes(diagnostics.iter(), &locator);
|
||||
assert_eq!(
|
||||
contents,
|
||||
r#"
|
||||
|
||||
25
crates/ruff/src/checkers/ast/deferred.rs
Normal file
25
crates/ruff/src/checkers/ast/deferred.rs
Normal file
@@ -0,0 +1,25 @@
|
||||
use ruff_python_ast::scope::ScopeStack;
|
||||
use rustpython_parser::ast::{Expr, Stmt};
|
||||
|
||||
use ruff_python_ast::types::Range;
|
||||
use ruff_python_ast::types::RefEquality;
|
||||
use ruff_python_ast::visibility::{Visibility, VisibleScope};
|
||||
|
||||
use crate::checkers::ast::AnnotationContext;
|
||||
use crate::docstrings::definition::Definition;
|
||||
|
||||
type Context<'a> = (ScopeStack, Vec<RefEquality<'a, Stmt>>);
|
||||
|
||||
/// A collection of AST nodes that are deferred for later analysis.
|
||||
/// Used to, e.g., store functions, whose bodies shouldn't be analyzed until all
|
||||
/// module-level definitions have been analyzed.
|
||||
#[derive(Default)]
|
||||
pub struct Deferred<'a> {
|
||||
pub definitions: Vec<(Definition<'a>, Visibility, Context<'a>)>,
|
||||
pub string_type_definitions: Vec<(Range, &'a str, AnnotationContext, Context<'a>)>,
|
||||
pub type_definitions: Vec<(&'a Expr, AnnotationContext, Context<'a>)>,
|
||||
pub functions: Vec<(&'a Stmt, Context<'a>, VisibleScope)>,
|
||||
pub lambdas: Vec<(&'a Expr, Context<'a>)>,
|
||||
pub for_loops: Vec<(&'a Stmt, Context<'a>)>,
|
||||
pub assignments: Vec<Context<'a>>,
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user