Compare commits
211 Commits
schemastor
...
zb/debug-c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
17e77fe515 | ||
|
|
946b308197 | ||
|
|
d22ce5372d | ||
|
|
acab5f3cf2 | ||
|
|
06c9f625b6 | ||
|
|
bbb0a0c360 | ||
|
|
9361e22fe9 | ||
|
|
f484df5470 | ||
|
|
af88ffc57e | ||
|
|
b918647927 | ||
|
|
ef7778d794 | ||
|
|
bd443ebe91 | ||
|
|
ee6548d7dd | ||
|
|
b4a050c21d | ||
|
|
958702ded0 | ||
|
|
268d95e911 | ||
|
|
3def18fc21 | ||
|
|
c48ba690eb | ||
|
|
fd49fb935f | ||
|
|
fe54ef08aa | ||
|
|
b7ffd73edd | ||
|
|
8d9912a83a | ||
|
|
93258e8d5b | ||
|
|
b90027d037 | ||
|
|
060a25df09 | ||
|
|
f5d4676c13 | ||
|
|
df69dc9f8d | ||
|
|
cb6c37abd9 | ||
|
|
54de990621 | ||
|
|
b91b09b961 | ||
|
|
0bda1913d1 | ||
|
|
7e390d3772 | ||
|
|
0bf0aa28ac | ||
|
|
8088c5367a | ||
|
|
6fe8f8a272 | ||
|
|
bfae1f1412 | ||
|
|
b358cbf398 | ||
|
|
17c8817695 | ||
|
|
1dda669f9a | ||
|
|
3fbabfe126 | ||
|
|
20ab14e354 | ||
|
|
22d8a989d4 | ||
|
|
35082b28cd | ||
|
|
5aaf99b856 | ||
|
|
58bf6f5762 | ||
|
|
277cd80175 | ||
|
|
20a40771a5 | ||
|
|
4af3f43e5e | ||
|
|
0b1a36f8c8 | ||
|
|
64c2535e28 | ||
|
|
5510a6131e | ||
|
|
e5db72459e | ||
|
|
d66063bb33 | ||
|
|
506be68782 | ||
|
|
cb1d3df085 | ||
|
|
69dfe0a207 | ||
|
|
46a174a22e | ||
|
|
912c39ce2a | ||
|
|
b2638c62a5 | ||
|
|
eaa310429f | ||
|
|
019d9aebe9 | ||
|
|
f06c5dc896 | ||
|
|
c1dc4a60be | ||
|
|
70febb1862 | ||
|
|
4212b41796 | ||
|
|
bbad4b4c93 | ||
|
|
3ee1ec70cc | ||
|
|
ee5d95f751 | ||
|
|
d674e7946d | ||
|
|
20782ab02c | ||
|
|
073eddb1d9 | ||
|
|
e8da95d09c | ||
|
|
c324cb6202 | ||
|
|
774c77adae | ||
|
|
fd70cd789f | ||
|
|
08f3110f1e | ||
|
|
2314b9aaca | ||
|
|
cddc696896 | ||
|
|
6435e4e4aa | ||
|
|
ec7456bac0 | ||
|
|
b28556d739 | ||
|
|
4957d94beb | ||
|
|
5d554edace | ||
|
|
412688826c | ||
|
|
47d80f29a7 | ||
|
|
9dee1883ce | ||
|
|
f585e3e2dc | ||
|
|
578ddf1bb1 | ||
|
|
ed14fd9163 | ||
|
|
60eb11fa50 | ||
|
|
33caa2ab1c | ||
|
|
d9845a2628 | ||
|
|
1f14d9a9f7 | ||
|
|
0202a49297 | ||
|
|
d0591561c9 | ||
|
|
2f5859e79e | ||
|
|
16085339bc | ||
|
|
074812115f | ||
|
|
9b17724d77 | ||
|
|
0d4af9d3c6 | ||
|
|
1dbfab9a0c | ||
|
|
501cca8b72 | ||
|
|
626b0577cd | ||
|
|
017e829115 | ||
|
|
2590aa30ae | ||
|
|
852a8f4a4f | ||
|
|
8365d2e0fd | ||
|
|
5b726f70f4 | ||
|
|
727e389cac | ||
|
|
0cb438dd65 | ||
|
|
63a87dda63 | ||
|
|
359a68d18f | ||
|
|
948094e691 | ||
|
|
f1ed0f27c2 | ||
|
|
5ce6299e22 | ||
|
|
5373759f62 | ||
|
|
d9151b1948 | ||
|
|
b61ce7fa46 | ||
|
|
6fb6478887 | ||
|
|
bf729e7a77 | ||
|
|
6ca2aaa245 | ||
|
|
e306359411 | ||
|
|
aec80dc3ab | ||
|
|
10d937c1a1 | ||
|
|
653e51ae97 | ||
|
|
04f0625d23 | ||
|
|
29dc8b986b | ||
|
|
f750257ef4 | ||
|
|
0f2c9ab4d2 | ||
|
|
779a5a9c32 | ||
|
|
bba43029d4 | ||
|
|
1de5425f7d | ||
|
|
71573fd35c | ||
|
|
95e2f632e6 | ||
|
|
00a015ca24 | ||
|
|
94178a0320 | ||
|
|
7165f8f05d | ||
|
|
415e808046 | ||
|
|
9279114521 | ||
|
|
8b86e8004d | ||
|
|
a7fc785cc5 | ||
|
|
f460f9c5c0 | ||
|
|
2faac1e7a8 | ||
|
|
b7dbb9062c | ||
|
|
66794bc9fe | ||
|
|
dca430f4d2 | ||
|
|
841e6c889e | ||
|
|
bd99175fea | ||
|
|
4c86b155f2 | ||
|
|
e2109c1353 | ||
|
|
1fcccf82fc | ||
|
|
14e65afdc6 | ||
|
|
6d5d079a18 | ||
|
|
d1e88dc984 | ||
|
|
dda31b6996 | ||
|
|
b6a7787318 | ||
|
|
5fa961f670 | ||
|
|
2424188bb2 | ||
|
|
a59172528c | ||
|
|
cd29761b9c | ||
|
|
4ac78d5725 | ||
|
|
2083352ae3 | ||
|
|
0e2ece5217 | ||
|
|
a783b14e7d | ||
|
|
9d76e4e0b9 | ||
|
|
561277925f | ||
|
|
1074324c52 | ||
|
|
4099b9610f | ||
|
|
f7d249ae06 | ||
|
|
bf2cc3f520 | ||
|
|
23c819b4b3 | ||
|
|
16060670b8 | ||
|
|
534fc34f11 | ||
|
|
df9ade7fd9 | ||
|
|
345e1401cf | ||
|
|
a8e0d4ab4f | ||
|
|
6f23bdb78f | ||
|
|
d574fcd1ac | ||
|
|
3592f44ade | ||
|
|
8984072df2 | ||
|
|
6a6de53722 | ||
|
|
5ba852a878 | ||
|
|
c4fc2b8584 | ||
|
|
1c5f2288ba | ||
|
|
62f1830898 | ||
|
|
abca0a86ea | ||
|
|
213d315373 | ||
|
|
7fd95e15d9 | ||
|
|
02946e7b0c | ||
|
|
cbd9157bbf | ||
|
|
70f491d31e | ||
|
|
776eb8724f | ||
|
|
5f78580775 | ||
|
|
4d301f6dcc | ||
|
|
96b265ccec | ||
|
|
e0a0ddcf7d | ||
|
|
9724dfd939 | ||
|
|
d7144d6d8e | ||
|
|
39728a1198 | ||
|
|
8207d6df82 | ||
|
|
c8edac9d2b | ||
|
|
5a1a8bebca | ||
|
|
3e00ddce38 | ||
|
|
a7dbe9d670 | ||
|
|
036b6bc0bd | ||
|
|
d5606b7705 | ||
|
|
7968e190dd | ||
|
|
346a828db2 | ||
|
|
0ac124acef | ||
|
|
4ebd0bd31e | ||
|
|
565ddebb15 |
@@ -1,37 +1,3 @@
|
|||||||
[alias]
|
[alias]
|
||||||
dev = "run --package ruff_dev --bin ruff_dev"
|
dev = "run --package ruff_dev --bin ruff_dev"
|
||||||
benchmark = "bench -p ruff_benchmark --bench linter --bench formatter --"
|
benchmark = "bench -p ruff_benchmark --bench linter --bench formatter --"
|
||||||
|
|
||||||
[target.'cfg(all())']
|
|
||||||
rustflags = [
|
|
||||||
# CLIPPY LINT SETTINGS
|
|
||||||
# This is a workaround to configure lints for the entire workspace, pending the ability to configure this via TOML.
|
|
||||||
# See: `https://github.com/rust-lang/cargo/issues/5034`
|
|
||||||
# `https://github.com/EmbarkStudios/rust-ecosystem/issues/22#issuecomment-947011395`
|
|
||||||
"-Dunsafe_code",
|
|
||||||
"-Wclippy::pedantic",
|
|
||||||
# Allowed pedantic lints
|
|
||||||
"-Wclippy::char_lit_as_u8",
|
|
||||||
"-Aclippy::collapsible_else_if",
|
|
||||||
"-Aclippy::collapsible_if",
|
|
||||||
"-Aclippy::implicit_hasher",
|
|
||||||
"-Aclippy::match_same_arms",
|
|
||||||
"-Aclippy::missing_errors_doc",
|
|
||||||
"-Aclippy::missing_panics_doc",
|
|
||||||
"-Aclippy::module_name_repetitions",
|
|
||||||
"-Aclippy::must_use_candidate",
|
|
||||||
"-Aclippy::similar_names",
|
|
||||||
"-Aclippy::too_many_lines",
|
|
||||||
# Disallowed restriction lints
|
|
||||||
"-Wclippy::print_stdout",
|
|
||||||
"-Wclippy::print_stderr",
|
|
||||||
"-Wclippy::dbg_macro",
|
|
||||||
"-Wclippy::empty_drop",
|
|
||||||
"-Wclippy::empty_structs_with_brackets",
|
|
||||||
"-Wclippy::exit",
|
|
||||||
"-Wclippy::get_unwrap",
|
|
||||||
"-Wclippy::rc_buffer",
|
|
||||||
"-Wclippy::rc_mutex",
|
|
||||||
"-Wclippy::rest_pat_in_fully_bound_structs",
|
|
||||||
"-Wunreachable_pub"
|
|
||||||
]
|
|
||||||
|
|||||||
3
.gitattributes
vendored
3
.gitattributes
vendored
@@ -3,5 +3,8 @@
|
|||||||
crates/ruff_linter/resources/test/fixtures/isort/line_ending_crlf.py text eol=crlf
|
crates/ruff_linter/resources/test/fixtures/isort/line_ending_crlf.py text eol=crlf
|
||||||
crates/ruff_linter/resources/test/fixtures/pycodestyle/W605_1.py text eol=crlf
|
crates/ruff_linter/resources/test/fixtures/pycodestyle/W605_1.py text eol=crlf
|
||||||
|
|
||||||
|
crates/ruff_python_formatter/resources/test/fixtures/ruff/docstring_code_examples_crlf.py text eol=crlf
|
||||||
|
crates/ruff_python_formatter/tests/snapshots/format@docstring_code_examples_crlf.py.snap text eol=crlf
|
||||||
|
|
||||||
ruff.schema.json linguist-generated=true text=auto eol=lf
|
ruff.schema.json linguist-generated=true text=auto eol=lf
|
||||||
*.md.snap linguist-language=Markdown
|
*.md.snap linguist-language=Markdown
|
||||||
|
|||||||
41
.github/workflows/ci.yaml
vendored
41
.github/workflows/ci.yaml
vendored
@@ -23,8 +23,13 @@ jobs:
|
|||||||
name: "Determine changes"
|
name: "Determine changes"
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
outputs:
|
outputs:
|
||||||
|
# Flag that is raised when any code that affects linter is changed
|
||||||
linter: ${{ steps.changed.outputs.linter_any_changed }}
|
linter: ${{ steps.changed.outputs.linter_any_changed }}
|
||||||
|
# Flag that is raised when any code that affects formatter is changed
|
||||||
formatter: ${{ steps.changed.outputs.formatter_any_changed }}
|
formatter: ${{ steps.changed.outputs.formatter_any_changed }}
|
||||||
|
# Flag that is raised when any code is changed
|
||||||
|
# This is superset of the linter and formatter
|
||||||
|
code: ${{ steps.changed.outputs.code_any_changed }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
@@ -43,6 +48,7 @@ jobs:
|
|||||||
- "!crates/ruff_dev/**"
|
- "!crates/ruff_dev/**"
|
||||||
- "!crates/ruff_shrinking/**"
|
- "!crates/ruff_shrinking/**"
|
||||||
- scripts/*
|
- scripts/*
|
||||||
|
- python/**
|
||||||
- .github/workflows/ci.yaml
|
- .github/workflows/ci.yaml
|
||||||
|
|
||||||
formatter:
|
formatter:
|
||||||
@@ -58,8 +64,15 @@ jobs:
|
|||||||
- crates/ruff_python_parser/**
|
- crates/ruff_python_parser/**
|
||||||
- crates/ruff_dev/**
|
- crates/ruff_dev/**
|
||||||
- scripts/*
|
- scripts/*
|
||||||
|
- python/**
|
||||||
- .github/workflows/ci.yaml
|
- .github/workflows/ci.yaml
|
||||||
|
|
||||||
|
code:
|
||||||
|
- "**/*"
|
||||||
|
- "!**/*.md"
|
||||||
|
- "!docs/**"
|
||||||
|
- "!assets/**"
|
||||||
|
|
||||||
cargo-fmt:
|
cargo-fmt:
|
||||||
name: "cargo fmt"
|
name: "cargo fmt"
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -72,6 +85,8 @@ jobs:
|
|||||||
cargo-clippy:
|
cargo-clippy:
|
||||||
name: "cargo clippy"
|
name: "cargo clippy"
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
needs: determine_changes
|
||||||
|
if: ${{ needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main' }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: "Install Rust toolchain"
|
- name: "Install Rust toolchain"
|
||||||
@@ -86,6 +101,8 @@ jobs:
|
|||||||
|
|
||||||
cargo-test-linux:
|
cargo-test-linux:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
needs: determine_changes
|
||||||
|
if: ${{ needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main' }}
|
||||||
name: "cargo test (linux)"
|
name: "cargo test (linux)"
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@@ -110,6 +127,8 @@ jobs:
|
|||||||
|
|
||||||
cargo-test-windows:
|
cargo-test-windows:
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
|
needs: determine_changes
|
||||||
|
if: ${{ needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main' }}
|
||||||
name: "cargo test (windows)"
|
name: "cargo test (windows)"
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@@ -127,6 +146,8 @@ jobs:
|
|||||||
|
|
||||||
cargo-test-wasm:
|
cargo-test-wasm:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
needs: determine_changes
|
||||||
|
if: ${{ needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main' }}
|
||||||
name: "cargo test (wasm)"
|
name: "cargo test (wasm)"
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@@ -146,6 +167,8 @@ jobs:
|
|||||||
|
|
||||||
cargo-fuzz:
|
cargo-fuzz:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
needs: determine_changes
|
||||||
|
if: ${{ needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main' }}
|
||||||
name: "cargo fuzz"
|
name: "cargo fuzz"
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@@ -163,6 +186,8 @@ jobs:
|
|||||||
scripts:
|
scripts:
|
||||||
name: "test scripts"
|
name: "test scripts"
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
needs: determine_changes
|
||||||
|
if: ${{ needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main' }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: "Install Rust toolchain"
|
- name: "Install Rust toolchain"
|
||||||
@@ -186,8 +211,7 @@ jobs:
|
|||||||
# Only runs on pull requests, since that is the only we way we can find the base version for comparison.
|
# Only runs on pull requests, since that is the only we way we can find the base version for comparison.
|
||||||
# Ecosystem check needs linter and/or formatter changes.
|
# Ecosystem check needs linter and/or formatter changes.
|
||||||
if: github.event_name == 'pull_request' && ${{
|
if: github.event_name == 'pull_request' && ${{
|
||||||
needs.determine_changes.outputs.linter == 'true' ||
|
needs.determine_changes.outputs.code == 'true'
|
||||||
needs.determine_changes.outputs.formatter == 'true'
|
|
||||||
}}
|
}}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@@ -296,6 +320,8 @@ jobs:
|
|||||||
cargo-udeps:
|
cargo-udeps:
|
||||||
name: "cargo udeps"
|
name: "cargo udeps"
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
needs: determine_changes
|
||||||
|
if: ${{ needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main' }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: "Install nightly Rust toolchain"
|
- name: "Install nightly Rust toolchain"
|
||||||
@@ -392,7 +418,7 @@ jobs:
|
|||||||
run: mkdocs build --strict -f mkdocs.insiders.yml
|
run: mkdocs build --strict -f mkdocs.insiders.yml
|
||||||
- name: "Build docs"
|
- name: "Build docs"
|
||||||
if: ${{ env.MKDOCS_INSIDERS_SSH_KEY_EXISTS != 'true' }}
|
if: ${{ env.MKDOCS_INSIDERS_SSH_KEY_EXISTS != 'true' }}
|
||||||
run: mkdocs build --strict -f mkdocs.generated.yml
|
run: mkdocs build --strict -f mkdocs.public.yml
|
||||||
|
|
||||||
check-formatter-instability-and-black-similarity:
|
check-formatter-instability-and-black-similarity:
|
||||||
name: "formatter instabilities and black similarity"
|
name: "formatter instabilities and black similarity"
|
||||||
@@ -415,7 +441,10 @@ jobs:
|
|||||||
check-ruff-lsp:
|
check-ruff-lsp:
|
||||||
name: "test ruff-lsp"
|
name: "test ruff-lsp"
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: cargo-test-linux
|
needs:
|
||||||
|
- cargo-test-linux
|
||||||
|
- determine_changes
|
||||||
|
if: ${{ needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main' }}
|
||||||
steps:
|
steps:
|
||||||
- uses: extractions/setup-just@v1
|
- uses: extractions/setup-just@v1
|
||||||
env:
|
env:
|
||||||
@@ -453,6 +482,8 @@ jobs:
|
|||||||
|
|
||||||
benchmarks:
|
benchmarks:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
needs: determine_changes
|
||||||
|
if: ${{ needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main' }}
|
||||||
steps:
|
steps:
|
||||||
- name: "Checkout Branch"
|
- name: "Checkout Branch"
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
@@ -471,7 +502,7 @@ jobs:
|
|||||||
run: cargo codspeed build --features codspeed -p ruff_benchmark
|
run: cargo codspeed build --features codspeed -p ruff_benchmark
|
||||||
|
|
||||||
- name: "Run benchmarks"
|
- name: "Run benchmarks"
|
||||||
uses: CodSpeedHQ/action@v1
|
uses: CodSpeedHQ/action@v2
|
||||||
with:
|
with:
|
||||||
run: cargo codspeed run
|
run: cargo codspeed run
|
||||||
token: ${{ secrets.CODSPEED_TOKEN }}
|
token: ${{ secrets.CODSPEED_TOKEN }}
|
||||||
|
|||||||
2
.github/workflows/docs.yaml
vendored
2
.github/workflows/docs.yaml
vendored
@@ -44,7 +44,7 @@ jobs:
|
|||||||
run: mkdocs build --strict -f mkdocs.insiders.yml
|
run: mkdocs build --strict -f mkdocs.insiders.yml
|
||||||
- name: "Build docs"
|
- name: "Build docs"
|
||||||
if: ${{ env.MKDOCS_INSIDERS_SSH_KEY_EXISTS != 'true' }}
|
if: ${{ env.MKDOCS_INSIDERS_SSH_KEY_EXISTS != 'true' }}
|
||||||
run: mkdocs build --strict -f mkdocs.generated.yml
|
run: mkdocs build --strict -f mkdocs.public.yml
|
||||||
- name: "Deploy to Cloudflare Pages"
|
- name: "Deploy to Cloudflare Pages"
|
||||||
if: ${{ env.CF_API_TOKEN_EXISTS == 'true' }}
|
if: ${{ env.CF_API_TOKEN_EXISTS == 'true' }}
|
||||||
uses: cloudflare/wrangler-action@v3.3.2
|
uses: cloudflare/wrangler-action@v3.3.2
|
||||||
|
|||||||
72
.github/workflows/release.yaml
vendored
72
.github/workflows/release.yaml
vendored
@@ -86,7 +86,7 @@ jobs:
|
|||||||
path: dist
|
path: dist
|
||||||
- name: "Archive binary"
|
- name: "Archive binary"
|
||||||
run: |
|
run: |
|
||||||
ARCHIVE_FILE=ruff-x86_64-apple-darwin.tar.gz
|
ARCHIVE_FILE=ruff-${{ inputs.tag }}-x86_64-apple-darwin.tar.gz
|
||||||
tar czvf $ARCHIVE_FILE -C target/x86_64-apple-darwin/release ruff
|
tar czvf $ARCHIVE_FILE -C target/x86_64-apple-darwin/release ruff
|
||||||
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
|
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
|
||||||
- name: "Upload binary"
|
- name: "Upload binary"
|
||||||
@@ -125,7 +125,7 @@ jobs:
|
|||||||
path: dist
|
path: dist
|
||||||
- name: "Archive binary"
|
- name: "Archive binary"
|
||||||
run: |
|
run: |
|
||||||
ARCHIVE_FILE=ruff-aarch64-apple-darwin.tar.gz
|
ARCHIVE_FILE=ruff-${{ inputs.tag }}-aarch64-apple-darwin.tar.gz
|
||||||
tar czvf $ARCHIVE_FILE -C target/aarch64-apple-darwin/release ruff
|
tar czvf $ARCHIVE_FILE -C target/aarch64-apple-darwin/release ruff
|
||||||
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
|
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
|
||||||
- name: "Upload binary"
|
- name: "Upload binary"
|
||||||
@@ -177,7 +177,7 @@ jobs:
|
|||||||
- name: "Archive binary"
|
- name: "Archive binary"
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
ARCHIVE_FILE=ruff-${{ matrix.platform.target }}.zip
|
ARCHIVE_FILE=ruff-${{ inputs.tag }}-${{ matrix.platform.target }}.zip
|
||||||
7z a $ARCHIVE_FILE ./target/${{ matrix.platform.target }}/release/ruff.exe
|
7z a $ARCHIVE_FILE ./target/${{ matrix.platform.target }}/release/ruff.exe
|
||||||
sha256sum $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
|
sha256sum $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
|
||||||
- name: "Upload binary"
|
- name: "Upload binary"
|
||||||
@@ -224,7 +224,7 @@ jobs:
|
|||||||
path: dist
|
path: dist
|
||||||
- name: "Archive binary"
|
- name: "Archive binary"
|
||||||
run: |
|
run: |
|
||||||
ARCHIVE_FILE=ruff-${{ matrix.target }}.tar.gz
|
ARCHIVE_FILE=ruff-${{ inputs.tag }}-${{ matrix.target }}.tar.gz
|
||||||
tar czvf $ARCHIVE_FILE -C target/${{ matrix.target }}/release ruff
|
tar czvf $ARCHIVE_FILE -C target/${{ matrix.target }}/release ruff
|
||||||
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
|
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
|
||||||
- name: "Upload binary"
|
- name: "Upload binary"
|
||||||
@@ -291,7 +291,7 @@ jobs:
|
|||||||
path: dist
|
path: dist
|
||||||
- name: "Archive binary"
|
- name: "Archive binary"
|
||||||
run: |
|
run: |
|
||||||
ARCHIVE_FILE=ruff-${{ matrix.platform.target }}.tar.gz
|
ARCHIVE_FILE=ruff-${{ inputs.tag }}-${{ matrix.platform.target }}.tar.gz
|
||||||
tar czvf $ARCHIVE_FILE -C target/${{ matrix.platform.target }}/release ruff
|
tar czvf $ARCHIVE_FILE -C target/${{ matrix.platform.target }}/release ruff
|
||||||
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
|
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
|
||||||
- name: "Upload binary"
|
- name: "Upload binary"
|
||||||
@@ -343,7 +343,7 @@ jobs:
|
|||||||
path: dist
|
path: dist
|
||||||
- name: "Archive binary"
|
- name: "Archive binary"
|
||||||
run: |
|
run: |
|
||||||
ARCHIVE_FILE=ruff-${{ matrix.target }}.tar.gz
|
ARCHIVE_FILE=ruff-${{ inputs.tag }}-${{ matrix.target }}.tar.gz
|
||||||
tar czvf $ARCHIVE_FILE -C target/${{ matrix.target }}/release ruff
|
tar czvf $ARCHIVE_FILE -C target/${{ matrix.target }}/release ruff
|
||||||
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
|
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
|
||||||
- name: "Upload binary"
|
- name: "Upload binary"
|
||||||
@@ -399,7 +399,7 @@ jobs:
|
|||||||
path: dist
|
path: dist
|
||||||
- name: "Archive binary"
|
- name: "Archive binary"
|
||||||
run: |
|
run: |
|
||||||
ARCHIVE_FILE=ruff-${{ matrix.platform.target }}.tar.gz
|
ARCHIVE_FILE=ruff-${{ inputs.tag }}-${{ matrix.platform.target }}.tar.gz
|
||||||
tar czvf $ARCHIVE_FILE -C target/${{ matrix.platform.target }}/release ruff
|
tar czvf $ARCHIVE_FILE -C target/${{ matrix.platform.target }}/release ruff
|
||||||
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
|
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
|
||||||
- name: "Upload binary"
|
- name: "Upload binary"
|
||||||
@@ -516,6 +516,62 @@ jobs:
|
|||||||
files: binaries/*
|
files: binaries/*
|
||||||
tag_name: v${{ inputs.tag }}
|
tag_name: v${{ inputs.tag }}
|
||||||
|
|
||||||
|
docker-publish:
|
||||||
|
# This action doesn't need to wait on any other task, it's easy to re-tag if something failed and we're validating
|
||||||
|
# the tag here also
|
||||||
|
name: Push Docker image ghcr.io/astral-sh/ruff
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
environment:
|
||||||
|
name: release
|
||||||
|
permissions:
|
||||||
|
# For the docker push
|
||||||
|
packages: write
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
ref: ${{ inputs.sha }}
|
||||||
|
|
||||||
|
- uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.repository_owner }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Extract metadata (tags, labels) for Docker
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@v5
|
||||||
|
with:
|
||||||
|
images: ghcr.io/astral-sh/ruff
|
||||||
|
|
||||||
|
- name: Check tag consistency
|
||||||
|
# Unlike validate-tag we don't check if the commit is on the main branch, but it seems good enough since we can
|
||||||
|
# change docker tags
|
||||||
|
if: ${{ inputs.tag }}
|
||||||
|
run: |
|
||||||
|
version=$(grep "version = " pyproject.toml | sed -e 's/version = "\(.*\)"/\1/g')
|
||||||
|
if [ "${{ inputs.tag }}" != "${version}" ]; then
|
||||||
|
echo "The input tag does not match the version from pyproject.toml:" >&2
|
||||||
|
echo "${{ inputs.tag }}" >&2
|
||||||
|
echo "${version}" >&2
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
echo "Releasing ${version}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: "Build and push Docker image"
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
# Reuse the builder
|
||||||
|
cache-from: type=gha
|
||||||
|
cache-to: type=gha,mode=max
|
||||||
|
push: ${{ inputs.tag != '' }}
|
||||||
|
tags: ghcr.io/astral-sh/ruff:latest,ghcr.io/astral-sh/ruff:${{ inputs.tag || 'dry-run' }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
|
||||||
# After the release has been published, we update downstream repositories
|
# After the release has been published, we update downstream repositories
|
||||||
# This is separate because if this fails the release is still fine, we just need to do some manual workflow triggers
|
# This is separate because if this fails the release is still fine, we just need to do some manual workflow triggers
|
||||||
update-dependents:
|
update-dependents:
|
||||||
@@ -524,7 +580,7 @@ jobs:
|
|||||||
needs: publish-release
|
needs: publish-release
|
||||||
steps:
|
steps:
|
||||||
- name: "Update pre-commit mirror"
|
- name: "Update pre-commit mirror"
|
||||||
uses: actions/github-script@v6
|
uses: actions/github-script@v7
|
||||||
with:
|
with:
|
||||||
github-token: ${{ secrets.RUFF_PRE_COMMIT_PAT }}
|
github-token: ${{ secrets.RUFF_PRE_COMMIT_PAT }}
|
||||||
script: |
|
script: |
|
||||||
|
|||||||
167
CHANGELOG.md
167
CHANGELOG.md
@@ -1,5 +1,172 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 0.1.7
|
||||||
|
|
||||||
|
### Preview features
|
||||||
|
|
||||||
|
- Implement multiline dictionary and list hugging for preview style ([#8293](https://github.com/astral-sh/ruff/pull/8293))
|
||||||
|
- Implement the `fix_power_op_line_length` preview style ([#8947](https://github.com/astral-sh/ruff/pull/8947))
|
||||||
|
- Use Python version to determine typing rewrite safety ([#8919](https://github.com/astral-sh/ruff/pull/8919))
|
||||||
|
- \[`flake8-annotations`\] Enable auto-return-type involving `Optional` and `Union` annotations ([#8885](https://github.com/astral-sh/ruff/pull/8885))
|
||||||
|
- \[`flake8-bandit`\] Implement `django-raw-sql` (`S611`) ([#8651](https://github.com/astral-sh/ruff/pull/8651))
|
||||||
|
- \[`flake8-bandit`\] Implement `tarfile-unsafe-members` (`S202`) ([#8829](https://github.com/astral-sh/ruff/pull/8829))
|
||||||
|
- \[`flake8-pyi`\] Implement fix for `unnecessary-literal-union` (`PYI030`) ([#7934](https://github.com/astral-sh/ruff/pull/7934))
|
||||||
|
- \[`flake8-simplify`\] Extend `dict-get-with-none-default` (`SIM910`) to non-literals ([#8762](https://github.com/astral-sh/ruff/pull/8762))
|
||||||
|
- \[`pylint`\] - add `unnecessary-list-index-lookup` (`PLR1736`) + autofix ([#7999](https://github.com/astral-sh/ruff/pull/7999))
|
||||||
|
- \[`pylint`\] - implement R0202 and R0203 with autofixes ([#8335](https://github.com/astral-sh/ruff/pull/8335))
|
||||||
|
- \[`pylint`\] Implement `repeated-keyword` (`PLe1132`) ([#8706](https://github.com/astral-sh/ruff/pull/8706))
|
||||||
|
- \[`pylint`\] Implement `too-many-positional` (`PLR0917`) ([#8995](https://github.com/astral-sh/ruff/pull/8995))
|
||||||
|
- \[`pylint`\] Implement `unnecessary-dict-index-lookup` (`PLR1733`) ([#8036](https://github.com/astral-sh/ruff/pull/8036))
|
||||||
|
- \[`refurb`\] Implement `redundant-log-base` (`FURB163`) ([#8842](https://github.com/astral-sh/ruff/pull/8842))
|
||||||
|
|
||||||
|
### Rule changes
|
||||||
|
|
||||||
|
- \[`flake8-boolean-trap`\] Allow booleans in `@override` methods ([#8882](https://github.com/astral-sh/ruff/pull/8882))
|
||||||
|
- \[`flake8-bugbear`\] Avoid `B015`,`B018` for last expression in a cell ([#8815](https://github.com/astral-sh/ruff/pull/8815))
|
||||||
|
- \[`flake8-pie`\] Allow ellipses for enum values in stub files ([#8825](https://github.com/astral-sh/ruff/pull/8825))
|
||||||
|
- \[`flake8-pyi`\] Check PEP 695 type aliases for `snake-case-type-alias` and `t-suffixed-type-alias` ([#8966](https://github.com/astral-sh/ruff/pull/8966))
|
||||||
|
- \[`flake8-pyi`\] Check for kwarg and vararg `NoReturn` type annotations ([#8948](https://github.com/astral-sh/ruff/pull/8948))
|
||||||
|
- \[`flake8-simplify`\] Omit select context managers from `SIM117` ([#8801](https://github.com/astral-sh/ruff/pull/8801))
|
||||||
|
- \[`pep8-naming`\] Allow Django model loads in `non-lowercase-variable-in-function` (`N806`) ([#8917](https://github.com/astral-sh/ruff/pull/8917))
|
||||||
|
- \[`pycodestyle`\] Avoid `E703` for last expression in a cell ([#8821](https://github.com/astral-sh/ruff/pull/8821))
|
||||||
|
- \[`pycodestyle`\] Update `E402` to work at cell level for notebooks ([#8872](https://github.com/astral-sh/ruff/pull/8872))
|
||||||
|
- \[`pydocstyle`\] Avoid `D100` for Jupyter Notebooks ([#8816](https://github.com/astral-sh/ruff/pull/8816))
|
||||||
|
- \[`pylint`\] Implement fix for `unspecified-encoding` (`PLW1514`) ([#8928](https://github.com/astral-sh/ruff/pull/8928))
|
||||||
|
|
||||||
|
### Formatter
|
||||||
|
|
||||||
|
- Avoid unstable formatting in ellipsis-only body with trailing comment ([#8984](https://github.com/astral-sh/ruff/pull/8984))
|
||||||
|
- Inline trailing comments for type alias similar to assignments ([#8941](https://github.com/astral-sh/ruff/pull/8941))
|
||||||
|
- Insert trailing comma when function breaks with single argument ([#8921](https://github.com/astral-sh/ruff/pull/8921))
|
||||||
|
|
||||||
|
### CLI
|
||||||
|
|
||||||
|
- Update `ruff check` and `ruff format` to default to the current directory ([#8791](https://github.com/astral-sh/ruff/pull/8791))
|
||||||
|
- Stop at the first resolved parent configuration ([#8864](https://github.com/astral-sh/ruff/pull/8864))
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
- \[`pylint`\] Default `max-positional-args` to `max-args` ([#8998](https://github.com/astral-sh/ruff/pull/8998))
|
||||||
|
- \[`pylint`\] Add `allow-dunder-method-names` setting for `bad-dunder-method-name` (`PLW3201`) ([#8812](https://github.com/astral-sh/ruff/pull/8812))
|
||||||
|
- \[`isort`\] Add support for `from-first` setting ([#8663](https://github.com/astral-sh/ruff/pull/8663))
|
||||||
|
- \[`isort`\] Add support for `length-sort` settings ([#8841](https://github.com/astral-sh/ruff/pull/8841))
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
- Add support for `@functools.singledispatch` ([#8934](https://github.com/astral-sh/ruff/pull/8934))
|
||||||
|
- Avoid off-by-one error in stripping noqa following multi-byte char ([#8979](https://github.com/astral-sh/ruff/pull/8979))
|
||||||
|
- Avoid off-by-one error in with-item named expressions ([#8915](https://github.com/astral-sh/ruff/pull/8915))
|
||||||
|
- Avoid syntax error via invalid ur string prefix ([#8971](https://github.com/astral-sh/ruff/pull/8971))
|
||||||
|
- Avoid underflow in `get_model` matching ([#8965](https://github.com/astral-sh/ruff/pull/8965))
|
||||||
|
- Avoid unnecessary index diagnostics when value is modified ([#8970](https://github.com/astral-sh/ruff/pull/8970))
|
||||||
|
- Convert over-indentation rule to use number of characters ([#8983](https://github.com/astral-sh/ruff/pull/8983))
|
||||||
|
- Detect implicit returns in auto-return-types ([#8952](https://github.com/astral-sh/ruff/pull/8952))
|
||||||
|
- Fix start >= end error in over-indentation ([#8982](https://github.com/astral-sh/ruff/pull/8982))
|
||||||
|
- Ignore `@overload` and `@override` methods for too-many-arguments checks ([#8954](https://github.com/astral-sh/ruff/pull/8954))
|
||||||
|
- Lexer start of line is false only for `Mode::Expression` ([#8880](https://github.com/astral-sh/ruff/pull/8880))
|
||||||
|
- Mark `pydantic_settings.BaseSettings` as having default copy semantics ([#8793](https://github.com/astral-sh/ruff/pull/8793))
|
||||||
|
- Respect dictionary unpacking in `NamedTuple` assignments ([#8810](https://github.com/astral-sh/ruff/pull/8810))
|
||||||
|
- Respect local subclasses in `flake8-type-checking` ([#8768](https://github.com/astral-sh/ruff/pull/8768))
|
||||||
|
- Support type alias statements in simple statement positions ([#8916](https://github.com/astral-sh/ruff/pull/8916))
|
||||||
|
- \[`flake8-annotations`\] Avoid filtering out un-representable types in return annotation ([#8881](https://github.com/astral-sh/ruff/pull/8881))
|
||||||
|
- \[`flake8-pie`\] Retain extra ellipses in protocols and abstract methods ([#8769](https://github.com/astral-sh/ruff/pull/8769))
|
||||||
|
- \[`flake8-pyi`\] Respect local enum subclasses in `simple-defaults` (`PYI052`) ([#8767](https://github.com/astral-sh/ruff/pull/8767))
|
||||||
|
- \[`flake8-trio`\] Use correct range for `TRIO115` fix ([#8933](https://github.com/astral-sh/ruff/pull/8933))
|
||||||
|
- \[`flake8-trio`\] Use full arguments range for zero-sleep-call ([#8936](https://github.com/astral-sh/ruff/pull/8936))
|
||||||
|
- \[`isort`\] fix: mark `__main__` as first-party import ([#8805](https://github.com/astral-sh/ruff/pull/8805))
|
||||||
|
- \[`pep8-naming`\] Avoid `N806` errors for type alias statements ([#8785](https://github.com/astral-sh/ruff/pull/8785))
|
||||||
|
- \[`perflint`\] Avoid `PERF101` if there's an append in loop body ([#8809](https://github.com/astral-sh/ruff/pull/8809))
|
||||||
|
- \[`pycodestyle`\] Allow space-before-colon after end-of-slice ([#8838](https://github.com/astral-sh/ruff/pull/8838))
|
||||||
|
- \[`pydocstyle`\] Avoid non-character breaks in `over-indentation` (`D208`) ([#8866](https://github.com/astral-sh/ruff/pull/8866))
|
||||||
|
- \[`pydocstyle`\] Ignore underlines when determining docstring logical lines ([#8929](https://github.com/astral-sh/ruff/pull/8929))
|
||||||
|
- \[`pylint`\] Extend `self-assigning-variable` to multi-target assignments ([#8839](https://github.com/astral-sh/ruff/pull/8839))
|
||||||
|
- \[`tryceratops`\] Avoid repeated triggers in nested `tryceratops` diagnostics ([#8772](https://github.com/astral-sh/ruff/pull/8772))
|
||||||
|
|
||||||
|
### Documentation
|
||||||
|
|
||||||
|
- Add advice for fixing RUF008 when mutability is not desired ([#8853](https://github.com/astral-sh/ruff/pull/8853))
|
||||||
|
- Added the command to run ruff using pkgx to the installation.md ([#8955](https://github.com/astral-sh/ruff/pull/8955))
|
||||||
|
- Document fix safety for flake8-comprehensions and some pyupgrade rules ([#8918](https://github.com/astral-sh/ruff/pull/8918))
|
||||||
|
- Fix doc formatting for zero-sleep-call ([#8937](https://github.com/astral-sh/ruff/pull/8937))
|
||||||
|
- Remove duplicate imports from os-stat documentation ([#8930](https://github.com/astral-sh/ruff/pull/8930))
|
||||||
|
- Replace generated reference to MkDocs ([#8806](https://github.com/astral-sh/ruff/pull/8806))
|
||||||
|
- Update Arch Linux package URL in installation.md ([#8802](https://github.com/astral-sh/ruff/pull/8802))
|
||||||
|
- \[`flake8-pyi`\] Fix error in `t-suffixed-type-alias` (`PYI043`) example ([#8963](https://github.com/astral-sh/ruff/pull/8963))
|
||||||
|
- \[`flake8-pyi`\] Improve motivation for `custom-type-var-return-type` (`PYI019`) ([#8766](https://github.com/astral-sh/ruff/pull/8766))
|
||||||
|
|
||||||
|
## 0.1.6
|
||||||
|
|
||||||
|
### Preview features
|
||||||
|
|
||||||
|
- \[`flake8-boolean-trap`\] Extend `boolean-type-hint-positional-argument` (`FBT001`) to include booleans in unions ([#7501](https://github.com/astral-sh/ruff/pull/7501))
|
||||||
|
- \[`flake8-pie`\] Extend `reimplemented-list-builtin` (`PIE807`) to `dict` reimplementations ([#8608](https://github.com/astral-sh/ruff/pull/8608))
|
||||||
|
- \[`flake8-pie`\] Extend `unnecessary-pass` (`PIE790`) to include ellipses (`...`) ([#8641](https://github.com/astral-sh/ruff/pull/8641))
|
||||||
|
- \[`flake8-pie`\] Implement fix for `unnecessary-spread` (`PIE800`) ([#8668](https://github.com/astral-sh/ruff/pull/8668))
|
||||||
|
- \[`flake8-quotes`\] Implement `unnecessary-escaped-quote` (`Q004`) ([#8630](https://github.com/astral-sh/ruff/pull/8630))
|
||||||
|
- \[`pycodestyle`\] Implement fix for `multiple-spaces-after-keyword` (`E271`) and `multiple-spaces-before-keyword` (`E272`) ([#8622](https://github.com/astral-sh/ruff/pull/8622))
|
||||||
|
- \[`pycodestyle`\] Implement fix for `multiple-spaces-after-operator` (`E222`) and `multiple-spaces-before-operator` (`E221`) ([#8623](https://github.com/astral-sh/ruff/pull/8623))
|
||||||
|
- \[`pyflakes`\] Extend `is-literal` (`F632`) to include comparisons against mutable initializers ([#8607](https://github.com/astral-sh/ruff/pull/8607))
|
||||||
|
- \[`pylint`\] Implement `redefined-argument-from-local` (`PLR1704`) ([#8159](https://github.com/astral-sh/ruff/pull/8159))
|
||||||
|
- \[`pylint`\] Implement fix for `unnecessary-lambda` (`PLW0108`) ([#8621](https://github.com/astral-sh/ruff/pull/8621))
|
||||||
|
- \[`refurb`\] Implement `if-expr-min-max` (`FURB136`) ([#8664](https://github.com/astral-sh/ruff/pull/8664))
|
||||||
|
- \[`refurb`\] Implement `math-constant` (`FURB152`) ([#8727](https://github.com/astral-sh/ruff/pull/8727))
|
||||||
|
|
||||||
|
### Rule changes
|
||||||
|
|
||||||
|
- \[`flake8-annotations`\] Add autotyping-like return type inference for annotation rules ([#8643](https://github.com/astral-sh/ruff/pull/8643))
|
||||||
|
- \[`flake8-future-annotations`\] Implement fix for `future-required-type-annotation` (`FA102`) ([#8711](https://github.com/astral-sh/ruff/pull/8711))
|
||||||
|
- \[`flake8-implicit-namespace-package`\] Avoid missing namespace violations in scripts with shebangs ([#8710](https://github.com/astral-sh/ruff/pull/8710))
|
||||||
|
- \[`pydocstyle`\] Update `over-indentation` (`D208`) to preserve indentation offsets when fixing overindented lines ([#8699](https://github.com/astral-sh/ruff/pull/8699))
|
||||||
|
- \[`pyupgrade`\] Refine `timeout-error-alias` (`UP041`) to remove false positives ([#8587](https://github.com/astral-sh/ruff/pull/8587))
|
||||||
|
|
||||||
|
### Formatter
|
||||||
|
|
||||||
|
- Fix instability in `await` formatting with fluent style ([#8676](https://github.com/astral-sh/ruff/pull/8676))
|
||||||
|
- Compare formatted and unformatted ASTs during formatter tests ([#8624](https://github.com/astral-sh/ruff/pull/8624))
|
||||||
|
- Preserve trailing semicolon for Notebooks ([#8590](https://github.com/astral-sh/ruff/pull/8590))
|
||||||
|
|
||||||
|
### CLI
|
||||||
|
|
||||||
|
- Improve debug printing for resolving origin of config settings ([#8729](https://github.com/astral-sh/ruff/pull/8729))
|
||||||
|
- Write unchanged, excluded files to stdout when read via stdin ([#8596](https://github.com/astral-sh/ruff/pull/8596))
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
- \[`isort`\] Support disabling sections with `no-sections = true` ([#8657](https://github.com/astral-sh/ruff/pull/8657))
|
||||||
|
- \[`pep8-naming`\] Support local and dynamic class- and static-method decorators ([#8592](https://github.com/astral-sh/ruff/pull/8592))
|
||||||
|
- \[`pydocstyle`\] Allow overriding pydocstyle convention rules ([#8586](https://github.com/astral-sh/ruff/pull/8586))
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
- Avoid syntax error via importing `trio.lowlevel` ([#8730](https://github.com/astral-sh/ruff/pull/8730))
|
||||||
|
- Omit unrolled augmented assignments in `PIE794` ([#8634](https://github.com/astral-sh/ruff/pull/8634))
|
||||||
|
- Slice source code instead of generating it for `EM` fixes ([#7746](https://github.com/astral-sh/ruff/pull/7746))
|
||||||
|
- Allow whitespace around colon in slices for `whitespace-before-punctuation` (`E203`) ([#8654](https://github.com/astral-sh/ruff/pull/8654))
|
||||||
|
- Use function range for `no-self-use` ([#8637](https://github.com/astral-sh/ruff/pull/8637))
|
||||||
|
- F-strings doesn't contain bytes literal for `PLW0129` ([#8675](https://github.com/astral-sh/ruff/pull/8675))
|
||||||
|
- Improve detection of `TYPE_CHECKING` blocks imported from `typing_extensions` or `_typeshed` ([#8429](https://github.com/astral-sh/ruff/pull/8429))
|
||||||
|
- Treat display as a builtin in IPython ([#8707](https://github.com/astral-sh/ruff/pull/8707))
|
||||||
|
- Avoid `FURB113` autofix if comments are present ([#8494](https://github.com/astral-sh/ruff/pull/8494))
|
||||||
|
- Consider the new f-string tokens for `flake8-commas` ([#8582](https://github.com/astral-sh/ruff/pull/8582))
|
||||||
|
- Remove erroneous bad-dunder-name reference ([#8742](https://github.com/astral-sh/ruff/pull/8742))
|
||||||
|
- Avoid recommending Self usages in metaclasses ([#8639](https://github.com/astral-sh/ruff/pull/8639))
|
||||||
|
- Detect runtime-evaluated base classes defined in the current file ([#8572](https://github.com/astral-sh/ruff/pull/8572))
|
||||||
|
- Avoid inserting trailing commas within f-strings ([#8574](https://github.com/astral-sh/ruff/pull/8574))
|
||||||
|
- Remove incorrect deprecation label for stdout and stderr ([#8743](https://github.com/astral-sh/ruff/pull/8743))
|
||||||
|
- Fix unnecessary parentheses in UP007 fix ([#8610](https://github.com/astral-sh/ruff/pull/8610))
|
||||||
|
- Remove repeated and erroneous scoped settings headers in docs ([#8670](https://github.com/astral-sh/ruff/pull/8670))
|
||||||
|
- Trim trailing empty strings when converting to f-strings ([#8712](https://github.com/astral-sh/ruff/pull/8712))
|
||||||
|
- Fix ordering for `force-sort-within-sections` ([#8665](https://github.com/astral-sh/ruff/pull/8665))
|
||||||
|
- Run unicode prefix rule over tokens ([#8709](https://github.com/astral-sh/ruff/pull/8709))
|
||||||
|
- Update UP032 to unescape curly braces in literal parts of converted strings ([#8697](https://github.com/astral-sh/ruff/pull/8697))
|
||||||
|
- List all ipython builtins ([#8719](https://github.com/astral-sh/ruff/pull/8719))
|
||||||
|
|
||||||
|
### Documentation
|
||||||
|
|
||||||
|
- Document conventions in the FAQ ([#8638](https://github.com/astral-sh/ruff/pull/8638))
|
||||||
|
- Redirect from rule codes to rule pages in docs ([#8636](https://github.com/astral-sh/ruff/pull/8636))
|
||||||
|
- Fix permalink to convention setting ([#8575](https://github.com/astral-sh/ruff/pull/8575))
|
||||||
|
|
||||||
## 0.1.5
|
## 0.1.5
|
||||||
|
|
||||||
### Preview features
|
### Preview features
|
||||||
|
|||||||
@@ -295,7 +295,7 @@ To preview any changes to the documentation locally:
|
|||||||
|
|
||||||
```shell
|
```shell
|
||||||
# For contributors.
|
# For contributors.
|
||||||
mkdocs serve -f mkdocs.generated.yml
|
mkdocs serve -f mkdocs.public.yml
|
||||||
|
|
||||||
# For members of the Astral org, which has access to MkDocs Insiders via sponsorship.
|
# For members of the Astral org, which has access to MkDocs Insiders via sponsorship.
|
||||||
mkdocs serve -f mkdocs.insiders.yml
|
mkdocs serve -f mkdocs.insiders.yml
|
||||||
|
|||||||
206
Cargo.lock
generated
206
Cargo.lock
generated
@@ -64,9 +64,9 @@ checksum = "c7021ce4924a3f25f802b2cccd1af585e39ea1a363a1aa2e72afe54b67a3a7a7"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "annotate-snippets"
|
name = "annotate-snippets"
|
||||||
version = "0.9.1"
|
version = "0.9.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c3b9d411ecbaf79885c6df4d75fff75858d5995ff25385657a28af47e82f9c36"
|
checksum = "ccaf7e9dfbb6ab22c82e473cd1a8a7bd313c19a5b7e40970f3d89ef5a5c9e81e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-width",
|
"unicode-width",
|
||||||
"yansi-term",
|
"yansi-term",
|
||||||
@@ -278,9 +278,7 @@ checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"android-tzdata",
|
"android-tzdata",
|
||||||
"iana-time-zone",
|
"iana-time-zone",
|
||||||
"js-sys",
|
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"wasm-bindgen",
|
|
||||||
"windows-targets 0.48.5",
|
"windows-targets 0.48.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -407,9 +405,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "codspeed"
|
name = "codspeed"
|
||||||
version = "2.3.1"
|
version = "2.3.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "918b13a0f1a32460ab3bd5debd56b5a27a7071fa5ff5dfeb3a5cf291a85b174b"
|
checksum = "0eb4ab4dcb6554eb4f590fb16f99d3b102ab76f5f56554c9a5340518b32c499b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"colored",
|
"colored",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -418,9 +416,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "codspeed-criterion-compat"
|
name = "codspeed-criterion-compat"
|
||||||
version = "2.3.1"
|
version = "2.3.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c683c7fef2b873fbbdf4062782914c652309951244bf0bd362fe608b7d6f901c"
|
checksum = "cc07a3d3f7e0c8961d0ffdee149d39b231bafdcdc3d978dc5ad790c615f55f3f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"codspeed",
|
"codspeed",
|
||||||
"colored",
|
"colored",
|
||||||
@@ -446,9 +444,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "configparser"
|
name = "configparser"
|
||||||
version = "3.0.2"
|
version = "3.0.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5458d9d1a587efaf5091602c59d299696a3877a439c8f6d461a2d3cce11df87a"
|
checksum = "e0e56e414a2a52ab2a104f85cd40933c2fbc278b83637facf646ecf451b49237"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "console"
|
name = "console"
|
||||||
@@ -810,7 +808,7 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "flake8-to-ruff"
|
name = "flake8-to-ruff"
|
||||||
version = "0.1.5"
|
version = "0.1.7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"clap",
|
"clap",
|
||||||
@@ -829,7 +827,7 @@ dependencies = [
|
|||||||
"serde_json",
|
"serde_json",
|
||||||
"strum",
|
"strum",
|
||||||
"strum_macros",
|
"strum_macros",
|
||||||
"toml",
|
"toml 0.7.8",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -850,18 +848,21 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "form_urlencoded"
|
name = "form_urlencoded"
|
||||||
version = "1.2.0"
|
version = "1.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652"
|
checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fs-err"
|
name = "fs-err"
|
||||||
version = "2.9.0"
|
version = "2.11.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0845fa252299212f0389d64ba26f34fa32cfe41588355f21ed507c59a0f64541"
|
checksum = "88a41f105fe1d5b6b34b2055e3dc59bb79b46b48b2040b9e6c7b4b5de097aa41"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fsevent-sys"
|
name = "fsevent-sys"
|
||||||
@@ -902,15 +903,15 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "globset"
|
name = "globset"
|
||||||
version = "0.4.13"
|
version = "0.4.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "759c97c1e17c55525b57192c06a267cda0ac5210b222d6b82189a2338fa1c13d"
|
checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"bstr",
|
"bstr",
|
||||||
"fnv",
|
|
||||||
"log",
|
"log",
|
||||||
"regex",
|
"regex-automata 0.4.3",
|
||||||
|
"regex-syntax 0.8.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -927,9 +928,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.14.0"
|
version = "0.14.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a"
|
checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "heck"
|
name = "heck"
|
||||||
@@ -986,9 +987,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "idna"
|
name = "idna"
|
||||||
version = "0.4.0"
|
version = "0.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c"
|
checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-bidi",
|
"unicode-bidi",
|
||||||
"unicode-normalization",
|
"unicode-normalization",
|
||||||
@@ -1033,12 +1034,12 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "2.0.0"
|
version = "2.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d"
|
checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"equivalent",
|
"equivalent",
|
||||||
"hashbrown 0.14.0",
|
"hashbrown 0.14.2",
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1169,9 +1170,9 @@ checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "js-sys"
|
name = "js-sys"
|
||||||
version = "0.3.64"
|
version = "0.3.66"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a"
|
checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
@@ -1621,9 +1622,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "percent-encoding"
|
name = "percent-encoding"
|
||||||
version = "2.3.0"
|
version = "2.3.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
|
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "petgraph"
|
name = "petgraph"
|
||||||
@@ -1792,45 +1793,46 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.69"
|
version = "1.0.70"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da"
|
checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pyproject-toml"
|
name = "pyproject-toml"
|
||||||
version = "0.8.0"
|
version = "0.8.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0774c13ff0b8b7ebb4791c050c497aefcfe3f6a222c0829c7017161ed38391ff"
|
checksum = "46d4a5e69187f23a29f8aa0ea57491d104ba541bc55f76552c2a74962aa20e04"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"pep440_rs",
|
"pep440_rs",
|
||||||
"pep508_rs",
|
"pep508_rs",
|
||||||
"serde",
|
"serde",
|
||||||
"toml",
|
"toml 0.8.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quick-junit"
|
name = "quick-junit"
|
||||||
version = "0.3.3"
|
version = "0.3.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6bf780b59d590c25f8c59b44c124166a2a93587868b619fb8f5b47fb15e9ed6d"
|
checksum = "1b9599bffc2cd7511355996e0cfd979266b2cfa3f3ff5247d07a3a6e1ded6158"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"nextest-workspace-hack",
|
"nextest-workspace-hack",
|
||||||
"quick-xml",
|
"quick-xml",
|
||||||
|
"strip-ansi-escapes",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"uuid",
|
"uuid",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quick-xml"
|
name = "quick-xml"
|
||||||
version = "0.29.0"
|
version = "0.31.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "81b9228215d82c7b61490fec1de287136b5de6f5700f6e58ea9ad61a7964ca51"
|
checksum = "1004a344b30a54e2ee58d66a71b32d2db2feb0a31f9a2d302bf0536f15de2a33"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
@@ -2060,9 +2062,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ruff_cli"
|
name = "ruff_cli"
|
||||||
version = "0.1.5"
|
version = "0.1.7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"annotate-snippets 0.9.1",
|
"annotate-snippets 0.9.2",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"argfile",
|
"argfile",
|
||||||
"assert_cmd",
|
"assert_cmd",
|
||||||
@@ -2152,7 +2154,7 @@ dependencies = [
|
|||||||
"strum",
|
"strum",
|
||||||
"strum_macros",
|
"strum_macros",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"toml",
|
"toml 0.7.8",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-indicatif",
|
"tracing-indicatif",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
@@ -2196,10 +2198,10 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ruff_linter"
|
name = "ruff_linter"
|
||||||
version = "0.1.5"
|
version = "0.1.7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"annotate-snippets 0.9.1",
|
"annotate-snippets 0.9.2",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bitflags 2.4.1",
|
"bitflags 2.4.1",
|
||||||
"chrono",
|
"chrono",
|
||||||
@@ -2252,7 +2254,7 @@ dependencies = [
|
|||||||
"tempfile",
|
"tempfile",
|
||||||
"test-case",
|
"test-case",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"toml",
|
"toml 0.7.8",
|
||||||
"typed-arena",
|
"typed-arena",
|
||||||
"unicode-width",
|
"unicode-width",
|
||||||
"unicode_names2",
|
"unicode_names2",
|
||||||
@@ -2332,6 +2334,7 @@ dependencies = [
|
|||||||
"itertools 0.11.0",
|
"itertools 0.11.0",
|
||||||
"memchr",
|
"memchr",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
"regex",
|
||||||
"ruff_cache",
|
"ruff_cache",
|
||||||
"ruff_formatter",
|
"ruff_formatter",
|
||||||
"ruff_macros",
|
"ruff_macros",
|
||||||
@@ -2447,7 +2450,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ruff_shrinking"
|
name = "ruff_shrinking"
|
||||||
version = "0.1.5"
|
version = "0.1.7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"clap",
|
"clap",
|
||||||
@@ -2538,7 +2541,7 @@ dependencies = [
|
|||||||
"shellexpand",
|
"shellexpand",
|
||||||
"strum",
|
"strum",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"toml",
|
"toml 0.7.8",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2615,9 +2618,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "schemars"
|
name = "schemars"
|
||||||
version = "0.8.15"
|
version = "0.8.16"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1f7b0ce13155372a76ee2e1c5ffba1fe61ede73fbea5630d61eee6fac4929c0c"
|
checksum = "45a28f4c49489add4ce10783f7911893516f15afe45d015608d41faca6bc4d29"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dyn-clone",
|
"dyn-clone",
|
||||||
"schemars_derive",
|
"schemars_derive",
|
||||||
@@ -2627,9 +2630,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "schemars_derive"
|
name = "schemars_derive"
|
||||||
version = "0.8.15"
|
version = "0.8.16"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e85e2a16b12bdb763244c69ab79363d71db2b4b918a2def53f80b02e0574b13c"
|
checksum = "c767fd6fa65d9ccf9cf026122c1b555f2ef9a4f0cea69da4d7dbc3e258d30967"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -2802,9 +2805,9 @@ checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smallvec"
|
name = "smallvec"
|
||||||
version = "1.11.1"
|
version = "1.11.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a"
|
checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "spin"
|
name = "spin"
|
||||||
@@ -2831,6 +2834,15 @@ dependencies = [
|
|||||||
"precomputed-hash",
|
"precomputed-hash",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strip-ansi-escapes"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "55ff8ef943b384c414f54aefa961dd2bd853add74ec75e7ac74cf91dba62bcfa"
|
||||||
|
dependencies = [
|
||||||
|
"vte",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strsim"
|
name = "strsim"
|
||||||
version = "0.10.0"
|
version = "0.10.0"
|
||||||
@@ -3086,7 +3098,19 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
"serde_spanned",
|
"serde_spanned",
|
||||||
"toml_datetime",
|
"toml_datetime",
|
||||||
"toml_edit",
|
"toml_edit 0.19.15",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml"
|
||||||
|
version = "0.8.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
"serde_spanned",
|
||||||
|
"toml_datetime",
|
||||||
|
"toml_edit 0.20.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -3111,6 +3135,19 @@ dependencies = [
|
|||||||
"winnow",
|
"winnow",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_edit"
|
||||||
|
version = "0.20.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338"
|
||||||
|
dependencies = [
|
||||||
|
"indexmap",
|
||||||
|
"serde",
|
||||||
|
"serde_spanned",
|
||||||
|
"toml_datetime",
|
||||||
|
"winnow",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing"
|
name = "tracing"
|
||||||
version = "0.1.40"
|
version = "0.1.40"
|
||||||
@@ -3158,20 +3195,20 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing-log"
|
name = "tracing-log"
|
||||||
version = "0.1.3"
|
version = "0.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922"
|
checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lazy_static",
|
|
||||||
"log",
|
"log",
|
||||||
|
"once_cell",
|
||||||
"tracing-core",
|
"tracing-core",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing-subscriber"
|
name = "tracing-subscriber"
|
||||||
version = "0.3.17"
|
version = "0.3.18"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77"
|
checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"matchers",
|
"matchers",
|
||||||
"nu-ansi-term",
|
"nu-ansi-term",
|
||||||
@@ -3297,9 +3334,9 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ureq"
|
name = "ureq"
|
||||||
version = "2.8.0"
|
version = "2.9.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f5ccd538d4a604753ebc2f17cd9946e89b77bf87f6a8e2309667c6f2e87855e3"
|
checksum = "f8cdd25c339e200129fe4de81451814e5228c9b771d57378817d6117cc2b3f97"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"flate2",
|
"flate2",
|
||||||
@@ -3313,9 +3350,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "url"
|
name = "url"
|
||||||
version = "2.4.1"
|
version = "2.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5"
|
checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"form_urlencoded",
|
"form_urlencoded",
|
||||||
"idna",
|
"idna",
|
||||||
@@ -3331,9 +3368,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uuid"
|
name = "uuid"
|
||||||
version = "1.5.0"
|
version = "1.6.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "88ad59a7560b41a70d191093a945f0b87bc1deeda46fb237479708a1d6b6cdfc"
|
checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom",
|
"getrandom",
|
||||||
"rand",
|
"rand",
|
||||||
@@ -3343,9 +3380,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uuid-macro-internal"
|
name = "uuid-macro-internal"
|
||||||
version = "1.5.0"
|
version = "1.6.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3d8c6bba9b149ee82950daefc9623b32bb1dacbfb1890e352f6b887bd582adaf"
|
checksum = "f49e7f3f3db8040a100710a11932239fd30697115e2ba4107080d8252939845e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -3424,9 +3461,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen"
|
name = "wasm-bindgen"
|
||||||
version = "0.2.87"
|
version = "0.2.89"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342"
|
checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"wasm-bindgen-macro",
|
"wasm-bindgen-macro",
|
||||||
@@ -3434,9 +3471,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-backend"
|
name = "wasm-bindgen-backend"
|
||||||
version = "0.2.87"
|
version = "0.2.89"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd"
|
checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
"log",
|
"log",
|
||||||
@@ -3449,9 +3486,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-futures"
|
name = "wasm-bindgen-futures"
|
||||||
version = "0.4.37"
|
version = "0.4.38"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03"
|
checksum = "9afec9963e3d0994cac82455b2b3502b81a7f40f9a0d32181f7528d9f4b43e02"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
@@ -3461,9 +3498,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-macro"
|
name = "wasm-bindgen-macro"
|
||||||
version = "0.2.87"
|
version = "0.2.89"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d"
|
checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"quote",
|
"quote",
|
||||||
"wasm-bindgen-macro-support",
|
"wasm-bindgen-macro-support",
|
||||||
@@ -3471,9 +3508,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-macro-support"
|
name = "wasm-bindgen-macro-support"
|
||||||
version = "0.2.87"
|
version = "0.2.89"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
|
checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -3484,15 +3521,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-shared"
|
name = "wasm-bindgen-shared"
|
||||||
version = "0.2.87"
|
version = "0.2.89"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1"
|
checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-test"
|
name = "wasm-bindgen-test"
|
||||||
version = "0.3.37"
|
version = "0.3.38"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6e6e302a7ea94f83a6d09e78e7dc7d9ca7b186bc2829c24a22d0753efd680671"
|
checksum = "c6433b7c56db97397842c46b67e11873eda263170afeb3a2dc74a7cb370fee0d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"console_error_panic_hook",
|
"console_error_panic_hook",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
@@ -3504,12 +3541,13 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-test-macro"
|
name = "wasm-bindgen-test-macro"
|
||||||
version = "0.3.37"
|
version = "0.3.38"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ecb993dd8c836930ed130e020e77d9b2e65dd0fbab1b67c790b0f5d80b11a575"
|
checksum = "493fcbab756bb764fa37e6bee8cec2dd709eb4273d06d0c282a5e74275ded735"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
"syn 2.0.39",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
46
Cargo.toml
46
Cargo.toml
@@ -9,7 +9,7 @@ homepage = "https://docs.astral.sh/ruff"
|
|||||||
documentation = "https://docs.astral.sh/ruff"
|
documentation = "https://docs.astral.sh/ruff"
|
||||||
repository = "https://github.com/astral-sh/ruff"
|
repository = "https://github.com/astral-sh/ruff"
|
||||||
authors = ["Charlie Marsh <charlie.r.marsh@gmail.com>"]
|
authors = ["Charlie Marsh <charlie.r.marsh@gmail.com>"]
|
||||||
license = "MIT"
|
license = "MIT2"
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
anyhow = { version = "1.0.69" }
|
anyhow = { version = "1.0.69" }
|
||||||
@@ -19,7 +19,7 @@ clap = { version = "4.4.7", features = ["derive"] }
|
|||||||
colored = { version = "2.0.0" }
|
colored = { version = "2.0.0" }
|
||||||
filetime = { version = "0.2.20" }
|
filetime = { version = "0.2.20" }
|
||||||
glob = { version = "0.3.1" }
|
glob = { version = "0.3.1" }
|
||||||
globset = { version = "0.4.10" }
|
globset = { version = "0.4.14" }
|
||||||
ignore = { version = "0.4.20" }
|
ignore = { version = "0.4.20" }
|
||||||
insta = { version = "1.34.0", feature = ["filters", "glob"] }
|
insta = { version = "1.34.0", feature = ["filters", "glob"] }
|
||||||
is-macro = { version = "0.3.0" }
|
is-macro = { version = "0.3.0" }
|
||||||
@@ -29,16 +29,16 @@ log = { version = "0.4.17" }
|
|||||||
memchr = { version = "2.6.4" }
|
memchr = { version = "2.6.4" }
|
||||||
once_cell = { version = "1.17.1" }
|
once_cell = { version = "1.17.1" }
|
||||||
path-absolutize = { version = "3.1.1" }
|
path-absolutize = { version = "3.1.1" }
|
||||||
proc-macro2 = { version = "1.0.69" }
|
proc-macro2 = { version = "1.0.70" }
|
||||||
quote = { version = "1.0.23" }
|
quote = { version = "1.0.23" }
|
||||||
regex = { version = "1.10.2" }
|
regex = { version = "1.10.2" }
|
||||||
rustc-hash = { version = "1.1.0" }
|
rustc-hash = { version = "1.1.0" }
|
||||||
schemars = { version = "0.8.15" }
|
schemars = { version = "0.8.16" }
|
||||||
serde = { version = "1.0.190", features = ["derive"] }
|
serde = { version = "1.0.190", features = ["derive"] }
|
||||||
serde_json = { version = "1.0.108" }
|
serde_json = { version = "1.0.108" }
|
||||||
shellexpand = { version = "3.0.0" }
|
shellexpand = { version = "3.0.0" }
|
||||||
similar = { version = "2.3.0", features = ["inline"] }
|
similar = { version = "2.3.0", features = ["inline"] }
|
||||||
smallvec = { version = "1.11.1" }
|
smallvec = { version = "1.11.2" }
|
||||||
static_assertions = "1.1.0"
|
static_assertions = "1.1.0"
|
||||||
strum = { version = "0.25.0", features = ["strum_macros"] }
|
strum = { version = "0.25.0", features = ["strum_macros"] }
|
||||||
strum_macros = { version = "0.25.3" }
|
strum_macros = { version = "0.25.3" }
|
||||||
@@ -48,13 +48,45 @@ thiserror = { version = "1.0.50" }
|
|||||||
toml = { version = "0.7.8" }
|
toml = { version = "0.7.8" }
|
||||||
tracing = { version = "0.1.40" }
|
tracing = { version = "0.1.40" }
|
||||||
tracing-indicatif = { version = "0.3.4" }
|
tracing-indicatif = { version = "0.3.4" }
|
||||||
tracing-subscriber = { version = "0.3.17", features = ["env-filter"] }
|
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
|
||||||
unicode-ident = { version = "1.0.12" }
|
unicode-ident = { version = "1.0.12" }
|
||||||
unicode_names2 = { version = "1.2.0" }
|
unicode_names2 = { version = "1.2.0" }
|
||||||
unicode-width = { version = "0.1.11" }
|
unicode-width = { version = "0.1.11" }
|
||||||
uuid = { version = "1.5.0", features = ["v4", "fast-rng", "macro-diagnostics", "js"] }
|
uuid = { version = "1.6.1", features = ["v4", "fast-rng", "macro-diagnostics", "js"] }
|
||||||
wsl = { version = "0.1.0" }
|
wsl = { version = "0.1.0" }
|
||||||
|
|
||||||
|
[workspace.lints.rust]
|
||||||
|
unsafe_code = "warn"
|
||||||
|
unreachable_pub = "warn"
|
||||||
|
|
||||||
|
[workspace.lints.clippy]
|
||||||
|
pedantic = { level = "warn", priority = -2 }
|
||||||
|
# Allowed pedantic lints
|
||||||
|
char_lit_as_u8 = "allow"
|
||||||
|
collapsible_else_if = "allow"
|
||||||
|
collapsible_if = "allow"
|
||||||
|
implicit_hasher = "allow"
|
||||||
|
match_same_arms = "allow"
|
||||||
|
missing_errors_doc = "allow"
|
||||||
|
missing_panics_doc = "allow"
|
||||||
|
module_name_repetitions = "allow"
|
||||||
|
must_use_candidate = "allow"
|
||||||
|
similar_names = "allow"
|
||||||
|
too_many_lines = "allow"
|
||||||
|
# To allow `#[allow(clippy::all)]` in `crates/ruff_python_parser/src/python.rs`.
|
||||||
|
needless_raw_string_hashes = "allow"
|
||||||
|
# Disallowed restriction lints
|
||||||
|
print_stdout = "warn"
|
||||||
|
print_stderr = "warn"
|
||||||
|
dbg_macro = "warn"
|
||||||
|
empty_drop = "warn"
|
||||||
|
empty_structs_with_brackets = "warn"
|
||||||
|
exit = "warn"
|
||||||
|
get_unwrap = "warn"
|
||||||
|
rc_buffer = "warn"
|
||||||
|
rc_mutex = "warn"
|
||||||
|
rest_pat_in_fully_bound_structs = "warn"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
lto = "fat"
|
lto = "fat"
|
||||||
codegen-units = 1
|
codegen-units = 1
|
||||||
|
|||||||
38
Dockerfile
Normal file
38
Dockerfile
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
FROM --platform=$BUILDPLATFORM ubuntu as build
|
||||||
|
ENV HOME="/root"
|
||||||
|
WORKDIR $HOME
|
||||||
|
|
||||||
|
RUN apt update && apt install -y build-essential curl python3-venv
|
||||||
|
|
||||||
|
# Setup zig as cross compiling linker
|
||||||
|
RUN python3 -m venv $HOME/.venv
|
||||||
|
RUN .venv/bin/pip install cargo-zigbuild
|
||||||
|
ENV PATH="$HOME/.venv/bin:$PATH"
|
||||||
|
|
||||||
|
# Install rust
|
||||||
|
ARG TARGETPLATFORM
|
||||||
|
RUN case "$TARGETPLATFORM" in \
|
||||||
|
"linux/arm64") echo "aarch64-unknown-linux-musl" > rust_target.txt ;; \
|
||||||
|
"linux/amd64") echo "x86_64-unknown-linux-musl" > rust_target.txt ;; \
|
||||||
|
*) exit 1 ;; \
|
||||||
|
esac
|
||||||
|
# Update rustup whenever we bump the rust version
|
||||||
|
COPY rust-toolchain.toml rust-toolchain.toml
|
||||||
|
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --target $(cat rust_target.txt) --profile minimal --default-toolchain none
|
||||||
|
ENV PATH="$HOME/.cargo/bin:$PATH"
|
||||||
|
# Installs the correct toolchain version from rust-toolchain.toml and then the musl target
|
||||||
|
RUN rustup target add $(cat rust_target.txt)
|
||||||
|
|
||||||
|
# Build
|
||||||
|
COPY crates crates
|
||||||
|
COPY Cargo.toml Cargo.toml
|
||||||
|
COPY Cargo.lock Cargo.lock
|
||||||
|
RUN cargo zigbuild --bin ruff --target $(cat rust_target.txt) --release
|
||||||
|
RUN cp target/$(cat rust_target.txt)/release/ruff /ruff
|
||||||
|
# TODO: Optimize binary size, with a version that also works when cross compiling
|
||||||
|
# RUN strip --strip-all /ruff
|
||||||
|
|
||||||
|
FROM scratch
|
||||||
|
COPY --from=build /ruff /ruff
|
||||||
|
WORKDIR /io
|
||||||
|
ENTRYPOINT ["/ruff"]
|
||||||
20
README.md
20
README.md
@@ -54,7 +54,7 @@ Ruff is extremely actively developed and used in major open-source projects like
|
|||||||
- [Pandas](https://github.com/pandas-dev/pandas)
|
- [Pandas](https://github.com/pandas-dev/pandas)
|
||||||
- [SciPy](https://github.com/scipy/scipy)
|
- [SciPy](https://github.com/scipy/scipy)
|
||||||
|
|
||||||
...and many more.
|
...and [many more](#whos-using-ruff).
|
||||||
|
|
||||||
Ruff is backed by [Astral](https://astral.sh). Read the [launch post](https://astral.sh/blog/announcing-astral-the-company-behind-ruff),
|
Ruff is backed by [Astral](https://astral.sh). Read the [launch post](https://astral.sh/blog/announcing-astral-the-company-behind-ruff),
|
||||||
or the original [project announcement](https://notes.crmarsh.com/python-tooling-could-be-much-much-faster).
|
or the original [project announcement](https://notes.crmarsh.com/python-tooling-could-be-much-much-faster).
|
||||||
@@ -150,7 +150,7 @@ Ruff can also be used as a [pre-commit](https://pre-commit.com/) hook via [`ruff
|
|||||||
```yaml
|
```yaml
|
||||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||||
# Ruff version.
|
# Ruff version.
|
||||||
rev: v0.1.5
|
rev: v0.1.7
|
||||||
hooks:
|
hooks:
|
||||||
# Run the linter.
|
# Run the linter.
|
||||||
- id: ruff
|
- id: ruff
|
||||||
@@ -377,8 +377,8 @@ Ruff is used by a number of major open-source projects and companies, including:
|
|||||||
- Anthropic ([Python SDK](https://github.com/anthropics/anthropic-sdk-python))
|
- Anthropic ([Python SDK](https://github.com/anthropics/anthropic-sdk-python))
|
||||||
- [Apache Airflow](https://github.com/apache/airflow)
|
- [Apache Airflow](https://github.com/apache/airflow)
|
||||||
- AstraZeneca ([Magnus](https://github.com/AstraZeneca/magnus-core))
|
- AstraZeneca ([Magnus](https://github.com/AstraZeneca/magnus-core))
|
||||||
- Benchling ([Refac](https://github.com/benchling/refac))
|
|
||||||
- [Babel](https://github.com/python-babel/babel)
|
- [Babel](https://github.com/python-babel/babel)
|
||||||
|
- Benchling ([Refac](https://github.com/benchling/refac))
|
||||||
- [Bokeh](https://github.com/bokeh/bokeh)
|
- [Bokeh](https://github.com/bokeh/bokeh)
|
||||||
- [Cryptography (PyCA)](https://github.com/pyca/cryptography)
|
- [Cryptography (PyCA)](https://github.com/pyca/cryptography)
|
||||||
- [DVC](https://github.com/iterative/dvc)
|
- [DVC](https://github.com/iterative/dvc)
|
||||||
@@ -389,15 +389,16 @@ Ruff is used by a number of major open-source projects and companies, including:
|
|||||||
- [Gradio](https://github.com/gradio-app/gradio)
|
- [Gradio](https://github.com/gradio-app/gradio)
|
||||||
- [Great Expectations](https://github.com/great-expectations/great_expectations)
|
- [Great Expectations](https://github.com/great-expectations/great_expectations)
|
||||||
- [HTTPX](https://github.com/encode/httpx)
|
- [HTTPX](https://github.com/encode/httpx)
|
||||||
|
- [Hatch](https://github.com/pypa/hatch)
|
||||||
|
- [Home Assistant](https://github.com/home-assistant/core)
|
||||||
- Hugging Face ([Transformers](https://github.com/huggingface/transformers),
|
- Hugging Face ([Transformers](https://github.com/huggingface/transformers),
|
||||||
[Datasets](https://github.com/huggingface/datasets),
|
[Datasets](https://github.com/huggingface/datasets),
|
||||||
[Diffusers](https://github.com/huggingface/diffusers))
|
[Diffusers](https://github.com/huggingface/diffusers))
|
||||||
- [Hatch](https://github.com/pypa/hatch)
|
|
||||||
- [Home Assistant](https://github.com/home-assistant/core)
|
|
||||||
- ING Bank ([popmon](https://github.com/ing-bank/popmon), [probatus](https://github.com/ing-bank/probatus))
|
- ING Bank ([popmon](https://github.com/ing-bank/popmon), [probatus](https://github.com/ing-bank/probatus))
|
||||||
- [Ibis](https://github.com/ibis-project/ibis)
|
- [Ibis](https://github.com/ibis-project/ibis)
|
||||||
- [Jupyter](https://github.com/jupyter-server/jupyter_server)
|
- [Jupyter](https://github.com/jupyter-server/jupyter_server)
|
||||||
- [LangChain](https://github.com/hwchase17/langchain)
|
- [LangChain](https://github.com/hwchase17/langchain)
|
||||||
|
- [Litestar](https://litestar.dev/)
|
||||||
- [LlamaIndex](https://github.com/jerryjliu/llama_index)
|
- [LlamaIndex](https://github.com/jerryjliu/llama_index)
|
||||||
- Matrix ([Synapse](https://github.com/matrix-org/synapse))
|
- Matrix ([Synapse](https://github.com/matrix-org/synapse))
|
||||||
- [MegaLinter](https://github.com/oxsecurity/megalinter)
|
- [MegaLinter](https://github.com/oxsecurity/megalinter)
|
||||||
@@ -422,20 +423,21 @@ Ruff is used by a number of major open-source projects and companies, including:
|
|||||||
- [PostHog](https://github.com/PostHog/posthog)
|
- [PostHog](https://github.com/PostHog/posthog)
|
||||||
- Prefect ([Python SDK](https://github.com/PrefectHQ/prefect), [Marvin](https://github.com/PrefectHQ/marvin))
|
- Prefect ([Python SDK](https://github.com/PrefectHQ/prefect), [Marvin](https://github.com/PrefectHQ/marvin))
|
||||||
- [PyInstaller](https://github.com/pyinstaller/pyinstaller)
|
- [PyInstaller](https://github.com/pyinstaller/pyinstaller)
|
||||||
|
- [PyMC-Marketing](https://github.com/pymc-labs/pymc-marketing)
|
||||||
- [PyTorch](https://github.com/pytorch/pytorch)
|
- [PyTorch](https://github.com/pytorch/pytorch)
|
||||||
- [Pydantic](https://github.com/pydantic/pydantic)
|
- [Pydantic](https://github.com/pydantic/pydantic)
|
||||||
- [Pylint](https://github.com/PyCQA/pylint)
|
- [Pylint](https://github.com/PyCQA/pylint)
|
||||||
- [PyMC-Marketing](https://github.com/pymc-labs/pymc-marketing)
|
|
||||||
- [Reflex](https://github.com/reflex-dev/reflex)
|
- [Reflex](https://github.com/reflex-dev/reflex)
|
||||||
|
- [River](https://github.com/online-ml/river)
|
||||||
- [Rippling](https://rippling.com)
|
- [Rippling](https://rippling.com)
|
||||||
- [Robyn](https://github.com/sansyrox/robyn)
|
- [Robyn](https://github.com/sansyrox/robyn)
|
||||||
- Scale AI ([Launch SDK](https://github.com/scaleapi/launch-python-client))
|
|
||||||
- Snowflake ([SnowCLI](https://github.com/Snowflake-Labs/snowcli))
|
|
||||||
- [Saleor](https://github.com/saleor/saleor)
|
- [Saleor](https://github.com/saleor/saleor)
|
||||||
|
- Scale AI ([Launch SDK](https://github.com/scaleapi/launch-python-client))
|
||||||
- [SciPy](https://github.com/scipy/scipy)
|
- [SciPy](https://github.com/scipy/scipy)
|
||||||
|
- Snowflake ([SnowCLI](https://github.com/Snowflake-Labs/snowcli))
|
||||||
- [Sphinx](https://github.com/sphinx-doc/sphinx)
|
- [Sphinx](https://github.com/sphinx-doc/sphinx)
|
||||||
- [Stable Baselines3](https://github.com/DLR-RM/stable-baselines3)
|
- [Stable Baselines3](https://github.com/DLR-RM/stable-baselines3)
|
||||||
- [Litestar](https://litestar.dev/)
|
- [Starlette](https://github.com/encode/starlette)
|
||||||
- [The Algorithms](https://github.com/TheAlgorithms/Python)
|
- [The Algorithms](https://github.com/TheAlgorithms/Python)
|
||||||
- [Vega-Altair](https://github.com/altair-viz/altair)
|
- [Vega-Altair](https://github.com/altair-viz/altair)
|
||||||
- WordPress ([Openverse](https://github.com/WordPress/openverse))
|
- WordPress ([Openverse](https://github.com/WordPress/openverse))
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "flake8-to-ruff"
|
name = "flake8-to-ruff"
|
||||||
version = "0.1.5"
|
version = "0.1.7"
|
||||||
description = """
|
description = """
|
||||||
Convert Flake8 configuration files to Ruff configuration files.
|
Convert Flake8 configuration files to Ruff configuration files.
|
||||||
"""
|
"""
|
||||||
@@ -19,7 +19,7 @@ ruff_workspace = { path = "../ruff_workspace" }
|
|||||||
anyhow = { workspace = true }
|
anyhow = { workspace = true }
|
||||||
clap = { workspace = true }
|
clap = { workspace = true }
|
||||||
colored = { workspace = true }
|
colored = { workspace = true }
|
||||||
configparser = { version = "3.0.2" }
|
configparser = { version = "3.0.3" }
|
||||||
itertools = { workspace = true }
|
itertools = { workspace = true }
|
||||||
log = { workspace = true }
|
log = { workspace = true }
|
||||||
once_cell = { workspace = true }
|
once_cell = { workspace = true }
|
||||||
@@ -34,3 +34,6 @@ toml = { workspace = true }
|
|||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
pretty_assertions = "1.3.0"
|
pretty_assertions = "1.3.0"
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|||||||
@@ -34,10 +34,10 @@ harness = false
|
|||||||
once_cell.workspace = true
|
once_cell.workspace = true
|
||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
serde_json.workspace = true
|
serde_json.workspace = true
|
||||||
url = "2.3.1"
|
url = "2.5.0"
|
||||||
ureq = "2.8.0"
|
ureq = "2.9.1"
|
||||||
criterion = { version = "0.5.1", default-features = false }
|
criterion = { version = "0.5.1", default-features = false }
|
||||||
codspeed-criterion-compat = { version="2.3.1", default-features = false, optional = true}
|
codspeed-criterion-compat = { version="2.3.3", default-features = false, optional = true}
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
ruff_linter.path = "../ruff_linter"
|
ruff_linter.path = "../ruff_linter"
|
||||||
@@ -46,6 +46,9 @@ ruff_python_formatter = { path = "../ruff_python_formatter" }
|
|||||||
ruff_python_index = { path = "../ruff_python_index" }
|
ruff_python_index = { path = "../ruff_python_index" }
|
||||||
ruff_python_parser = { path = "../ruff_python_parser" }
|
ruff_python_parser = { path = "../ruff_python_parser" }
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
codspeed = ["codspeed-criterion-compat"]
|
codspeed = ["codspeed-criterion-compat"]
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use ruff_benchmark::criterion::{
|
|||||||
criterion_group, criterion_main, BenchmarkId, Criterion, Throughput,
|
criterion_group, criterion_main, BenchmarkId, Criterion, Throughput,
|
||||||
};
|
};
|
||||||
use ruff_benchmark::{TestCase, TestFile, TestFileDownloadError};
|
use ruff_benchmark::{TestCase, TestFile, TestFileDownloadError};
|
||||||
use ruff_python_formatter::{format_module_ast, PyFormatOptions};
|
use ruff_python_formatter::{format_module_ast, PreviewMode, PyFormatOptions};
|
||||||
use ruff_python_index::CommentRangesBuilder;
|
use ruff_python_index::CommentRangesBuilder;
|
||||||
use ruff_python_parser::lexer::lex;
|
use ruff_python_parser::lexer::lex;
|
||||||
use ruff_python_parser::{parse_tokens, Mode};
|
use ruff_python_parser::{parse_tokens, Mode};
|
||||||
@@ -69,7 +69,8 @@ fn benchmark_formatter(criterion: &mut Criterion) {
|
|||||||
.expect("Input to be a valid python program");
|
.expect("Input to be a valid python program");
|
||||||
|
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
let options = PyFormatOptions::from_extension(Path::new(case.name()));
|
let options = PyFormatOptions::from_extension(Path::new(case.name()))
|
||||||
|
.with_preview(PreviewMode::Enabled);
|
||||||
let formatted =
|
let formatted =
|
||||||
format_module_ast(&module, &comment_ranges, case.code(), options)
|
format_module_ast(&module, &comment_ranges, case.code(), options)
|
||||||
.expect("Formatting to succeed");
|
.expect("Formatting to succeed");
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ use ruff_benchmark::criterion::{
|
|||||||
};
|
};
|
||||||
use ruff_benchmark::{TestCase, TestFile, TestFileDownloadError};
|
use ruff_benchmark::{TestCase, TestFile, TestFileDownloadError};
|
||||||
use ruff_linter::linter::lint_only;
|
use ruff_linter::linter::lint_only;
|
||||||
|
use ruff_linter::rule_selector::PreviewOptions;
|
||||||
use ruff_linter::settings::rule_table::RuleTable;
|
use ruff_linter::settings::rule_table::RuleTable;
|
||||||
|
use ruff_linter::settings::types::PreviewMode;
|
||||||
use ruff_linter::settings::{flags, LinterSettings};
|
use ruff_linter::settings::{flags, LinterSettings};
|
||||||
use ruff_linter::source_kind::SourceKind;
|
use ruff_linter::source_kind::SourceKind;
|
||||||
use ruff_linter::{registry::Rule, RuleSelector};
|
use ruff_linter::{registry::Rule, RuleSelector};
|
||||||
@@ -78,12 +80,21 @@ fn benchmark_default_rules(criterion: &mut Criterion) {
|
|||||||
benchmark_linter(group, &LinterSettings::default());
|
benchmark_linter(group, &LinterSettings::default());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn benchmark_all_rules(criterion: &mut Criterion) {
|
/// Disables IO based rules because they are a source of flakiness
|
||||||
let mut rules: RuleTable = RuleSelector::All.all_rules().collect();
|
fn disable_io_rules(rules: &mut RuleTable) {
|
||||||
|
|
||||||
// Disable IO based rules because it is a source of flakiness
|
|
||||||
rules.disable(Rule::ShebangMissingExecutableFile);
|
rules.disable(Rule::ShebangMissingExecutableFile);
|
||||||
rules.disable(Rule::ShebangNotExecutable);
|
rules.disable(Rule::ShebangNotExecutable);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn benchmark_all_rules(criterion: &mut Criterion) {
|
||||||
|
let mut rules: RuleTable = RuleSelector::All
|
||||||
|
.rules(&PreviewOptions {
|
||||||
|
mode: PreviewMode::Disabled,
|
||||||
|
require_explicit: false,
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
disable_io_rules(&mut rules);
|
||||||
|
|
||||||
let settings = LinterSettings {
|
let settings = LinterSettings {
|
||||||
rules,
|
rules,
|
||||||
@@ -94,6 +105,22 @@ fn benchmark_all_rules(criterion: &mut Criterion) {
|
|||||||
benchmark_linter(group, &settings);
|
benchmark_linter(group, &settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn benchmark_preview_rules(criterion: &mut Criterion) {
|
||||||
|
let mut rules: RuleTable = RuleSelector::All.all_rules().collect();
|
||||||
|
|
||||||
|
disable_io_rules(&mut rules);
|
||||||
|
|
||||||
|
let settings = LinterSettings {
|
||||||
|
rules,
|
||||||
|
preview: PreviewMode::Enabled,
|
||||||
|
..LinterSettings::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
let group = criterion.benchmark_group("linter/all-with-preview-rules");
|
||||||
|
benchmark_linter(group, &settings);
|
||||||
|
}
|
||||||
|
|
||||||
criterion_group!(default_rules, benchmark_default_rules);
|
criterion_group!(default_rules, benchmark_default_rules);
|
||||||
criterion_group!(all_rules, benchmark_all_rules);
|
criterion_group!(all_rules, benchmark_all_rules);
|
||||||
criterion_main!(default_rules, all_rules);
|
criterion_group!(preview_rules, benchmark_preview_rules);
|
||||||
|
criterion_main!(default_rules, all_rules, preview_rules);
|
||||||
|
|||||||
@@ -20,3 +20,6 @@ seahash = "4.1.0"
|
|||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
ruff_macros = { path = "../ruff_macros" }
|
ruff_macros = { path = "../ruff_macros" }
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "ruff_cli"
|
name = "ruff_cli"
|
||||||
version = "0.1.5"
|
version = "0.1.7"
|
||||||
publish = false
|
publish = false
|
||||||
authors = { workspace = true }
|
authors = { workspace = true }
|
||||||
edition = { workspace = true }
|
edition = { workspace = true }
|
||||||
@@ -28,7 +28,7 @@ ruff_python_trivia = { path = "../ruff_python_trivia" }
|
|||||||
ruff_workspace = { path = "../ruff_workspace" }
|
ruff_workspace = { path = "../ruff_workspace" }
|
||||||
ruff_text_size = { path = "../ruff_text_size" }
|
ruff_text_size = { path = "../ruff_text_size" }
|
||||||
|
|
||||||
annotate-snippets = { version = "0.9.1", features = ["color"] }
|
annotate-snippets = { version = "0.9.2", features = ["color"] }
|
||||||
anyhow = { workspace = true }
|
anyhow = { workspace = true }
|
||||||
argfile = { version = "0.1.6" }
|
argfile = { version = "0.1.6" }
|
||||||
bincode = { version = "1.3.3" }
|
bincode = { version = "1.3.3" }
|
||||||
@@ -69,10 +69,13 @@ insta = { workspace = true, features = ["filters", "json"] }
|
|||||||
insta-cmd = { version = "0.4.0" }
|
insta-cmd = { version = "0.4.0" }
|
||||||
tempfile = "3.8.1"
|
tempfile = "3.8.1"
|
||||||
test-case = { workspace = true }
|
test-case = { workspace = true }
|
||||||
ureq = { version = "2.8.0", features = [] }
|
ureq = { version = "2.9.1", features = [] }
|
||||||
|
|
||||||
[target.'cfg(target_os = "windows")'.dependencies]
|
[target.'cfg(target_os = "windows")'.dependencies]
|
||||||
mimalloc = "0.1.39"
|
mimalloc = "0.1.39"
|
||||||
|
|
||||||
[target.'cfg(all(not(target_os = "windows"), not(target_os = "openbsd"), any(target_arch = "x86_64", target_arch = "aarch64", target_arch = "powerpc64")))'.dependencies]
|
[target.'cfg(all(not(target_os = "windows"), not(target_os = "openbsd"), any(target_arch = "x86_64", target_arch = "aarch64", target_arch = "powerpc64")))'.dependencies]
|
||||||
tikv-jemallocator = "0.5.0"
|
tikv-jemallocator = "0.5.0"
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|||||||
0
crates/ruff_cli/resources/test/fixtures/include-test/a.py
vendored
Normal file
0
crates/ruff_cli/resources/test/fixtures/include-test/a.py
vendored
Normal file
0
crates/ruff_cli/resources/test/fixtures/include-test/b.py
vendored
Normal file
0
crates/ruff_cli/resources/test/fixtures/include-test/b.py
vendored
Normal file
0
crates/ruff_cli/resources/test/fixtures/include-test/nested-project/e.py
vendored
Normal file
0
crates/ruff_cli/resources/test/fixtures/include-test/nested-project/e.py
vendored
Normal file
2
crates/ruff_cli/resources/test/fixtures/include-test/nested-project/pyproject.toml
vendored
Normal file
2
crates/ruff_cli/resources/test/fixtures/include-test/nested-project/pyproject.toml
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
[tool.ruff]
|
||||||
|
select = []
|
||||||
2
crates/ruff_cli/resources/test/fixtures/include-test/pyproject.toml
vendored
Normal file
2
crates/ruff_cli/resources/test/fixtures/include-test/pyproject.toml
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
[tool.ruff]
|
||||||
|
include = ["a.py", "subdirectory/c.py"]
|
||||||
0
crates/ruff_cli/resources/test/fixtures/include-test/subdirectory/c.py
vendored
Normal file
0
crates/ruff_cli/resources/test/fixtures/include-test/subdirectory/c.py
vendored
Normal file
0
crates/ruff_cli/resources/test/fixtures/include-test/subdirectory/d.py
vendored
Normal file
0
crates/ruff_cli/resources/test/fixtures/include-test/subdirectory/d.py
vendored
Normal file
413
crates/ruff_cli/resources/test/fixtures/trailing_semicolon.ipynb
vendored
Normal file
413
crates/ruff_cli/resources/test/fixtures/trailing_semicolon.ipynb
vendored
Normal file
@@ -0,0 +1,413 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 1,
|
||||||
|
"id": "4f8ce941-1492-4d4e-8ab5-70d733fe891a",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"%config ZMQInteractiveShell.ast_node_interactivity=\"last_expr_or_assign\""
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 2,
|
||||||
|
"id": "721ec705-0c65-4bfb-9809-7ed8bc534186",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 2,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"# Assignment statement without a semicolon\n",
|
||||||
|
"x = 1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 3,
|
||||||
|
"id": "de50e495-17e5-41cc-94bd-565757555d7e",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Assignment statement with a semicolon\n",
|
||||||
|
"x = 1;\n",
|
||||||
|
"x = 1;"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 4,
|
||||||
|
"id": "39e31201-23da-44eb-8684-41bba3663991",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"2"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 4,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"# Augmented assignment without a semicolon\n",
|
||||||
|
"x += 1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 5,
|
||||||
|
"id": "6b73d3dd-c73a-4697-9e97-e109a6c1fbab",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Augmented assignment without a semicolon\n",
|
||||||
|
"x += 1;\n",
|
||||||
|
"x += 1; # comment\n",
|
||||||
|
"# comment"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 6,
|
||||||
|
"id": "2a3e5b86-aa5b-46ba-b9c6-0386d876f58c",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Multiple assignment without a semicolon\n",
|
||||||
|
"x = y = 1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 7,
|
||||||
|
"id": "07f89e51-9357-4cfb-8fc5-76fb75e35949",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Multiple assignment with a semicolon\n",
|
||||||
|
"x = y = 1;\n",
|
||||||
|
"x = y = 1;"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 8,
|
||||||
|
"id": "c22b539d-473e-48f8-a236-625e58c47a00",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Tuple unpacking without a semicolon\n",
|
||||||
|
"x, y = 1, 2"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 9,
|
||||||
|
"id": "12c87940-a0d5-403b-a81c-7507eb06dc7e",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Tuple unpacking with a semicolon (irrelevant)\n",
|
||||||
|
"x, y = 1, 2;\n",
|
||||||
|
"x, y = 1, 2; # comment\n",
|
||||||
|
"# comment"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 10,
|
||||||
|
"id": "5a768c76-6bc4-470c-b37e-8cc14bc6caf4",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 10,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"# Annotated assignment statement without a semicolon\n",
|
||||||
|
"x: int = 1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 11,
|
||||||
|
"id": "21bfda82-1a9a-4ba1-9078-74ac480804b5",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Annotated assignment statement without a semicolon\n",
|
||||||
|
"x: int = 1;\n",
|
||||||
|
"x: int = 1; # comment\n",
|
||||||
|
"# comment"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 12,
|
||||||
|
"id": "09929999-ff29-4d10-ad2b-e665af15812d",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 12,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"# Assignment expression without a semicolon\n",
|
||||||
|
"(x := 1)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 13,
|
||||||
|
"id": "32a83217-1bad-4f61-855e-ffcdb119c763",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Assignment expression with a semicolon\n",
|
||||||
|
"(x := 1);\n",
|
||||||
|
"(x := 1); # comment\n",
|
||||||
|
"# comment"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 14,
|
||||||
|
"id": "61b81865-277e-4964-b03e-eb78f1f318eb",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 14,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"x = 1\n",
|
||||||
|
"# Expression without a semicolon\n",
|
||||||
|
"x"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 15,
|
||||||
|
"id": "974c29be-67e1-4000-95fa-6ca118a63bad",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"x = 1\n",
|
||||||
|
"# Expression with a semicolon\n",
|
||||||
|
"x;"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 16,
|
||||||
|
"id": "cfeb1757-46d6-4f13-969f-a283b6d0304f",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"class Point:\n",
|
||||||
|
" def __init__(self, x, y):\n",
|
||||||
|
" self.x = x\n",
|
||||||
|
" self.y = y\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"p = Point(0, 0);"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 17,
|
||||||
|
"id": "2ee7f1a5-ccfe-4004-bfa4-ef834a58da97",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Assignment statement where the left is an attribute access doesn't\n",
|
||||||
|
"# print the value.\n",
|
||||||
|
"p.x = 1;"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 18,
|
||||||
|
"id": "3e49370a-048b-474d-aa0a-3d1d4a73ad37",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"data = {}\n",
|
||||||
|
"\n",
|
||||||
|
"# Neither does the subscript node\n",
|
||||||
|
"data[\"foo\"] = 1;"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 19,
|
||||||
|
"id": "d594bdd3-eaa9-41ef-8cda-cf01bc273b2d",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"if (x := 1):\n",
|
||||||
|
" # It should be the top level statement\n",
|
||||||
|
" x"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 20,
|
||||||
|
"id": "e532f0cf-80c7-42b7-8226-6002fcf74fb6",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 20,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"# Parentheses with comments\n",
|
||||||
|
"(\n",
|
||||||
|
" x := 1 # comment\n",
|
||||||
|
") # comment"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 21,
|
||||||
|
"id": "473c5d62-871b-46ed-8a34-27095243f462",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Parentheses with comments\n",
|
||||||
|
"(\n",
|
||||||
|
" x := 1 # comment\n",
|
||||||
|
"); # comment"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 22,
|
||||||
|
"id": "8c3c2361-f49f-45fe-bbe3-7e27410a8a86",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"'Hello world!'"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 22,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"\"\"\"Hello world!\"\"\""
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 23,
|
||||||
|
"id": "23dbe9b5-3f68-4890-ab2d-ab0dbfd0712a",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"\"\"\"Hello world!\"\"\"; # comment\n",
|
||||||
|
"# comment"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 24,
|
||||||
|
"id": "3ce33108-d95d-4c70-83d1-0d4fd36a2951",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"'x = 1'"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 24,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"x = 1\n",
|
||||||
|
"f\"x = {x}\""
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 25,
|
||||||
|
"id": "654a4a67-de43-4684-824a-9451c67db48f",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"x = 1\n",
|
||||||
|
"f\"x = {x}\";\n",
|
||||||
|
"f\"x = {x}\"; # comment\n",
|
||||||
|
"# comment"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python (ruff-playground)",
|
||||||
|
"language": "python",
|
||||||
|
"name": "ruff-playground"
|
||||||
|
},
|
||||||
|
"language_info": {
|
||||||
|
"codemirror_mode": {
|
||||||
|
"name": "ipython",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"file_extension": ".py",
|
||||||
|
"mimetype": "text/x-python",
|
||||||
|
"name": "python",
|
||||||
|
"nbconvert_exporter": "python",
|
||||||
|
"pygments_lexer": "ipython3",
|
||||||
|
"version": "3.11.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 5
|
||||||
|
}
|
||||||
@@ -88,6 +88,7 @@ pub enum Command {
|
|||||||
#[allow(clippy::struct_excessive_bools)]
|
#[allow(clippy::struct_excessive_bools)]
|
||||||
pub struct CheckCommand {
|
pub struct CheckCommand {
|
||||||
/// List of files or directories to check.
|
/// List of files or directories to check.
|
||||||
|
#[clap(help = "List of files or directories to check [default: .]")]
|
||||||
pub files: Vec<PathBuf>,
|
pub files: Vec<PathBuf>,
|
||||||
/// Apply fixes to resolve lint violations.
|
/// Apply fixes to resolve lint violations.
|
||||||
/// Use `--no-fix` to disable or `--unsafe-fixes` to include unsafe fixes.
|
/// Use `--no-fix` to disable or `--unsafe-fixes` to include unsafe fixes.
|
||||||
@@ -363,6 +364,7 @@ pub struct CheckCommand {
|
|||||||
#[allow(clippy::struct_excessive_bools)]
|
#[allow(clippy::struct_excessive_bools)]
|
||||||
pub struct FormatCommand {
|
pub struct FormatCommand {
|
||||||
/// List of files or directories to format.
|
/// List of files or directories to format.
|
||||||
|
#[clap(help = "List of files or directories to format [default: .]")]
|
||||||
pub files: Vec<PathBuf>,
|
pub files: Vec<PathBuf>,
|
||||||
/// Avoid writing any formatted files back; instead, exit with a non-zero status code if any
|
/// Avoid writing any formatted files back; instead, exit with a non-zero status code if any
|
||||||
/// files would have been modified, and zero otherwise.
|
/// files would have been modified, and zero otherwise.
|
||||||
|
|||||||
@@ -202,12 +202,12 @@ fn lint_path(
|
|||||||
match result {
|
match result {
|
||||||
Ok(inner) => inner,
|
Ok(inner) => inner,
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
let message = r#"This indicates a bug in Ruff. If you could open an issue at:
|
let message = r"This indicates a bug in Ruff. If you could open an issue at:
|
||||||
|
|
||||||
https://github.com/astral-sh/ruff/issues/new?title=%5BLinter%20panic%5D
|
https://github.com/astral-sh/ruff/issues/new?title=%5BLinter%20panic%5D
|
||||||
|
|
||||||
...with the relevant file contents, the `pyproject.toml` settings, and the following stack trace, we'd be very appreciative!
|
...with the relevant file contents, the `pyproject.toml` settings, and the following stack trace, we'd be very appreciative!
|
||||||
"#;
|
";
|
||||||
|
|
||||||
error!(
|
error!(
|
||||||
"{}{}{} {message}\n{error}",
|
"{}{}{} {message}\n{error}",
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use ruff_workspace::resolver::{match_exclusion, python_file_at_path, PyprojectCo
|
|||||||
|
|
||||||
use crate::args::CliOverrides;
|
use crate::args::CliOverrides;
|
||||||
use crate::diagnostics::{lint_stdin, Diagnostics};
|
use crate::diagnostics::{lint_stdin, Diagnostics};
|
||||||
use crate::stdin::read_from_stdin;
|
use crate::stdin::{parrot_stdin, read_from_stdin};
|
||||||
|
|
||||||
/// Run the linter over a single file, read from `stdin`.
|
/// Run the linter over a single file, read from `stdin`.
|
||||||
pub(crate) fn check_stdin(
|
pub(crate) fn check_stdin(
|
||||||
@@ -21,6 +21,9 @@ pub(crate) fn check_stdin(
|
|||||||
if pyproject_config.settings.file_resolver.force_exclude {
|
if pyproject_config.settings.file_resolver.force_exclude {
|
||||||
if let Some(filename) = filename {
|
if let Some(filename) = filename {
|
||||||
if !python_file_at_path(filename, pyproject_config, overrides)? {
|
if !python_file_at_path(filename, pyproject_config, overrides)? {
|
||||||
|
if fix_mode.is_apply() {
|
||||||
|
parrot_stdin()?;
|
||||||
|
}
|
||||||
return Ok(Diagnostics::default());
|
return Ok(Diagnostics::default());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,14 +32,17 @@ pub(crate) fn check_stdin(
|
|||||||
.file_name()
|
.file_name()
|
||||||
.is_some_and(|name| match_exclusion(filename, name, &lint_settings.exclude))
|
.is_some_and(|name| match_exclusion(filename, name, &lint_settings.exclude))
|
||||||
{
|
{
|
||||||
|
if fix_mode.is_apply() {
|
||||||
|
parrot_stdin()?;
|
||||||
|
}
|
||||||
return Ok(Diagnostics::default());
|
return Ok(Diagnostics::default());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let stdin = read_from_stdin()?;
|
||||||
let package_root = filename.and_then(Path::parent).and_then(|path| {
|
let package_root = filename.and_then(Path::parent).and_then(|path| {
|
||||||
packaging::detect_package_root(path, &pyproject_config.settings.linter.namespace_packages)
|
packaging::detect_package_root(path, &pyproject_config.settings.linter.namespace_packages)
|
||||||
});
|
});
|
||||||
let stdin = read_from_stdin()?;
|
|
||||||
let mut diagnostics = lint_stdin(
|
let mut diagnostics = lint_stdin(
|
||||||
filename,
|
filename,
|
||||||
package_root,
|
package_root,
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ use crate::args::{CliOverrides, FormatArguments};
|
|||||||
use crate::cache::{Cache, FileCacheKey, PackageCacheMap, PackageCaches};
|
use crate::cache::{Cache, FileCacheKey, PackageCacheMap, PackageCaches};
|
||||||
use crate::panic::{catch_unwind, PanicError};
|
use crate::panic::{catch_unwind, PanicError};
|
||||||
use crate::resolve::resolve;
|
use crate::resolve::resolve;
|
||||||
use crate::ExitStatus;
|
use crate::{resolve_default_files, ExitStatus};
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, is_macro::Is)]
|
#[derive(Debug, Copy, Clone, is_macro::Is)]
|
||||||
pub(crate) enum FormatMode {
|
pub(crate) enum FormatMode {
|
||||||
@@ -60,7 +60,7 @@ impl FormatMode {
|
|||||||
|
|
||||||
/// Format a set of files, and return the exit status.
|
/// Format a set of files, and return the exit status.
|
||||||
pub(crate) fn format(
|
pub(crate) fn format(
|
||||||
cli: &FormatArguments,
|
cli: FormatArguments,
|
||||||
overrides: &CliOverrides,
|
overrides: &CliOverrides,
|
||||||
log_level: LogLevel,
|
log_level: LogLevel,
|
||||||
) -> Result<ExitStatus> {
|
) -> Result<ExitStatus> {
|
||||||
@@ -70,8 +70,9 @@ pub(crate) fn format(
|
|||||||
overrides,
|
overrides,
|
||||||
cli.stdin_filename.as_deref(),
|
cli.stdin_filename.as_deref(),
|
||||||
)?;
|
)?;
|
||||||
let mode = FormatMode::from_cli(cli);
|
let mode = FormatMode::from_cli(&cli);
|
||||||
let (paths, resolver) = python_files_in_path(&cli.files, &pyproject_config, overrides)?;
|
let files = resolve_default_files(cli.files, false);
|
||||||
|
let (paths, resolver) = python_files_in_path(&files, &pyproject_config, overrides)?;
|
||||||
|
|
||||||
if paths.is_empty() {
|
if paths.is_empty() {
|
||||||
warn_user_once!("No Python files found under the given path(s)");
|
warn_user_once!("No Python files found under the given path(s)");
|
||||||
@@ -660,12 +661,12 @@ impl Display for FormatCommandError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Self::Panic(path, err) => {
|
Self::Panic(path, err) => {
|
||||||
let message = r#"This indicates a bug in Ruff. If you could open an issue at:
|
let message = r"This indicates a bug in Ruff. If you could open an issue at:
|
||||||
|
|
||||||
https://github.com/astral-sh/ruff/issues/new?title=%5BFormatter%20panic%5D
|
https://github.com/astral-sh/ruff/issues/new?title=%5BFormatter%20panic%5D
|
||||||
|
|
||||||
...with the relevant file contents, the `pyproject.toml` settings, and the following stack trace, we'd be very appreciative!
|
...with the relevant file contents, the `pyproject.toml` settings, and the following stack trace, we'd be very appreciative!
|
||||||
"#;
|
";
|
||||||
if let Some(path) = path {
|
if let Some(path) = path {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ use crate::commands::format::{
|
|||||||
FormatResult, FormattedSource,
|
FormatResult, FormattedSource,
|
||||||
};
|
};
|
||||||
use crate::resolve::resolve;
|
use crate::resolve::resolve;
|
||||||
use crate::stdin::read_from_stdin;
|
use crate::stdin::{parrot_stdin, read_from_stdin};
|
||||||
use crate::ExitStatus;
|
use crate::ExitStatus;
|
||||||
|
|
||||||
/// Run the formatter over a single file, read from `stdin`.
|
/// Run the formatter over a single file, read from `stdin`.
|
||||||
@@ -34,6 +34,9 @@ pub(crate) fn format_stdin(cli: &FormatArguments, overrides: &CliOverrides) -> R
|
|||||||
if pyproject_config.settings.file_resolver.force_exclude {
|
if pyproject_config.settings.file_resolver.force_exclude {
|
||||||
if let Some(filename) = cli.stdin_filename.as_deref() {
|
if let Some(filename) = cli.stdin_filename.as_deref() {
|
||||||
if !python_file_at_path(filename, &pyproject_config, overrides)? {
|
if !python_file_at_path(filename, &pyproject_config, overrides)? {
|
||||||
|
if mode.is_write() {
|
||||||
|
parrot_stdin()?;
|
||||||
|
}
|
||||||
return Ok(ExitStatus::Success);
|
return Ok(ExitStatus::Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,6 +45,9 @@ pub(crate) fn format_stdin(cli: &FormatArguments, overrides: &CliOverrides) -> R
|
|||||||
.file_name()
|
.file_name()
|
||||||
.is_some_and(|name| match_exclusion(filename, name, &format_settings.exclude))
|
.is_some_and(|name| match_exclusion(filename, name, &format_settings.exclude))
|
||||||
{
|
{
|
||||||
|
if mode.is_write() {
|
||||||
|
parrot_stdin()?;
|
||||||
|
}
|
||||||
return Ok(ExitStatus::Success);
|
return Ok(ExitStatus::Success);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -50,6 +56,9 @@ pub(crate) fn format_stdin(cli: &FormatArguments, overrides: &CliOverrides) -> R
|
|||||||
let path = cli.stdin_filename.as_deref();
|
let path = cli.stdin_filename.as_deref();
|
||||||
|
|
||||||
let SourceType::Python(source_type) = path.map(SourceType::from).unwrap_or_default() else {
|
let SourceType::Python(source_type) = path.map(SourceType::from).unwrap_or_default() else {
|
||||||
|
if mode.is_write() {
|
||||||
|
parrot_stdin()?;
|
||||||
|
}
|
||||||
return Ok(ExitStatus::Success);
|
return Ok(ExitStatus::Success);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ fn format_rule_text(rule: Rule) -> String {
|
|||||||
|
|
||||||
if rule.is_preview() || rule.is_nursery() {
|
if rule.is_preview() || rule.is_nursery() {
|
||||||
output.push_str(
|
output.push_str(
|
||||||
r#"This rule is in preview and is not stable. The `--preview` flag is required for use."#,
|
r"This rule is in preview and is not stable. The `--preview` flag is required for use.",
|
||||||
);
|
);
|
||||||
output.push('\n');
|
output.push('\n');
|
||||||
output.push('\n');
|
output.push('\n');
|
||||||
|
|||||||
@@ -101,6 +101,19 @@ fn is_stdin(files: &[PathBuf], stdin_filename: Option<&Path>) -> bool {
|
|||||||
file == Path::new("-")
|
file == Path::new("-")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the default set of files if none are provided, otherwise returns `None`.
|
||||||
|
fn resolve_default_files(files: Vec<PathBuf>, is_stdin: bool) -> Vec<PathBuf> {
|
||||||
|
if files.is_empty() {
|
||||||
|
if is_stdin {
|
||||||
|
vec![Path::new("-").to_path_buf()]
|
||||||
|
} else {
|
||||||
|
vec![Path::new(".").to_path_buf()]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
files
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the actual value of the `format` desired from either `output_format`
|
/// Get the actual value of the `format` desired from either `output_format`
|
||||||
/// or `format`, and warn the user if they're using the deprecated form.
|
/// or `format`, and warn the user if they're using the deprecated form.
|
||||||
fn resolve_help_output_format(output_format: HelpFormat, format: Option<HelpFormat>) -> HelpFormat {
|
fn resolve_help_output_format(output_format: HelpFormat, format: Option<HelpFormat>) -> HelpFormat {
|
||||||
@@ -196,7 +209,7 @@ fn format(args: FormatCommand, log_level: LogLevel) -> Result<ExitStatus> {
|
|||||||
if is_stdin(&cli.files, cli.stdin_filename.as_deref()) {
|
if is_stdin(&cli.files, cli.stdin_filename.as_deref()) {
|
||||||
commands::format_stdin::format_stdin(&cli, &overrides)
|
commands::format_stdin::format_stdin(&cli, &overrides)
|
||||||
} else {
|
} else {
|
||||||
commands::format::format(&cli, &overrides, log_level)
|
commands::format::format(cli, &overrides, log_level)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,17 +235,15 @@ pub fn check(args: CheckCommand, log_level: LogLevel) -> Result<ExitStatus> {
|
|||||||
};
|
};
|
||||||
let stderr_writer = Box::new(BufWriter::new(io::stderr()));
|
let stderr_writer = Box::new(BufWriter::new(io::stderr()));
|
||||||
|
|
||||||
|
let is_stdin = is_stdin(&cli.files, cli.stdin_filename.as_deref());
|
||||||
|
let files = resolve_default_files(cli.files, is_stdin);
|
||||||
|
|
||||||
if cli.show_settings {
|
if cli.show_settings {
|
||||||
commands::show_settings::show_settings(
|
commands::show_settings::show_settings(&files, &pyproject_config, &overrides, &mut writer)?;
|
||||||
&cli.files,
|
|
||||||
&pyproject_config,
|
|
||||||
&overrides,
|
|
||||||
&mut writer,
|
|
||||||
)?;
|
|
||||||
return Ok(ExitStatus::Success);
|
return Ok(ExitStatus::Success);
|
||||||
}
|
}
|
||||||
if cli.show_files {
|
if cli.show_files {
|
||||||
commands::show_files::show_files(&cli.files, &pyproject_config, &overrides, &mut writer)?;
|
commands::show_files::show_files(&files, &pyproject_config, &overrides, &mut writer)?;
|
||||||
return Ok(ExitStatus::Success);
|
return Ok(ExitStatus::Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -295,8 +306,7 @@ pub fn check(args: CheckCommand, log_level: LogLevel) -> Result<ExitStatus> {
|
|||||||
if !fix_mode.is_generate() {
|
if !fix_mode.is_generate() {
|
||||||
warn_user!("--fix is incompatible with --add-noqa.");
|
warn_user!("--fix is incompatible with --add-noqa.");
|
||||||
}
|
}
|
||||||
let modifications =
|
let modifications = commands::add_noqa::add_noqa(&files, &pyproject_config, &overrides)?;
|
||||||
commands::add_noqa::add_noqa(&cli.files, &pyproject_config, &overrides)?;
|
|
||||||
if modifications > 0 && log_level >= LogLevel::Default {
|
if modifications > 0 && log_level >= LogLevel::Default {
|
||||||
let s = if modifications == 1 { "" } else { "s" };
|
let s = if modifications == 1 { "" } else { "s" };
|
||||||
#[allow(clippy::print_stderr)]
|
#[allow(clippy::print_stderr)]
|
||||||
@@ -323,7 +333,7 @@ pub fn check(args: CheckCommand, log_level: LogLevel) -> Result<ExitStatus> {
|
|||||||
// Configure the file watcher.
|
// Configure the file watcher.
|
||||||
let (tx, rx) = channel();
|
let (tx, rx) = channel();
|
||||||
let mut watcher = recommended_watcher(tx)?;
|
let mut watcher = recommended_watcher(tx)?;
|
||||||
for file in &cli.files {
|
for file in &files {
|
||||||
watcher.watch(file, RecursiveMode::Recursive)?;
|
watcher.watch(file, RecursiveMode::Recursive)?;
|
||||||
}
|
}
|
||||||
if let Some(file) = pyproject_config.path.as_ref() {
|
if let Some(file) = pyproject_config.path.as_ref() {
|
||||||
@@ -335,7 +345,7 @@ pub fn check(args: CheckCommand, log_level: LogLevel) -> Result<ExitStatus> {
|
|||||||
printer.write_to_user("Starting linter in watch mode...\n");
|
printer.write_to_user("Starting linter in watch mode...\n");
|
||||||
|
|
||||||
let messages = commands::check::check(
|
let messages = commands::check::check(
|
||||||
&cli.files,
|
&files,
|
||||||
&pyproject_config,
|
&pyproject_config,
|
||||||
&overrides,
|
&overrides,
|
||||||
cache.into(),
|
cache.into(),
|
||||||
@@ -368,7 +378,7 @@ pub fn check(args: CheckCommand, log_level: LogLevel) -> Result<ExitStatus> {
|
|||||||
printer.write_to_user("File change detected...\n");
|
printer.write_to_user("File change detected...\n");
|
||||||
|
|
||||||
let messages = commands::check::check(
|
let messages = commands::check::check(
|
||||||
&cli.files,
|
&files,
|
||||||
&pyproject_config,
|
&pyproject_config,
|
||||||
&overrides,
|
&overrides,
|
||||||
cache.into(),
|
cache.into(),
|
||||||
@@ -382,8 +392,6 @@ pub fn check(args: CheckCommand, log_level: LogLevel) -> Result<ExitStatus> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let is_stdin = is_stdin(&cli.files, cli.stdin_filename.as_deref());
|
|
||||||
|
|
||||||
// Generate lint violations.
|
// Generate lint violations.
|
||||||
let diagnostics = if is_stdin {
|
let diagnostics = if is_stdin {
|
||||||
commands::check_stdin::check_stdin(
|
commands::check_stdin::check_stdin(
|
||||||
@@ -395,7 +403,7 @@ pub fn check(args: CheckCommand, log_level: LogLevel) -> Result<ExitStatus> {
|
|||||||
)?
|
)?
|
||||||
} else {
|
} else {
|
||||||
commands::check::check(
|
commands::check::check(
|
||||||
&cli.files,
|
&files,
|
||||||
&pyproject_config,
|
&pyproject_config,
|
||||||
&overrides,
|
&overrides,
|
||||||
cache.into(),
|
cache.into(),
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ pub fn resolve(
|
|||||||
{
|
{
|
||||||
let settings = resolve_root_settings(&pyproject, Relativity::Cwd, overrides)?;
|
let settings = resolve_root_settings(&pyproject, Relativity::Cwd, overrides)?;
|
||||||
debug!(
|
debug!(
|
||||||
"Using user specified pyproject.toml at {}",
|
"Using user-specified configuration file at: {}",
|
||||||
pyproject.display()
|
pyproject.display()
|
||||||
);
|
);
|
||||||
return Ok(PyprojectConfig::new(
|
return Ok(PyprojectConfig::new(
|
||||||
@@ -63,7 +63,10 @@ pub fn resolve(
|
|||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap_or(&path_dedot::CWD.as_path()),
|
.unwrap_or(&path_dedot::CWD.as_path()),
|
||||||
)? {
|
)? {
|
||||||
debug!("Using pyproject.toml (parent) at {}", pyproject.display());
|
debug!(
|
||||||
|
"Using configuration file (via parent) at: {}",
|
||||||
|
pyproject.display()
|
||||||
|
);
|
||||||
let settings = resolve_root_settings(&pyproject, Relativity::Parent, overrides)?;
|
let settings = resolve_root_settings(&pyproject, Relativity::Parent, overrides)?;
|
||||||
return Ok(PyprojectConfig::new(
|
return Ok(PyprojectConfig::new(
|
||||||
PyprojectDiscoveryStrategy::Hierarchical,
|
PyprojectDiscoveryStrategy::Hierarchical,
|
||||||
@@ -77,7 +80,10 @@ pub fn resolve(
|
|||||||
// end up the "closest" `pyproject.toml` file for every Python file later on, so
|
// end up the "closest" `pyproject.toml` file for every Python file later on, so
|
||||||
// these act as the "default" settings.)
|
// these act as the "default" settings.)
|
||||||
if let Some(pyproject) = pyproject::find_user_settings_toml() {
|
if let Some(pyproject) = pyproject::find_user_settings_toml() {
|
||||||
debug!("Using pyproject.toml (cwd) at {}", pyproject.display());
|
debug!(
|
||||||
|
"Using configuration file (via cwd) at: {}",
|
||||||
|
pyproject.display()
|
||||||
|
);
|
||||||
let settings = resolve_root_settings(&pyproject, Relativity::Cwd, overrides)?;
|
let settings = resolve_root_settings(&pyproject, Relativity::Cwd, overrides)?;
|
||||||
return Ok(PyprojectConfig::new(
|
return Ok(PyprojectConfig::new(
|
||||||
PyprojectDiscoveryStrategy::Hierarchical,
|
PyprojectDiscoveryStrategy::Hierarchical,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use std::io;
|
use std::io;
|
||||||
use std::io::Read;
|
use std::io::{Read, Write};
|
||||||
|
|
||||||
/// Read a string from `stdin`.
|
/// Read a string from `stdin`.
|
||||||
pub(crate) fn read_from_stdin() -> Result<String, io::Error> {
|
pub(crate) fn read_from_stdin() -> Result<String, io::Error> {
|
||||||
@@ -7,3 +7,11 @@ pub(crate) fn read_from_stdin() -> Result<String, io::Error> {
|
|||||||
io::stdin().lock().read_to_string(&mut buffer)?;
|
io::stdin().lock().read_to_string(&mut buffer)?;
|
||||||
Ok(buffer)
|
Ok(buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Read bytes from `stdin` and write them to `stdout`.
|
||||||
|
pub(crate) fn parrot_stdin() -> Result<(), io::Error> {
|
||||||
|
let mut buffer = String::new();
|
||||||
|
io::stdin().lock().read_to_string(&mut buffer)?;
|
||||||
|
io::stdout().write_all(buffer.as_bytes())?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|||||||
@@ -43,6 +43,53 @@ if condition:
|
|||||||
"###);
|
"###);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn default_files() -> Result<()> {
|
||||||
|
let tempdir = TempDir::new()?;
|
||||||
|
fs::write(
|
||||||
|
tempdir.path().join("foo.py"),
|
||||||
|
r#"
|
||||||
|
foo = "needs formatting"
|
||||||
|
"#,
|
||||||
|
)?;
|
||||||
|
fs::write(
|
||||||
|
tempdir.path().join("bar.py"),
|
||||||
|
r#"
|
||||||
|
bar = "needs formatting"
|
||||||
|
"#,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||||||
|
.args(["format", "--isolated", "--no-cache", "--check"]).current_dir(tempdir.path()), @r###"
|
||||||
|
success: false
|
||||||
|
exit_code: 1
|
||||||
|
----- stdout -----
|
||||||
|
Would reformat: bar.py
|
||||||
|
Would reformat: foo.py
|
||||||
|
2 files would be reformatted
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
"###);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn format_warn_stdin_filename_with_files() {
|
||||||
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||||||
|
.args(["format", "--isolated", "--stdin-filename", "foo.py"])
|
||||||
|
.arg("foo.py")
|
||||||
|
.pass_stdin("foo = 1"), @r###"
|
||||||
|
success: true
|
||||||
|
exit_code: 0
|
||||||
|
----- stdout -----
|
||||||
|
foo = 1
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
warning: Ignoring file foo.py in favor of standard input.
|
||||||
|
"###);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn format_options() -> Result<()> {
|
fn format_options() -> Result<()> {
|
||||||
let tempdir = TempDir::new()?;
|
let tempdir = TempDir::new()?;
|
||||||
@@ -320,6 +367,11 @@ if __name__ == '__main__':
|
|||||||
exit_code: 0
|
exit_code: 0
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
|
||||||
|
from test import say_hy
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
say_hy("dear Ruff contributor")
|
||||||
|
|
||||||
----- stderr -----
|
----- stderr -----
|
||||||
"###);
|
"###);
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -390,9 +442,9 @@ fn deprecated_options() -> Result<()> {
|
|||||||
let ruff_toml = tempdir.path().join("ruff.toml");
|
let ruff_toml = tempdir.path().join("ruff.toml");
|
||||||
fs::write(
|
fs::write(
|
||||||
&ruff_toml,
|
&ruff_toml,
|
||||||
r#"
|
r"
|
||||||
tab-size = 2
|
tab-size = 2
|
||||||
"#,
|
",
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
insta::with_settings!({filters => vec![
|
insta::with_settings!({filters => vec![
|
||||||
@@ -402,10 +454,10 @@ tab-size = 2
|
|||||||
.args(["format", "--config"])
|
.args(["format", "--config"])
|
||||||
.arg(&ruff_toml)
|
.arg(&ruff_toml)
|
||||||
.arg("-")
|
.arg("-")
|
||||||
.pass_stdin(r#"
|
.pass_stdin(r"
|
||||||
if True:
|
if True:
|
||||||
pass
|
pass
|
||||||
"#), @r###"
|
"), @r###"
|
||||||
success: true
|
success: true
|
||||||
exit_code: 0
|
exit_code: 0
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
@@ -438,9 +490,9 @@ format = "json"
|
|||||||
.args(["check", "--select", "F401", "--no-cache", "--config"])
|
.args(["check", "--select", "F401", "--no-cache", "--config"])
|
||||||
.arg(&ruff_toml)
|
.arg(&ruff_toml)
|
||||||
.arg("-")
|
.arg("-")
|
||||||
.pass_stdin(r#"
|
.pass_stdin(r"
|
||||||
import os
|
import os
|
||||||
"#), @r###"
|
"), @r###"
|
||||||
success: false
|
success: false
|
||||||
exit_code: 2
|
exit_code: 2
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
@@ -813,3 +865,432 @@ fn test_diff_stdin_formatted() {
|
|||||||
----- stderr -----
|
----- stderr -----
|
||||||
"###);
|
"###);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_notebook_trailing_semicolon() {
|
||||||
|
let fixtures = Path::new("resources").join("test").join("fixtures");
|
||||||
|
let unformatted = fs::read(fixtures.join("trailing_semicolon.ipynb")).unwrap();
|
||||||
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||||||
|
.args(["format", "--isolated", "--stdin-filename", "test.ipynb"])
|
||||||
|
.arg("-")
|
||||||
|
.pass_stdin(unformatted), @r###"
|
||||||
|
success: true
|
||||||
|
exit_code: 0
|
||||||
|
----- stdout -----
|
||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 1,
|
||||||
|
"id": "4f8ce941-1492-4d4e-8ab5-70d733fe891a",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"%config ZMQInteractiveShell.ast_node_interactivity=\"last_expr_or_assign\""
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 2,
|
||||||
|
"id": "721ec705-0c65-4bfb-9809-7ed8bc534186",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 2,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"# Assignment statement without a semicolon\n",
|
||||||
|
"x = 1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 3,
|
||||||
|
"id": "de50e495-17e5-41cc-94bd-565757555d7e",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Assignment statement with a semicolon\n",
|
||||||
|
"x = 1\n",
|
||||||
|
"x = 1;"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 4,
|
||||||
|
"id": "39e31201-23da-44eb-8684-41bba3663991",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"2"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 4,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"# Augmented assignment without a semicolon\n",
|
||||||
|
"x += 1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 5,
|
||||||
|
"id": "6b73d3dd-c73a-4697-9e97-e109a6c1fbab",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Augmented assignment without a semicolon\n",
|
||||||
|
"x += 1\n",
|
||||||
|
"x += 1; # comment\n",
|
||||||
|
"# comment"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 6,
|
||||||
|
"id": "2a3e5b86-aa5b-46ba-b9c6-0386d876f58c",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Multiple assignment without a semicolon\n",
|
||||||
|
"x = y = 1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 7,
|
||||||
|
"id": "07f89e51-9357-4cfb-8fc5-76fb75e35949",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Multiple assignment with a semicolon\n",
|
||||||
|
"x = y = 1\n",
|
||||||
|
"x = y = 1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 8,
|
||||||
|
"id": "c22b539d-473e-48f8-a236-625e58c47a00",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Tuple unpacking without a semicolon\n",
|
||||||
|
"x, y = 1, 2"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 9,
|
||||||
|
"id": "12c87940-a0d5-403b-a81c-7507eb06dc7e",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Tuple unpacking with a semicolon (irrelevant)\n",
|
||||||
|
"x, y = 1, 2\n",
|
||||||
|
"x, y = 1, 2 # comment\n",
|
||||||
|
"# comment"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 10,
|
||||||
|
"id": "5a768c76-6bc4-470c-b37e-8cc14bc6caf4",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 10,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"# Annotated assignment statement without a semicolon\n",
|
||||||
|
"x: int = 1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 11,
|
||||||
|
"id": "21bfda82-1a9a-4ba1-9078-74ac480804b5",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Annotated assignment statement without a semicolon\n",
|
||||||
|
"x: int = 1\n",
|
||||||
|
"x: int = 1; # comment\n",
|
||||||
|
"# comment"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 12,
|
||||||
|
"id": "09929999-ff29-4d10-ad2b-e665af15812d",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 12,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"# Assignment expression without a semicolon\n",
|
||||||
|
"(x := 1)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 13,
|
||||||
|
"id": "32a83217-1bad-4f61-855e-ffcdb119c763",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Assignment expression with a semicolon\n",
|
||||||
|
"(x := 1)\n",
|
||||||
|
"(x := 1); # comment\n",
|
||||||
|
"# comment"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 14,
|
||||||
|
"id": "61b81865-277e-4964-b03e-eb78f1f318eb",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 14,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"x = 1\n",
|
||||||
|
"# Expression without a semicolon\n",
|
||||||
|
"x"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 15,
|
||||||
|
"id": "974c29be-67e1-4000-95fa-6ca118a63bad",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"x = 1\n",
|
||||||
|
"# Expression with a semicolon\n",
|
||||||
|
"x;"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 16,
|
||||||
|
"id": "cfeb1757-46d6-4f13-969f-a283b6d0304f",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"class Point:\n",
|
||||||
|
" def __init__(self, x, y):\n",
|
||||||
|
" self.x = x\n",
|
||||||
|
" self.y = y\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"p = Point(0, 0);"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 17,
|
||||||
|
"id": "2ee7f1a5-ccfe-4004-bfa4-ef834a58da97",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Assignment statement where the left is an attribute access doesn't\n",
|
||||||
|
"# print the value.\n",
|
||||||
|
"p.x = 1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 18,
|
||||||
|
"id": "3e49370a-048b-474d-aa0a-3d1d4a73ad37",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"data = {}\n",
|
||||||
|
"\n",
|
||||||
|
"# Neither does the subscript node\n",
|
||||||
|
"data[\"foo\"] = 1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 19,
|
||||||
|
"id": "d594bdd3-eaa9-41ef-8cda-cf01bc273b2d",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"if x := 1:\n",
|
||||||
|
" # It should be the top level statement\n",
|
||||||
|
" x"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 20,
|
||||||
|
"id": "e532f0cf-80c7-42b7-8226-6002fcf74fb6",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 20,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"# Parentheses with comments\n",
|
||||||
|
"(\n",
|
||||||
|
" x := 1 # comment\n",
|
||||||
|
") # comment"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 21,
|
||||||
|
"id": "473c5d62-871b-46ed-8a34-27095243f462",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Parentheses with comments\n",
|
||||||
|
"(\n",
|
||||||
|
" x := 1 # comment\n",
|
||||||
|
"); # comment"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 22,
|
||||||
|
"id": "8c3c2361-f49f-45fe-bbe3-7e27410a8a86",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"'Hello world!'"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 22,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"\"\"\"Hello world!\"\"\""
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 23,
|
||||||
|
"id": "23dbe9b5-3f68-4890-ab2d-ab0dbfd0712a",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"\"\"\"Hello world!\"\"\"; # comment\n",
|
||||||
|
"# comment"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 24,
|
||||||
|
"id": "3ce33108-d95d-4c70-83d1-0d4fd36a2951",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"'x = 1'"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 24,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"x = 1\n",
|
||||||
|
"f\"x = {x}\""
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 25,
|
||||||
|
"id": "654a4a67-de43-4684-824a-9451c67db48f",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"x = 1\n",
|
||||||
|
"f\"x = {x}\"\n",
|
||||||
|
"f\"x = {x}\"; # comment\n",
|
||||||
|
"# comment"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python (ruff-playground)",
|
||||||
|
"language": "python",
|
||||||
|
"name": "ruff-playground"
|
||||||
|
},
|
||||||
|
"language_info": {
|
||||||
|
"codemirror_mode": {
|
||||||
|
"name": "ipython",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"file_extension": ".py",
|
||||||
|
"mimetype": "text/x-python",
|
||||||
|
"name": "python",
|
||||||
|
"nbconvert_exporter": "python",
|
||||||
|
"pygments_lexer": "ipython3",
|
||||||
|
"version": "3.11.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 5
|
||||||
|
}
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
"###);
|
||||||
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -396,3 +396,43 @@ if __name__ == "__main__":
|
|||||||
"###);
|
"###);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Regression test for [#8858](https://github.com/astral-sh/ruff/issues/8858)
|
||||||
|
#[test]
|
||||||
|
fn parent_configuration_override() -> Result<()> {
|
||||||
|
let tempdir = TempDir::new()?;
|
||||||
|
let root_ruff = tempdir.path().join("ruff.toml");
|
||||||
|
fs::write(
|
||||||
|
root_ruff,
|
||||||
|
r#"
|
||||||
|
[lint]
|
||||||
|
select = ["ALL"]
|
||||||
|
"#,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let sub_dir = tempdir.path().join("subdirectory");
|
||||||
|
fs::create_dir(&sub_dir)?;
|
||||||
|
|
||||||
|
let subdirectory_ruff = sub_dir.join("ruff.toml");
|
||||||
|
fs::write(
|
||||||
|
subdirectory_ruff,
|
||||||
|
r#"
|
||||||
|
[lint]
|
||||||
|
ignore = ["D203", "D212"]
|
||||||
|
"#,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||||||
|
.current_dir(sub_dir)
|
||||||
|
.arg("check")
|
||||||
|
.args(STDIN_BASE_OPTIONS)
|
||||||
|
, @r###"
|
||||||
|
success: true
|
||||||
|
exit_code: 0
|
||||||
|
----- stdout -----
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
warning: No Python files found under the given path(s)
|
||||||
|
"###);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|||||||
101
crates/ruff_cli/tests/resolve_files.rs
Normal file
101
crates/ruff_cli/tests/resolve_files.rs
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
#![cfg(not(target_family = "wasm"))]
|
||||||
|
|
||||||
|
use std::path::Path;
|
||||||
|
use std::process::Command;
|
||||||
|
use std::str;
|
||||||
|
|
||||||
|
use insta_cmd::{assert_cmd_snapshot, get_cargo_bin};
|
||||||
|
const BIN_NAME: &str = "ruff";
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "windows"))]
|
||||||
|
const TEST_FILTERS: &[(&str, &str)] = &[(".*/resources/test/fixtures/", "[BASEPATH]/")];
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
const TEST_FILTERS: &[(&str, &str)] = &[
|
||||||
|
(r".*\\resources\\test\\fixtures\\", "[BASEPATH]\\"),
|
||||||
|
(r"\\", "/"),
|
||||||
|
];
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_project_include_defaults() {
|
||||||
|
// Defaults to checking the current working directory
|
||||||
|
//
|
||||||
|
// The test directory includes:
|
||||||
|
// - A pyproject.toml which specifies an include
|
||||||
|
// - A nested pyproject.toml which has a Ruff section
|
||||||
|
//
|
||||||
|
// The nested project should all be checked instead of respecting the parent includes
|
||||||
|
|
||||||
|
insta::with_settings!({
|
||||||
|
filters => TEST_FILTERS.to_vec()
|
||||||
|
}, {
|
||||||
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||||||
|
.args(["check", "--show-files"]).current_dir(Path::new("./resources/test/fixtures/include-test")), @r###"
|
||||||
|
success: true
|
||||||
|
exit_code: 0
|
||||||
|
----- stdout -----
|
||||||
|
[BASEPATH]/include-test/a.py
|
||||||
|
[BASEPATH]/include-test/nested-project/e.py
|
||||||
|
[BASEPATH]/include-test/nested-project/pyproject.toml
|
||||||
|
[BASEPATH]/include-test/subdirectory/c.py
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
"###);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_project_respects_direct_paths() {
|
||||||
|
// Given a direct path not included in the project `includes`, it should be checked
|
||||||
|
|
||||||
|
insta::with_settings!({
|
||||||
|
filters => TEST_FILTERS.to_vec()
|
||||||
|
}, {
|
||||||
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||||||
|
.args(["check", "--show-files", "b.py"]).current_dir(Path::new("./resources/test/fixtures/include-test")), @r###"
|
||||||
|
success: true
|
||||||
|
exit_code: 0
|
||||||
|
----- stdout -----
|
||||||
|
[BASEPATH]/include-test/b.py
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
"###);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_project_respects_subdirectory_includes() {
|
||||||
|
// Given a direct path to a subdirectory, the include should be respected
|
||||||
|
|
||||||
|
insta::with_settings!({
|
||||||
|
filters => TEST_FILTERS.to_vec()
|
||||||
|
}, {
|
||||||
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||||||
|
.args(["check", "--show-files", "subdirectory"]).current_dir(Path::new("./resources/test/fixtures/include-test")), @r###"
|
||||||
|
success: true
|
||||||
|
exit_code: 0
|
||||||
|
----- stdout -----
|
||||||
|
[BASEPATH]/include-test/subdirectory/c.py
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
"###);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_project_from_project_subdirectory_respects_includes() {
|
||||||
|
// Run from a project subdirectory, the include specified in the parent directory should be respected
|
||||||
|
|
||||||
|
insta::with_settings!({
|
||||||
|
filters => TEST_FILTERS.to_vec()
|
||||||
|
}, {
|
||||||
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||||||
|
.args(["check", "--show-files"]).current_dir(Path::new("./resources/test/fixtures/include-test/subdirectory")), @r###"
|
||||||
|
success: true
|
||||||
|
exit_code: 0
|
||||||
|
----- stdout -----
|
||||||
|
[BASEPATH]/include-test/subdirectory/c.py
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
"###);
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -48,9 +48,12 @@ tracing-indicatif = { workspace = true }
|
|||||||
tracing-subscriber = { workspace = true, features = ["env-filter"] }
|
tracing-subscriber = { workspace = true, features = ["env-filter"] }
|
||||||
imara-diff = "0.1.5"
|
imara-diff = "0.1.5"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
indoc = "2.0.4"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
# Turn off rayon for profiling
|
# Turn off rayon for profiling
|
||||||
singlethreaded = []
|
singlethreaded = []
|
||||||
|
|
||||||
[dev-dependencies]
|
[lints]
|
||||||
indoc = "2.0.4"
|
workspace = true
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ pub(crate) fn main(args: &Args) -> Result<()> {
|
|||||||
|
|
||||||
if rule.is_preview() || rule.is_nursery() {
|
if rule.is_preview() || rule.is_nursery() {
|
||||||
output.push_str(
|
output.push_str(
|
||||||
r#"This rule is unstable and in [preview](../preview.md). The `--preview` flag is required for use."#,
|
r"This rule is unstable and in [preview](../preview.md). The `--preview` flag is required for use.",
|
||||||
);
|
);
|
||||||
output.push('\n');
|
output.push('\n');
|
||||||
output.push('\n');
|
output.push('\n');
|
||||||
|
|||||||
@@ -129,12 +129,12 @@ fn emit_field(output: &mut String, name: &str, field: &OptionField, parent_set:
|
|||||||
output.push_str("**Example usage**:\n\n");
|
output.push_str("**Example usage**:\n\n");
|
||||||
output.push_str(&format_tab(
|
output.push_str(&format_tab(
|
||||||
"pyproject.toml",
|
"pyproject.toml",
|
||||||
&format_header(parent_set, ConfigurationFile::PyprojectToml),
|
&format_header(field.scope, parent_set, ConfigurationFile::PyprojectToml),
|
||||||
field.example,
|
field.example,
|
||||||
));
|
));
|
||||||
output.push_str(&format_tab(
|
output.push_str(&format_tab(
|
||||||
"ruff.toml",
|
"ruff.toml",
|
||||||
&format_header(parent_set, ConfigurationFile::RuffToml),
|
&format_header(field.scope, parent_set, ConfigurationFile::RuffToml),
|
||||||
field.example,
|
field.example,
|
||||||
));
|
));
|
||||||
output.push('\n');
|
output.push('\n');
|
||||||
@@ -149,23 +149,53 @@ fn format_tab(tab_name: &str, header: &str, content: &str) -> String {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn format_header(parent_set: &Set, configuration: ConfigurationFile) -> String {
|
/// Format the TOML header for the example usage for a given option.
|
||||||
let fmt = if let Some(set_name) = parent_set.name() {
|
///
|
||||||
if set_name == "format" {
|
/// For example: `[tool.ruff.format]` or `[tool.ruff.lint.isort]`.
|
||||||
String::from(".format")
|
fn format_header(
|
||||||
} else {
|
scope: Option<&str>,
|
||||||
format!(".lint.{set_name}")
|
parent_set: &Set,
|
||||||
}
|
configuration: ConfigurationFile,
|
||||||
} else {
|
) -> String {
|
||||||
String::new()
|
|
||||||
};
|
|
||||||
match configuration {
|
match configuration {
|
||||||
ConfigurationFile::PyprojectToml => format!("[tool.ruff{fmt}]"),
|
ConfigurationFile::PyprojectToml => {
|
||||||
|
let mut header = if let Some(set_name) = parent_set.name() {
|
||||||
|
if set_name == "format" {
|
||||||
|
String::from("tool.ruff.format")
|
||||||
|
} else {
|
||||||
|
format!("tool.ruff.lint.{set_name}")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
"tool.ruff".to_string()
|
||||||
|
};
|
||||||
|
if let Some(scope) = scope {
|
||||||
|
if !header.is_empty() {
|
||||||
|
header.push('.');
|
||||||
|
}
|
||||||
|
header.push_str(scope);
|
||||||
|
}
|
||||||
|
format!("[{header}]")
|
||||||
|
}
|
||||||
ConfigurationFile::RuffToml => {
|
ConfigurationFile::RuffToml => {
|
||||||
if fmt.is_empty() {
|
let mut header = if let Some(set_name) = parent_set.name() {
|
||||||
|
if set_name == "format" {
|
||||||
|
String::from("format")
|
||||||
|
} else {
|
||||||
|
format!("lint.{set_name}")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
String::new()
|
||||||
|
};
|
||||||
|
if let Some(scope) = scope {
|
||||||
|
if !header.is_empty() {
|
||||||
|
header.push('.');
|
||||||
|
}
|
||||||
|
header.push_str(scope);
|
||||||
|
}
|
||||||
|
if header.is_empty() {
|
||||||
String::new()
|
String::new()
|
||||||
} else {
|
} else {
|
||||||
format!("[{}]", fmt.strip_prefix('.').unwrap())
|
format!("[{header}]")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,30 +1,34 @@
|
|||||||
//! Print the AST for a given Python file.
|
//! Print the AST for a given Python file.
|
||||||
#![allow(clippy::print_stdout, clippy::print_stderr)]
|
#![allow(clippy::print_stdout, clippy::print_stderr)]
|
||||||
|
|
||||||
use std::fs;
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use ruff_python_parser::{parse, Mode};
|
|
||||||
|
use ruff_linter::source_kind::SourceKind;
|
||||||
|
use ruff_python_ast::PySourceType;
|
||||||
|
use ruff_python_parser::{parse, AsMode};
|
||||||
|
|
||||||
#[derive(clap::Args)]
|
#[derive(clap::Args)]
|
||||||
pub(crate) struct Args {
|
pub(crate) struct Args {
|
||||||
/// Python file for which to generate the AST.
|
/// Python file for which to generate the AST.
|
||||||
#[arg(required = true)]
|
#[arg(required = true)]
|
||||||
file: PathBuf,
|
file: PathBuf,
|
||||||
/// Run in Jupyter mode i.e., allow line magics.
|
|
||||||
#[arg(long)]
|
|
||||||
jupyter: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn main(args: &Args) -> Result<()> {
|
pub(crate) fn main(args: &Args) -> Result<()> {
|
||||||
let contents = fs::read_to_string(&args.file)?;
|
let source_type = PySourceType::from(&args.file);
|
||||||
let mode = if args.jupyter {
|
let source_kind = SourceKind::from_path(&args.file, source_type)?.ok_or_else(|| {
|
||||||
Mode::Ipython
|
anyhow::anyhow!(
|
||||||
} else {
|
"Could not determine source kind for file: {}",
|
||||||
Mode::Module
|
args.file.display()
|
||||||
};
|
)
|
||||||
let python_ast = parse(&contents, mode, &args.file.to_string_lossy())?;
|
})?;
|
||||||
|
let python_ast = parse(
|
||||||
|
source_kind.source_code(),
|
||||||
|
source_type.as_mode(),
|
||||||
|
&args.file.to_string_lossy(),
|
||||||
|
)?;
|
||||||
println!("{python_ast:#?}");
|
println!("{python_ast:#?}");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,30 +1,30 @@
|
|||||||
//! Print the token stream for a given Python file.
|
//! Print the token stream for a given Python file.
|
||||||
#![allow(clippy::print_stdout, clippy::print_stderr)]
|
#![allow(clippy::print_stdout, clippy::print_stderr)]
|
||||||
|
|
||||||
use std::fs;
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use ruff_python_parser::{lexer, Mode};
|
|
||||||
|
use ruff_linter::source_kind::SourceKind;
|
||||||
|
use ruff_python_ast::PySourceType;
|
||||||
|
use ruff_python_parser::{lexer, AsMode};
|
||||||
|
|
||||||
#[derive(clap::Args)]
|
#[derive(clap::Args)]
|
||||||
pub(crate) struct Args {
|
pub(crate) struct Args {
|
||||||
/// Python file for which to generate the AST.
|
/// Python file for which to generate the AST.
|
||||||
#[arg(required = true)]
|
#[arg(required = true)]
|
||||||
file: PathBuf,
|
file: PathBuf,
|
||||||
/// Run in Jupyter mode i.e., allow line magics (`%`, `!`, `?`, `/`, `,`, `;`).
|
|
||||||
#[arg(long)]
|
|
||||||
jupyter: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn main(args: &Args) -> Result<()> {
|
pub(crate) fn main(args: &Args) -> Result<()> {
|
||||||
let contents = fs::read_to_string(&args.file)?;
|
let source_type = PySourceType::from(&args.file);
|
||||||
let mode = if args.jupyter {
|
let source_kind = SourceKind::from_path(&args.file, source_type)?.ok_or_else(|| {
|
||||||
Mode::Ipython
|
anyhow::anyhow!(
|
||||||
} else {
|
"Could not determine source kind for file: {}",
|
||||||
Mode::Module
|
args.file.display()
|
||||||
};
|
)
|
||||||
for (tok, range) in lexer::lex(&contents, mode).flatten() {
|
})?;
|
||||||
|
for (tok, range) in lexer::lex(source_kind.source_code(), source_type.as_mode()).flatten() {
|
||||||
println!(
|
println!(
|
||||||
"{start:#?} {tok:#?} {end:#?}",
|
"{start:#?} {tok:#?} {end:#?}",
|
||||||
start = range.start(),
|
start = range.start(),
|
||||||
|
|||||||
@@ -29,3 +29,6 @@ insta = { workspace = true }
|
|||||||
[features]
|
[features]
|
||||||
serde = ["dep:serde", "ruff_text_size/serde"]
|
serde = ["dep:serde", "ruff_text_size/serde"]
|
||||||
schemars = ["dep:schemars", "ruff_text_size/schemars"]
|
schemars = ["dep:schemars", "ruff_text_size/schemars"]
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|||||||
@@ -1,23 +1,9 @@
|
|||||||
use super::{Buffer, Format, Formatter};
|
use super::{Buffer, Format, Formatter};
|
||||||
use crate::FormatResult;
|
use crate::FormatResult;
|
||||||
use std::ffi::c_void;
|
|
||||||
use std::marker::PhantomData;
|
|
||||||
|
|
||||||
/// Mono-morphed type to format an object. Used by the [`crate::format`!], [`crate::format_args`!], and
|
/// A convenience wrapper for representing a formattable argument.
|
||||||
/// [`crate::write`!] macros.
|
|
||||||
///
|
|
||||||
/// This struct is similar to a dynamic dispatch (using `dyn Format`) because it stores a pointer to the value.
|
|
||||||
/// However, it doesn't store the pointer to `dyn Format`'s vtable, instead it statically resolves the function
|
|
||||||
/// pointer of `Format::format` and stores it in `formatter`.
|
|
||||||
pub struct Argument<'fmt, Context> {
|
pub struct Argument<'fmt, Context> {
|
||||||
/// The value to format stored as a raw pointer where `lifetime` stores the value's lifetime.
|
value: &'fmt dyn Format<Context>,
|
||||||
value: *const c_void,
|
|
||||||
|
|
||||||
/// Stores the lifetime of the value. To get the most out of our dear borrow checker.
|
|
||||||
lifetime: PhantomData<&'fmt ()>,
|
|
||||||
|
|
||||||
/// The function pointer to `value`'s `Format::format` method
|
|
||||||
formatter: fn(*const c_void, &mut Formatter<'_, Context>) -> FormatResult<()>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Context> Clone for Argument<'_, Context> {
|
impl<Context> Clone for Argument<'_, Context> {
|
||||||
@@ -28,32 +14,19 @@ impl<Context> Clone for Argument<'_, Context> {
|
|||||||
impl<Context> Copy for Argument<'_, Context> {}
|
impl<Context> Copy for Argument<'_, Context> {}
|
||||||
|
|
||||||
impl<'fmt, Context> Argument<'fmt, Context> {
|
impl<'fmt, Context> Argument<'fmt, Context> {
|
||||||
/// Called by the [ruff_formatter::format_args] macro. Creates a mono-morphed value for formatting
|
/// Called by the [ruff_formatter::format_args] macro.
|
||||||
/// an object.
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new<F: Format<Context>>(value: &'fmt F) -> Self {
|
pub fn new<F: Format<Context>>(value: &'fmt F) -> Self {
|
||||||
#[inline]
|
Self { value }
|
||||||
fn formatter<F: Format<Context>, Context>(
|
|
||||||
ptr: *const c_void,
|
|
||||||
fmt: &mut Formatter<Context>,
|
|
||||||
) -> FormatResult<()> {
|
|
||||||
// SAFETY: Safe because the 'fmt lifetime is captured by the 'lifetime' field.
|
|
||||||
#[allow(unsafe_code)]
|
|
||||||
F::fmt(unsafe { &*ptr.cast::<F>() }, fmt)
|
|
||||||
}
|
|
||||||
|
|
||||||
Self {
|
|
||||||
value: (value as *const F).cast::<std::ffi::c_void>(),
|
|
||||||
lifetime: PhantomData,
|
|
||||||
formatter: formatter::<F, Context>,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Formats the value stored by this argument using the given formatter.
|
/// Formats the value stored by this argument using the given formatter.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
// Seems to only be triggered on wasm32 and looks like a false positive?
|
||||||
|
#[allow(clippy::trivially_copy_pass_by_ref)]
|
||||||
pub(super) fn format(&self, f: &mut Formatter<Context>) -> FormatResult<()> {
|
pub(super) fn format(&self, f: &mut Formatter<Context>) -> FormatResult<()> {
|
||||||
(self.formatter)(self.value, f)
|
self.value.fmt(f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2555,17 +2555,17 @@ pub struct BestFitting<'a, Context> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Context> BestFitting<'a, Context> {
|
impl<'a, Context> BestFitting<'a, Context> {
|
||||||
/// Creates a new best fitting IR with the given variants. The method itself isn't unsafe
|
/// Creates a new best fitting IR with the given variants.
|
||||||
/// but it is to discourage people from using it because the printer will panic if
|
///
|
||||||
/// the slice doesn't contain at least the least and most expanded variants.
|
/// Callers are required to ensure that the number of variants given
|
||||||
|
/// is at least 2.
|
||||||
///
|
///
|
||||||
/// You're looking for a way to create a `BestFitting` object, use the `best_fitting![least_expanded, most_expanded]` macro.
|
/// You're looking for a way to create a `BestFitting` object, use the `best_fitting![least_expanded, most_expanded]` macro.
|
||||||
///
|
///
|
||||||
/// ## Safety
|
/// # Panics
|
||||||
|
///
|
||||||
/// The slice must contain at least two variants.
|
/// When the slice contains less than two variants.
|
||||||
#[allow(unsafe_code)]
|
pub fn from_arguments_unchecked(variants: Arguments<'a, Context>) -> Self {
|
||||||
pub unsafe fn from_arguments_unchecked(variants: Arguments<'a, Context>) -> Self {
|
|
||||||
assert!(
|
assert!(
|
||||||
variants.0.len() >= 2,
|
variants.0.len() >= 2,
|
||||||
"Requires at least the least expanded and most expanded variants"
|
"Requires at least the least expanded and most expanded variants"
|
||||||
@@ -2696,14 +2696,12 @@ impl<Context> Format<Context> for BestFitting<'_, Context> {
|
|||||||
buffer.write_element(FormatElement::Tag(EndBestFittingEntry));
|
buffer.write_element(FormatElement::Tag(EndBestFittingEntry));
|
||||||
}
|
}
|
||||||
|
|
||||||
// SAFETY: The constructor guarantees that there are always at least two variants. It's, therefore,
|
// OK because the constructor guarantees that there are always at
|
||||||
// safe to call into the unsafe `from_vec_unchecked` function
|
// least two variants.
|
||||||
#[allow(unsafe_code)]
|
let variants = BestFittingVariants::from_vec_unchecked(buffer.into_vec());
|
||||||
let element = unsafe {
|
let element = FormatElement::BestFitting {
|
||||||
FormatElement::BestFitting {
|
variants,
|
||||||
variants: BestFittingVariants::from_vec_unchecked(buffer.into_vec()),
|
mode: self.mode,
|
||||||
mode: self.mode,
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
f.write_element(element);
|
f.write_element(element);
|
||||||
|
|||||||
@@ -332,17 +332,14 @@ pub enum BestFittingMode {
|
|||||||
pub struct BestFittingVariants(Box<[FormatElement]>);
|
pub struct BestFittingVariants(Box<[FormatElement]>);
|
||||||
|
|
||||||
impl BestFittingVariants {
|
impl BestFittingVariants {
|
||||||
/// Creates a new best fitting IR with the given variants. The method itself isn't unsafe
|
/// Creates a new best fitting IR with the given variants.
|
||||||
/// but it is to discourage people from using it because the printer will panic if
|
///
|
||||||
/// the slice doesn't contain at least the least and most expanded variants.
|
/// Callers are required to ensure that the number of variants given
|
||||||
|
/// is at least 2 when using `most_expanded` or `most_flag`.
|
||||||
///
|
///
|
||||||
/// You're looking for a way to create a `BestFitting` object, use the `best_fitting![least_expanded, most_expanded]` macro.
|
/// You're looking for a way to create a `BestFitting` object, use the `best_fitting![least_expanded, most_expanded]` macro.
|
||||||
///
|
|
||||||
/// ## Safety
|
|
||||||
/// The slice must contain at least two variants.
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[allow(unsafe_code)]
|
pub fn from_vec_unchecked(variants: Vec<FormatElement>) -> Self {
|
||||||
pub unsafe fn from_vec_unchecked(variants: Vec<FormatElement>) -> Self {
|
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
variants
|
variants
|
||||||
.iter()
|
.iter()
|
||||||
@@ -351,12 +348,23 @@ impl BestFittingVariants {
|
|||||||
>= 2,
|
>= 2,
|
||||||
"Requires at least the least expanded and most expanded variants"
|
"Requires at least the least expanded and most expanded variants"
|
||||||
);
|
);
|
||||||
|
|
||||||
Self(variants.into_boxed_slice())
|
Self(variants.into_boxed_slice())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the most expanded variant
|
/// Returns the most expanded variant
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// When the number of variants is less than two.
|
||||||
pub fn most_expanded(&self) -> &[FormatElement] {
|
pub fn most_expanded(&self) -> &[FormatElement] {
|
||||||
|
assert!(
|
||||||
|
self.as_slice()
|
||||||
|
.iter()
|
||||||
|
.filter(|element| matches!(element, FormatElement::Tag(Tag::StartBestFittingEntry)))
|
||||||
|
.count()
|
||||||
|
>= 2,
|
||||||
|
"Requires at least the least expanded and most expanded variants"
|
||||||
|
);
|
||||||
self.into_iter().last().unwrap()
|
self.into_iter().last().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -365,7 +373,19 @@ impl BestFittingVariants {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the least expanded variant
|
/// Returns the least expanded variant
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// When the number of variants is less than two.
|
||||||
pub fn most_flat(&self) -> &[FormatElement] {
|
pub fn most_flat(&self) -> &[FormatElement] {
|
||||||
|
assert!(
|
||||||
|
self.as_slice()
|
||||||
|
.iter()
|
||||||
|
.filter(|element| matches!(element, FormatElement::Tag(Tag::StartBestFittingEntry)))
|
||||||
|
.count()
|
||||||
|
>= 2,
|
||||||
|
"Requires at least the least expanded and most expanded variants"
|
||||||
|
);
|
||||||
self.into_iter().next().unwrap()
|
self.into_iter().next().unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -329,10 +329,8 @@ macro_rules! format {
|
|||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! best_fitting {
|
macro_rules! best_fitting {
|
||||||
($least_expanded:expr, $($tail:expr),+ $(,)?) => {{
|
($least_expanded:expr, $($tail:expr),+ $(,)?) => {{
|
||||||
#[allow(unsafe_code)]
|
// OK because the macro syntax requires at least two variants.
|
||||||
unsafe {
|
$crate::BestFitting::from_arguments_unchecked($crate::format_args!($least_expanded, $($tail),+))
|
||||||
$crate::BestFitting::from_arguments_unchecked($crate::format_args!($least_expanded, $($tail),+))
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1711,14 +1711,14 @@ mod tests {
|
|||||||
));
|
));
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
r#"a
|
"a
|
||||||
b
|
b
|
||||||
c
|
c
|
||||||
d
|
d
|
||||||
d
|
d
|
||||||
c
|
c
|
||||||
b
|
b
|
||||||
a"#,
|
a",
|
||||||
formatted.as_code()
|
formatted.as_code()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -2047,10 +2047,10 @@ two lines`,
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
printed.as_code(),
|
printed.as_code(),
|
||||||
r#"Group with id-2
|
"Group with id-2
|
||||||
Group with id-1 does not fit on the line because it exceeds the line width of 80 characters by
|
Group with id-1 does not fit on the line because it exceeds the line width of 80 characters by
|
||||||
Group 2 fits
|
Group 2 fits
|
||||||
Group 1 breaks"#
|
Group 1 breaks"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,3 +17,6 @@ ruff_macros = { path = "../ruff_macros" }
|
|||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
static_assertions = "1.1.0"
|
static_assertions = "1.1.0"
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "ruff_linter"
|
name = "ruff_linter"
|
||||||
version = "0.1.5"
|
version = "0.1.7"
|
||||||
publish = false
|
publish = false
|
||||||
authors = { workspace = true }
|
authors = { workspace = true }
|
||||||
edition = { workspace = true }
|
edition = { workspace = true }
|
||||||
@@ -30,7 +30,7 @@ ruff_source_file = { path = "../ruff_source_file", features = ["serde"] }
|
|||||||
ruff_text_size = { path = "../ruff_text_size" }
|
ruff_text_size = { path = "../ruff_text_size" }
|
||||||
|
|
||||||
aho-corasick = { version = "1.1.2" }
|
aho-corasick = { version = "1.1.2" }
|
||||||
annotate-snippets = { version = "0.9.1", features = ["color"] }
|
annotate-snippets = { version = "0.9.2", features = ["color"] }
|
||||||
anyhow = { workspace = true }
|
anyhow = { workspace = true }
|
||||||
bitflags = { workspace = true }
|
bitflags = { workspace = true }
|
||||||
chrono = { workspace = true }
|
chrono = { workspace = true }
|
||||||
@@ -53,8 +53,8 @@ path-absolutize = { workspace = true, features = [
|
|||||||
] }
|
] }
|
||||||
pathdiff = { version = "0.2.1" }
|
pathdiff = { version = "0.2.1" }
|
||||||
pep440_rs = { version = "0.3.12", features = ["serde"] }
|
pep440_rs = { version = "0.3.12", features = ["serde"] }
|
||||||
pyproject-toml = { version = "0.8.0" }
|
pyproject-toml = { version = "0.8.1" }
|
||||||
quick-junit = { version = "0.3.2" }
|
quick-junit = { version = "0.3.5" }
|
||||||
regex = { workspace = true }
|
regex = { workspace = true }
|
||||||
result-like = { version = "0.4.6" }
|
result-like = { version = "0.4.6" }
|
||||||
rustc-hash = { workspace = true }
|
rustc-hash = { workspace = true }
|
||||||
@@ -86,3 +86,6 @@ default = []
|
|||||||
schemars = ["dep:schemars"]
|
schemars = ["dep:schemars"]
|
||||||
# Enables the UnreachableCode rule
|
# Enables the UnreachableCode rule
|
||||||
unreachable-code = []
|
unreachable-code = []
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
# fixtures
|
|
||||||
|
|
||||||
Fixture files used for snapshot testing.
|
|
||||||
@@ -39,3 +39,18 @@ def func():
|
|||||||
for i in range(1110):
|
for i in range(1110):
|
||||||
if True:
|
if True:
|
||||||
break
|
break
|
||||||
|
|
||||||
|
# TODO(charlie): The `pass` here does not get properly redirected to the top of the
|
||||||
|
# loop, unlike below.
|
||||||
|
def func():
|
||||||
|
for i in range(5):
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
return 1
|
||||||
|
|
||||||
|
def func():
|
||||||
|
for i in range(5):
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
return 1
|
||||||
|
x = 1
|
||||||
|
|||||||
@@ -129,3 +129,11 @@ def func():
|
|||||||
print("Grass is green")
|
print("Grass is green")
|
||||||
case Color.BLUE:
|
case Color.BLUE:
|
||||||
print("I'm feeling the blues :(")
|
print("I'm feeling the blues :(")
|
||||||
|
|
||||||
|
|
||||||
|
def func(point):
|
||||||
|
match point:
|
||||||
|
case (0, 0):
|
||||||
|
print("Origin")
|
||||||
|
case foo:
|
||||||
|
raise ValueError("oops")
|
||||||
|
|||||||
184
crates/ruff_linter/resources/test/fixtures/flake8_annotations/auto_return_type.py
vendored
Normal file
184
crates/ruff_linter/resources/test/fixtures/flake8_annotations/auto_return_type.py
vendored
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
def func():
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
def func():
|
||||||
|
return 1.5
|
||||||
|
|
||||||
|
|
||||||
|
def func(x: int):
|
||||||
|
if x > 0:
|
||||||
|
return 1
|
||||||
|
else:
|
||||||
|
return 1.5
|
||||||
|
|
||||||
|
|
||||||
|
def func():
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def func(x: int):
|
||||||
|
if x > 0:
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def func(x: int):
|
||||||
|
return 1 or 2.5 if x > 0 else 1.5 or "str"
|
||||||
|
|
||||||
|
|
||||||
|
def func(x: int):
|
||||||
|
return 1 + 2.5 if x > 0 else 1.5 or "str"
|
||||||
|
|
||||||
|
|
||||||
|
def func(x: int):
|
||||||
|
if not x:
|
||||||
|
return None
|
||||||
|
return {"foo": 1}
|
||||||
|
|
||||||
|
|
||||||
|
def func(x: int):
|
||||||
|
return {"foo": 1}
|
||||||
|
|
||||||
|
|
||||||
|
def func(x: int):
|
||||||
|
if not x:
|
||||||
|
return 1
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def func(x: int):
|
||||||
|
if not x:
|
||||||
|
return 1
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def func(x: int):
|
||||||
|
if not x:
|
||||||
|
return 1
|
||||||
|
elif x > 5:
|
||||||
|
return "str"
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def func(x: int):
|
||||||
|
if x:
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
def func():
|
||||||
|
x = 1
|
||||||
|
|
||||||
|
|
||||||
|
def func(x: int):
|
||||||
|
if x > 0:
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
def func(x: int):
|
||||||
|
match x:
|
||||||
|
case [1, 2, 3]:
|
||||||
|
return 1
|
||||||
|
case 4 as y:
|
||||||
|
return "foo"
|
||||||
|
|
||||||
|
|
||||||
|
def func(x: int):
|
||||||
|
for i in range(5):
|
||||||
|
if i > 0:
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
def func(x: int):
|
||||||
|
for i in range(5):
|
||||||
|
if i > 0:
|
||||||
|
return 1
|
||||||
|
else:
|
||||||
|
return 4
|
||||||
|
|
||||||
|
|
||||||
|
def func(x: int):
|
||||||
|
for i in range(5):
|
||||||
|
if i > 0:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
return 4
|
||||||
|
|
||||||
|
|
||||||
|
def func(x: int):
|
||||||
|
try:
|
||||||
|
pass
|
||||||
|
except:
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
def func(x: int):
|
||||||
|
try:
|
||||||
|
pass
|
||||||
|
except:
|
||||||
|
return 1
|
||||||
|
finally:
|
||||||
|
return 2
|
||||||
|
|
||||||
|
|
||||||
|
def func(x: int):
|
||||||
|
try:
|
||||||
|
pass
|
||||||
|
except:
|
||||||
|
return 1
|
||||||
|
else:
|
||||||
|
return 2
|
||||||
|
|
||||||
|
|
||||||
|
def func(x: int):
|
||||||
|
try:
|
||||||
|
return 1
|
||||||
|
except:
|
||||||
|
return 2
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def func(x: int):
|
||||||
|
while x > 0:
|
||||||
|
break
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
import abc
|
||||||
|
from abc import abstractmethod
|
||||||
|
|
||||||
|
|
||||||
|
class Foo(abc.ABC):
|
||||||
|
@abstractmethod
|
||||||
|
def method(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def method(self):
|
||||||
|
"""Docstring."""
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def method(self):
|
||||||
|
...
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
@abstractmethod
|
||||||
|
def method():
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@abstractmethod
|
||||||
|
def method(cls):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def method(self):
|
||||||
|
if self.x > 0:
|
||||||
|
return 1
|
||||||
|
else:
|
||||||
|
return 1.5
|
||||||
65
crates/ruff_linter/resources/test/fixtures/flake8_bandit/S202.py
vendored
Normal file
65
crates/ruff_linter/resources/test/fixtures/flake8_bandit/S202.py
vendored
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
import sys
|
||||||
|
import tarfile
|
||||||
|
import tempfile
|
||||||
|
|
||||||
|
|
||||||
|
def unsafe_archive_handler(filename):
|
||||||
|
tar = tarfile.open(filename)
|
||||||
|
tar.extractall(path=tempfile.mkdtemp())
|
||||||
|
tar.close()
|
||||||
|
|
||||||
|
|
||||||
|
def managed_members_archive_handler(filename):
|
||||||
|
tar = tarfile.open(filename)
|
||||||
|
tar.extractall(path=tempfile.mkdtemp(), members=members_filter(tar))
|
||||||
|
tar.close()
|
||||||
|
|
||||||
|
|
||||||
|
def list_members_archive_handler(filename):
|
||||||
|
tar = tarfile.open(filename)
|
||||||
|
tar.extractall(path=tempfile.mkdtemp(), members=[])
|
||||||
|
tar.close()
|
||||||
|
|
||||||
|
|
||||||
|
def provided_members_archive_handler(filename):
|
||||||
|
tar = tarfile.open(filename)
|
||||||
|
tarfile.extractall(path=tempfile.mkdtemp(), members=tar)
|
||||||
|
tar.close()
|
||||||
|
|
||||||
|
|
||||||
|
def filter_data(filename):
|
||||||
|
tar = tarfile.open(filename)
|
||||||
|
tarfile.extractall(path=tempfile.mkdtemp(), filter="data")
|
||||||
|
tar.close()
|
||||||
|
|
||||||
|
|
||||||
|
def filter_fully_trusted(filename):
|
||||||
|
tar = tarfile.open(filename)
|
||||||
|
tarfile.extractall(path=tempfile.mkdtemp(), filter="fully_trusted")
|
||||||
|
tar.close()
|
||||||
|
|
||||||
|
|
||||||
|
def filter_tar(filename):
|
||||||
|
tar = tarfile.open(filename)
|
||||||
|
tarfile.extractall(path=tempfile.mkdtemp(), filter="tar")
|
||||||
|
tar.close()
|
||||||
|
|
||||||
|
|
||||||
|
def members_filter(tarfile):
|
||||||
|
result = []
|
||||||
|
for member in tarfile.getmembers():
|
||||||
|
if '../' in member.name:
|
||||||
|
print('Member name container directory traversal sequence')
|
||||||
|
continue
|
||||||
|
elif (member.issym() or member.islnk()) and ('../' in member.linkname):
|
||||||
|
print('Symlink to external resource')
|
||||||
|
continue
|
||||||
|
result.append(member)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
if len(sys.argv) > 1:
|
||||||
|
filename = sys.argv[1]
|
||||||
|
unsafe_archive_handler(filename)
|
||||||
|
managed_members_archive_handler(filename)
|
||||||
13
crates/ruff_linter/resources/test/fixtures/flake8_bandit/S611.py
vendored
Normal file
13
crates/ruff_linter/resources/test/fixtures/flake8_bandit/S611.py
vendored
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
from django.db.models.expressions import RawSQL
|
||||||
|
from django.contrib.auth.models import User
|
||||||
|
|
||||||
|
User.objects.annotate(val=RawSQL('secure', []))
|
||||||
|
User.objects.annotate(val=RawSQL('%secure' % 'nos', []))
|
||||||
|
User.objects.annotate(val=RawSQL('{}secure'.format('no'), []))
|
||||||
|
raw = '"username") AS "val" FROM "auth_user" WHERE "username"="admin" --'
|
||||||
|
User.objects.annotate(val=RawSQL(raw, []))
|
||||||
|
raw = '"username") AS "val" FROM "auth_user"' \
|
||||||
|
' WHERE "username"="admin" OR 1=%s --'
|
||||||
|
User.objects.annotate(val=RawSQL(raw, [0]))
|
||||||
|
User.objects.annotate(val=RawSQL(sql='{}secure'.format('no'), params=[]))
|
||||||
|
User.objects.annotate(val=RawSQL(params=[], sql='{}secure'.format('no')))
|
||||||
@@ -91,3 +91,26 @@ class Registry:
|
|||||||
|
|
||||||
def foo(self) -> None:
|
def foo(self) -> None:
|
||||||
object.__setattr__(self, "flag", True)
|
object.__setattr__(self, "flag", True)
|
||||||
|
|
||||||
|
|
||||||
|
from typing import Optional, Union
|
||||||
|
|
||||||
|
|
||||||
|
def func(x: Union[list, Optional[int | str | float | bool]]):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def func(x: bool | str):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def func(x: int | str):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
from typing import override
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
def func(x: bool):
|
||||||
|
pass
|
||||||
|
|||||||
149
crates/ruff_linter/resources/test/fixtures/flake8_bugbear/B015.ipynb
vendored
Normal file
149
crates/ruff_linter/resources/test/fixtures/flake8_bugbear/B015.ipynb
vendored
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 1,
|
||||||
|
"id": "33faf7ad-a3fd-4ac4-a0c3-52e507ed49df",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"x = 1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 2,
|
||||||
|
"id": "481fb4bf-c1b9-47da-927f-3cfdfe4b49ec",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"True"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 2,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"# Simple case\n",
|
||||||
|
"x == 1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 3,
|
||||||
|
"id": "2f0c65a5-0a0e-4080-afce-5a8ed0d706df",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"True"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 3,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"# Only skip the last expression\n",
|
||||||
|
"x == 1 # B018\n",
|
||||||
|
"x == 1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 4,
|
||||||
|
"id": "5a3fd75d-26d9-44f7-b013-1684aabfd0ae",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Nested expressions isn't relevant\n",
|
||||||
|
"if True:\n",
|
||||||
|
" x == 1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 5,
|
||||||
|
"id": "e00e1afa-b76c-4774-be2a-7223641579e4",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Semicolons shouldn't affect the output\n",
|
||||||
|
"x == 1;"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 6,
|
||||||
|
"id": "05eab5b9-e2ba-4954-8ef3-b035a79573fe",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"True"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 6,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"# Semicolons with multiple expressions\n",
|
||||||
|
"x == 1; x == 1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 7,
|
||||||
|
"id": "9cbbddc5-83fc-4fdb-81ab-53a3912ae898",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"True"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 7,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"# Comments, newlines and whitespace\n",
|
||||||
|
"x == 1 # comment\n",
|
||||||
|
"\n",
|
||||||
|
"# another comment"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python (ruff-playground)",
|
||||||
|
"language": "python",
|
||||||
|
"name": "ruff-playground"
|
||||||
|
},
|
||||||
|
"language_info": {
|
||||||
|
"codemirror_mode": {
|
||||||
|
"name": "ipython",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"file_extension": ".py",
|
||||||
|
"mimetype": "text/x-python",
|
||||||
|
"name": "python",
|
||||||
|
"nbconvert_exporter": "python",
|
||||||
|
"pygments_lexer": "ipython3",
|
||||||
|
"version": "3.11.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 5
|
||||||
|
}
|
||||||
149
crates/ruff_linter/resources/test/fixtures/flake8_bugbear/B018.ipynb
vendored
Normal file
149
crates/ruff_linter/resources/test/fixtures/flake8_bugbear/B018.ipynb
vendored
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 1,
|
||||||
|
"id": "33faf7ad-a3fd-4ac4-a0c3-52e507ed49df",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"x = 1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 2,
|
||||||
|
"id": "481fb4bf-c1b9-47da-927f-3cfdfe4b49ec",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 2,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"# Simple case\n",
|
||||||
|
"x"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 3,
|
||||||
|
"id": "2f0c65a5-0a0e-4080-afce-5a8ed0d706df",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 3,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"# Only skip the last expression\n",
|
||||||
|
"x # B018\n",
|
||||||
|
"x"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 4,
|
||||||
|
"id": "5a3fd75d-26d9-44f7-b013-1684aabfd0ae",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Nested expressions isn't relevant\n",
|
||||||
|
"if True:\n",
|
||||||
|
" x"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 5,
|
||||||
|
"id": "e00e1afa-b76c-4774-be2a-7223641579e4",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Semicolons shouldn't affect the output\n",
|
||||||
|
"x;"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 6,
|
||||||
|
"id": "05eab5b9-e2ba-4954-8ef3-b035a79573fe",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 6,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"# Semicolons with multiple expressions\n",
|
||||||
|
"x; x"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 7,
|
||||||
|
"id": "9cbbddc5-83fc-4fdb-81ab-53a3912ae898",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 7,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"# Comments, newlines and whitespace\n",
|
||||||
|
"x # comment\n",
|
||||||
|
"\n",
|
||||||
|
"# another comment"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python (ruff-playground)",
|
||||||
|
"language": "python",
|
||||||
|
"name": "ruff-playground"
|
||||||
|
},
|
||||||
|
"language_info": {
|
||||||
|
"codemirror_mode": {
|
||||||
|
"name": "ipython",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"file_extension": ".py",
|
||||||
|
"mimetype": "text/x-python",
|
||||||
|
"name": "python",
|
||||||
|
"nbconvert_exporter": "python",
|
||||||
|
"pygments_lexer": "ipython3",
|
||||||
|
"version": "3.11.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 5
|
||||||
|
}
|
||||||
@@ -639,3 +639,18 @@ foo = namedtuple(
|
|||||||
:20
|
:20
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# F-strings
|
||||||
|
kwargs.pop("remove", f"this {trailing_comma}",)
|
||||||
|
|
||||||
|
raise Exception(
|
||||||
|
"first", extra=f"Add trailing comma here ->"
|
||||||
|
)
|
||||||
|
|
||||||
|
assert False, f"<- This is not a trailing comma"
|
||||||
|
|
||||||
|
f"""This is a test. {
|
||||||
|
"Another sentence."
|
||||||
|
if True else
|
||||||
|
"Don't add a trailing comma here ->"
|
||||||
|
}"""
|
||||||
|
|||||||
@@ -148,3 +148,62 @@ for i in range(10):
|
|||||||
for i in range(10):
|
for i in range(10):
|
||||||
pass # comment
|
pass # comment
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def foo():
|
||||||
|
print("foo")
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
def foo():
|
||||||
|
"""A docstring."""
|
||||||
|
print("foo")
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
for i in range(10):
|
||||||
|
...
|
||||||
|
...
|
||||||
|
|
||||||
|
for i in range(10):
|
||||||
|
...
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
for i in range(10):
|
||||||
|
... # comment
|
||||||
|
...
|
||||||
|
|
||||||
|
for i in range(10):
|
||||||
|
...
|
||||||
|
pass
|
||||||
|
|
||||||
|
from typing import Protocol
|
||||||
|
|
||||||
|
|
||||||
|
class Repro(Protocol):
|
||||||
|
def func(self) -> str:
|
||||||
|
"""Docstring"""
|
||||||
|
...
|
||||||
|
|
||||||
|
def impl(self) -> str:
|
||||||
|
"""Docstring"""
|
||||||
|
return self.func()
|
||||||
|
|
||||||
|
|
||||||
|
import abc
|
||||||
|
|
||||||
|
|
||||||
|
class Repro:
|
||||||
|
@abc.abstractmethod
|
||||||
|
def func(self) -> str:
|
||||||
|
"""Docstring"""
|
||||||
|
...
|
||||||
|
|
||||||
|
def impl(self) -> str:
|
||||||
|
"""Docstring"""
|
||||||
|
return self.func()
|
||||||
|
|
||||||
|
def stub(self) -> str:
|
||||||
|
"""Docstring"""
|
||||||
|
...
|
||||||
|
|||||||
@@ -38,3 +38,15 @@ class User:
|
|||||||
foo: bool = BooleanField()
|
foo: bool = BooleanField()
|
||||||
# ...
|
# ...
|
||||||
bar = StringField() # PIE794
|
bar = StringField() # PIE794
|
||||||
|
|
||||||
|
|
||||||
|
class Person:
|
||||||
|
name = "Foo"
|
||||||
|
name = name + " Bar"
|
||||||
|
name = "Bar" # PIE794
|
||||||
|
|
||||||
|
|
||||||
|
class Person:
|
||||||
|
name: str = "Foo"
|
||||||
|
name: str = name + " Bar"
|
||||||
|
name: str = "Bar" # PIE794
|
||||||
|
|||||||
@@ -64,3 +64,9 @@ class FakeEnum10(enum.Enum):
|
|||||||
A = enum.auto()
|
A = enum.auto()
|
||||||
B = enum.auto()
|
B = enum.auto()
|
||||||
C = enum.auto()
|
C = enum.auto()
|
||||||
|
|
||||||
|
|
||||||
|
class FakeEnum10(enum.Enum):
|
||||||
|
A = ...
|
||||||
|
B = ... # PIE796
|
||||||
|
C = ... # PIE796
|
||||||
|
|||||||
7
crates/ruff_linter/resources/test/fixtures/flake8_pie/PIE796.pyi
vendored
Normal file
7
crates/ruff_linter/resources/test/fixtures/flake8_pie/PIE796.pyi
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import enum
|
||||||
|
|
||||||
|
|
||||||
|
class FakeEnum1(enum.Enum):
|
||||||
|
A = ...
|
||||||
|
B = ...
|
||||||
|
C = ...
|
||||||
@@ -1,9 +1,21 @@
|
|||||||
{"foo": 1, **{"bar": 1}} # PIE800
|
{"foo": 1, **{"bar": 1}} # PIE800
|
||||||
|
|
||||||
|
{**{"bar": 10}, "a": "b"} # PIE800
|
||||||
|
|
||||||
foo({**foo, **{"bar": True}}) # PIE800
|
foo({**foo, **{"bar": True}}) # PIE800
|
||||||
|
|
||||||
{**foo, **{"bar": 10}} # PIE800
|
{**foo, **{"bar": 10}} # PIE800
|
||||||
|
|
||||||
|
{ # PIE800
|
||||||
|
"a": "b",
|
||||||
|
# Preserve
|
||||||
|
**{
|
||||||
|
# all
|
||||||
|
"bar": 10, # the
|
||||||
|
# comments
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
{**foo, **buzz, **{bar: 10}} # PIE800
|
{**foo, **buzz, **{bar: 10}} # PIE800
|
||||||
|
|
||||||
{**foo, "bar": True } # OK
|
{**foo, "bar": True } # OK
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ Foo.objects.create(**{**bar}) # PIE804
|
|||||||
|
|
||||||
foo(**{})
|
foo(**{})
|
||||||
|
|
||||||
|
|
||||||
foo(**{**data, "foo": "buzz"})
|
foo(**{**data, "foo": "buzz"})
|
||||||
foo(**buzz)
|
foo(**buzz)
|
||||||
foo(**{"bar-foo": True})
|
foo(**{"bar-foo": True})
|
||||||
@@ -20,3 +19,5 @@ foo(**{buzz: True})
|
|||||||
foo(**{"": True})
|
foo(**{"": True})
|
||||||
foo(**{f"buzz__{bar}": True})
|
foo(**{f"buzz__{bar}": True})
|
||||||
abc(**{"for": 3})
|
abc(**{"for": 3})
|
||||||
|
|
||||||
|
foo(**{},)
|
||||||
|
|||||||
@@ -1,27 +1,37 @@
|
|||||||
@dataclass
|
@dataclass
|
||||||
class Foo:
|
class Foo:
|
||||||
foo: List[str] = field(default_factory=lambda: []) # PIE807
|
foo: List[str] = field(default_factory=lambda: []) # PIE807
|
||||||
|
bar: Dict[str, int] = field(default_factory=lambda: {}) # PIE807
|
||||||
|
|
||||||
|
|
||||||
class FooTable(BaseTable):
|
class FooTable(BaseTable):
|
||||||
bar = fields.ListField(default=lambda: []) # PIE807
|
foo = fields.ListField(default=lambda: []) # PIE807
|
||||||
|
bar = fields.ListField(default=lambda: {}) # PIE807
|
||||||
|
|
||||||
|
|
||||||
class FooTable(BaseTable):
|
class FooTable(BaseTable):
|
||||||
bar = fields.ListField(lambda: []) # PIE807
|
foo = fields.ListField(lambda: []) # PIE807
|
||||||
|
bar = fields.ListField(default=lambda: {}) # PIE807
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Foo:
|
class Foo:
|
||||||
foo: List[str] = field(default_factory=list)
|
foo: List[str] = field(default_factory=list)
|
||||||
|
bar: Dict[str, int] = field(default_factory=dict)
|
||||||
|
|
||||||
|
|
||||||
class FooTable(BaseTable):
|
class FooTable(BaseTable):
|
||||||
bar = fields.ListField(list)
|
foo = fields.ListField(list)
|
||||||
|
bar = fields.ListField(dict)
|
||||||
|
|
||||||
|
|
||||||
lambda *args, **kwargs: []
|
lambda *args, **kwargs: []
|
||||||
|
lambda *args, **kwargs: {}
|
||||||
|
|
||||||
lambda *args: []
|
lambda *args: []
|
||||||
|
lambda *args: {}
|
||||||
|
|
||||||
lambda **kwargs: []
|
lambda **kwargs: []
|
||||||
|
lambda **kwargs: {}
|
||||||
|
|
||||||
|
lambda: {**unwrap}
|
||||||
|
|||||||
@@ -36,3 +36,54 @@ field10: (Literal[1] | str) | Literal[2] # Error
|
|||||||
|
|
||||||
# Should emit for union in generic parent type.
|
# Should emit for union in generic parent type.
|
||||||
field11: dict[Literal[1] | Literal[2], str] # Error
|
field11: dict[Literal[1] | Literal[2], str] # Error
|
||||||
|
|
||||||
|
# Should emit for unions with more than two cases
|
||||||
|
field12: Literal[1] | Literal[2] | Literal[3] # Error
|
||||||
|
field13: Literal[1] | Literal[2] | Literal[3] | Literal[4] # Error
|
||||||
|
|
||||||
|
# Should emit for unions with more than two cases, even if not directly adjacent
|
||||||
|
field14: Literal[1] | Literal[2] | str | Literal[3] # Error
|
||||||
|
|
||||||
|
# Should emit for unions with mixed literal internal types
|
||||||
|
field15: Literal[1] | Literal["foo"] | Literal[True] # Error
|
||||||
|
|
||||||
|
# Shouldn't emit for duplicate field types with same value; covered by Y016
|
||||||
|
field16: Literal[1] | Literal[1] # OK
|
||||||
|
|
||||||
|
# Shouldn't emit if in new parent type
|
||||||
|
field17: Literal[1] | dict[Literal[2], str] # OK
|
||||||
|
|
||||||
|
# Shouldn't emit if not in a union parent
|
||||||
|
field18: dict[Literal[1], Literal[2]] # OK
|
||||||
|
|
||||||
|
# Should respect name of literal type used
|
||||||
|
field19: typing.Literal[1] | typing.Literal[2] # Error
|
||||||
|
|
||||||
|
# Should emit in cases with newlines
|
||||||
|
field20: typing.Union[
|
||||||
|
Literal[
|
||||||
|
1 # test
|
||||||
|
],
|
||||||
|
Literal[2],
|
||||||
|
] # Error, newline and comment will not be emitted in message
|
||||||
|
|
||||||
|
# Should handle multiple unions with multiple members
|
||||||
|
field21: Literal[1, 2] | Literal[3, 4] # Error
|
||||||
|
|
||||||
|
# Should emit in cases with `typing.Union` instead of `|`
|
||||||
|
field22: typing.Union[Literal[1], Literal[2]] # Error
|
||||||
|
|
||||||
|
# Should emit in cases with `typing_extensions.Literal`
|
||||||
|
field23: typing_extensions.Literal[1] | typing_extensions.Literal[2] # Error
|
||||||
|
|
||||||
|
# Should emit in cases with nested `typing.Union`
|
||||||
|
field24: typing.Union[Literal[1], typing.Union[Literal[2], str]] # Error
|
||||||
|
|
||||||
|
# Should emit in cases with mixed `typing.Union` and `|`
|
||||||
|
field25: typing.Union[Literal[1], Literal[2] | str] # Error
|
||||||
|
|
||||||
|
# Should emit only once in cases with multiple nested `typing.Union`
|
||||||
|
field24: typing.Union[Literal[1], typing.Union[Literal[2], typing.Union[Literal[3], Literal[4]]]] # Error
|
||||||
|
|
||||||
|
# Should use the first literal subscript attribute when fixing
|
||||||
|
field25: typing.Union[typing_extensions.Literal[1], typing.Union[Literal[2], typing.Union[Literal[3], Literal[4]]], str] # Error
|
||||||
|
|||||||
@@ -84,3 +84,6 @@ field25: typing.Union[Literal[1], Literal[2] | str] # Error
|
|||||||
|
|
||||||
# Should emit only once in cases with multiple nested `typing.Union`
|
# Should emit only once in cases with multiple nested `typing.Union`
|
||||||
field24: typing.Union[Literal[1], typing.Union[Literal[2], typing.Union[Literal[3], Literal[4]]]] # Error
|
field24: typing.Union[Literal[1], typing.Union[Literal[2], typing.Union[Literal[3], Literal[4]]]] # Error
|
||||||
|
|
||||||
|
# Should use the first literal subscript attribute when fixing
|
||||||
|
field25: typing.Union[typing_extensions.Literal[1], typing.Union[Literal[2], typing.Union[Literal[3], Literal[4]]], str] # Error
|
||||||
|
|||||||
@@ -3,9 +3,11 @@
|
|||||||
import abc
|
import abc
|
||||||
import builtins
|
import builtins
|
||||||
import collections.abc
|
import collections.abc
|
||||||
|
import enum
|
||||||
import typing
|
import typing
|
||||||
from abc import abstractmethod
|
from abc import ABCMeta, abstractmethod
|
||||||
from collections.abc import AsyncIterable, AsyncIterator, Iterable, Iterator
|
from collections.abc import AsyncIterable, AsyncIterator, Iterable, Iterator
|
||||||
|
from enum import EnumMeta
|
||||||
from typing import Any, overload
|
from typing import Any, overload
|
||||||
|
|
||||||
import typing_extensions
|
import typing_extensions
|
||||||
@@ -199,6 +201,31 @@ class AsyncIteratorReturningAsyncIterable:
|
|||||||
... # Y045 "__aiter__" methods should return an AsyncIterator, not an AsyncIterable
|
... # Y045 "__aiter__" methods should return an AsyncIterator, not an AsyncIterable
|
||||||
|
|
||||||
|
|
||||||
|
class MetaclassInWhichSelfCannotBeUsed(type):
|
||||||
|
def __new__(cls) -> MetaclassInWhichSelfCannotBeUsed: ...
|
||||||
|
def __enter__(self) -> MetaclassInWhichSelfCannotBeUsed: ...
|
||||||
|
async def __aenter__(self) -> MetaclassInWhichSelfCannotBeUsed: ...
|
||||||
|
def __isub__(self, other: MetaclassInWhichSelfCannotBeUsed) -> MetaclassInWhichSelfCannotBeUsed: ...
|
||||||
|
|
||||||
|
class MetaclassInWhichSelfCannotBeUsed2(EnumMeta):
|
||||||
|
def __new__(cls) -> MetaclassInWhichSelfCannotBeUsed2: ...
|
||||||
|
def __enter__(self) -> MetaclassInWhichSelfCannotBeUsed2: ...
|
||||||
|
async def __aenter__(self) -> MetaclassInWhichSelfCannotBeUsed2: ...
|
||||||
|
def __isub__(self, other: MetaclassInWhichSelfCannotBeUsed2) -> MetaclassInWhichSelfCannotBeUsed2: ...
|
||||||
|
|
||||||
|
class MetaclassInWhichSelfCannotBeUsed3(enum.EnumType):
|
||||||
|
def __new__(cls) -> MetaclassInWhichSelfCannotBeUsed3: ...
|
||||||
|
def __enter__(self) -> MetaclassInWhichSelfCannotBeUsed3: ...
|
||||||
|
async def __aenter__(self) -> MetaclassInWhichSelfCannotBeUsed3: ...
|
||||||
|
def __isub__(self, other: MetaclassInWhichSelfCannotBeUsed3) -> MetaclassInWhichSelfCannotBeUsed3: ...
|
||||||
|
|
||||||
|
class MetaclassInWhichSelfCannotBeUsed4(ABCMeta):
|
||||||
|
def __new__(cls) -> MetaclassInWhichSelfCannotBeUsed4: ...
|
||||||
|
def __enter__(self) -> MetaclassInWhichSelfCannotBeUsed4: ...
|
||||||
|
async def __aenter__(self) -> MetaclassInWhichSelfCannotBeUsed4: ...
|
||||||
|
def __isub__(self, other: MetaclassInWhichSelfCannotBeUsed4) -> MetaclassInWhichSelfCannotBeUsed4: ...
|
||||||
|
|
||||||
|
|
||||||
class Abstract(Iterator[str]):
|
class Abstract(Iterator[str]):
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def __iter__(self) -> Iterator[str]:
|
def __iter__(self) -> Iterator[str]:
|
||||||
|
|||||||
@@ -3,9 +3,11 @@
|
|||||||
import abc
|
import abc
|
||||||
import builtins
|
import builtins
|
||||||
import collections.abc
|
import collections.abc
|
||||||
|
import enum
|
||||||
import typing
|
import typing
|
||||||
from abc import abstractmethod
|
from abc import ABCMeta, abstractmethod
|
||||||
from collections.abc import AsyncIterable, AsyncIterator, Iterable, Iterator
|
from collections.abc import AsyncIterable, AsyncIterator, Iterable, Iterator
|
||||||
|
from enum import EnumMeta
|
||||||
from typing import Any, overload
|
from typing import Any, overload
|
||||||
|
|
||||||
import typing_extensions
|
import typing_extensions
|
||||||
@@ -152,6 +154,30 @@ class AsyncIteratorReturningAsyncIterable:
|
|||||||
str
|
str
|
||||||
]: ... # Y045 "__aiter__" methods should return an AsyncIterator, not an AsyncIterable
|
]: ... # Y045 "__aiter__" methods should return an AsyncIterator, not an AsyncIterable
|
||||||
|
|
||||||
|
class MetaclassInWhichSelfCannotBeUsed(type):
|
||||||
|
def __new__(cls) -> MetaclassInWhichSelfCannotBeUsed: ...
|
||||||
|
def __enter__(self) -> MetaclassInWhichSelfCannotBeUsed: ...
|
||||||
|
async def __aenter__(self) -> MetaclassInWhichSelfCannotBeUsed: ...
|
||||||
|
def __isub__(self, other: MetaclassInWhichSelfCannotBeUsed) -> MetaclassInWhichSelfCannotBeUsed: ...
|
||||||
|
|
||||||
|
class MetaclassInWhichSelfCannotBeUsed2(EnumMeta):
|
||||||
|
def __new__(cls) -> MetaclassInWhichSelfCannotBeUsed2: ...
|
||||||
|
def __enter__(self) -> MetaclassInWhichSelfCannotBeUsed2: ...
|
||||||
|
async def __aenter__(self) -> MetaclassInWhichSelfCannotBeUsed2: ...
|
||||||
|
def __isub__(self, other: MetaclassInWhichSelfCannotBeUsed2) -> MetaclassInWhichSelfCannotBeUsed2: ...
|
||||||
|
|
||||||
|
class MetaclassInWhichSelfCannotBeUsed3(enum.EnumType):
|
||||||
|
def __new__(cls) -> MetaclassInWhichSelfCannotBeUsed3: ...
|
||||||
|
def __enter__(self) -> MetaclassInWhichSelfCannotBeUsed3: ...
|
||||||
|
async def __aenter__(self) -> MetaclassInWhichSelfCannotBeUsed3: ...
|
||||||
|
def __isub__(self, other: MetaclassInWhichSelfCannotBeUsed3) -> MetaclassInWhichSelfCannotBeUsed3: ...
|
||||||
|
|
||||||
|
class MetaclassInWhichSelfCannotBeUsed4(ABCMeta):
|
||||||
|
def __new__(cls) -> MetaclassInWhichSelfCannotBeUsed4: ...
|
||||||
|
def __enter__(self) -> MetaclassInWhichSelfCannotBeUsed4: ...
|
||||||
|
async def __aenter__(self) -> MetaclassInWhichSelfCannotBeUsed4: ...
|
||||||
|
def __isub__(self, other: MetaclassInWhichSelfCannotBeUsed4) -> MetaclassInWhichSelfCannotBeUsed4: ...
|
||||||
|
|
||||||
class Abstract(Iterator[str]):
|
class Abstract(Iterator[str]):
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def __iter__(self) -> Iterator[str]: ...
|
def __iter__(self) -> Iterator[str]: ...
|
||||||
|
|||||||
@@ -22,3 +22,7 @@ Snake_case_alias: TypeAlias = int | float # PYI042, since not camel case
|
|||||||
|
|
||||||
# check that this edge case doesn't crash
|
# check that this edge case doesn't crash
|
||||||
_: TypeAlias = str | int
|
_: TypeAlias = str | int
|
||||||
|
|
||||||
|
# PEP 695
|
||||||
|
type foo_bar = int | str
|
||||||
|
type FooBar = int | str
|
||||||
|
|||||||
@@ -22,3 +22,7 @@ Snake_case_alias: TypeAlias = int | float # PYI042, since not camel case
|
|||||||
|
|
||||||
# check that this edge case doesn't crash
|
# check that this edge case doesn't crash
|
||||||
_: TypeAlias = str | int
|
_: TypeAlias = str | int
|
||||||
|
|
||||||
|
# PEP 695
|
||||||
|
type foo_bar = int | str
|
||||||
|
type FooBar = int | str
|
||||||
|
|||||||
@@ -21,3 +21,7 @@ _PrivateAliasS2: TypeAlias = Annotated[str, "also okay"]
|
|||||||
|
|
||||||
# check that this edge case doesn't crash
|
# check that this edge case doesn't crash
|
||||||
_: TypeAlias = str | int
|
_: TypeAlias = str | int
|
||||||
|
|
||||||
|
# PEP 695
|
||||||
|
type _FooT = str | int
|
||||||
|
type Foo = str | int
|
||||||
|
|||||||
@@ -21,3 +21,7 @@ _PrivateAliasS2: TypeAlias = Annotated[str, "also okay"]
|
|||||||
|
|
||||||
# check that this edge case doesn't crash
|
# check that this edge case doesn't crash
|
||||||
_: TypeAlias = str | int
|
_: TypeAlias = str | int
|
||||||
|
|
||||||
|
# PEP 695
|
||||||
|
type _FooT = str | int
|
||||||
|
type Foo = str | int
|
||||||
|
|||||||
@@ -10,3 +10,14 @@ def foo_no_return_typing_extensions(
|
|||||||
def foo_no_return_kwarg(arg: int, *, arg2: NoReturn): ... # Error: PYI050
|
def foo_no_return_kwarg(arg: int, *, arg2: NoReturn): ... # Error: PYI050
|
||||||
def foo_no_return_pos_only(arg: int, /, arg2: NoReturn): ... # Error: PYI050
|
def foo_no_return_pos_only(arg: int, /, arg2: NoReturn): ... # Error: PYI050
|
||||||
def foo_never(arg: Never): ...
|
def foo_never(arg: Never): ...
|
||||||
|
def foo_args(*args: NoReturn): ... # Error: PYI050
|
||||||
|
def foo_kwargs(**kwargs: NoReturn): ... # Error: PYI050
|
||||||
|
def foo_args_kwargs(*args: NoReturn, **kwargs: NoReturn): ... # Error: PYI050
|
||||||
|
def foo_int_args(*args: int): ...
|
||||||
|
def foo_int_kwargs(**kwargs: int): ...
|
||||||
|
def foo_int_args_kwargs(*args: int, **kwargs: int): ...
|
||||||
|
def foo_int_args_no_return(*args: int, **kwargs: NoReturn): ... # Error: PYI050
|
||||||
|
def foo_int_kwargs_no_return(*args: NoReturn, **kwargs: int): ... # Error: PYI050
|
||||||
|
def foo_args_never(*args: Never): ...
|
||||||
|
def foo_kwargs_never(**kwargs: Never): ...
|
||||||
|
def foo_args_kwargs_never(*args: Never, **kwargs: Never): ...
|
||||||
|
|||||||
@@ -91,3 +91,17 @@ field27 = list[str]
|
|||||||
field28 = builtins.str
|
field28 = builtins.str
|
||||||
field29 = str
|
field29 = str
|
||||||
field30 = str | bytes | None
|
field30 = str | bytes | None
|
||||||
|
|
||||||
|
# We shouldn't emit Y052 for `enum` subclasses.
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
class Foo(Enum):
|
||||||
|
FOO = 0
|
||||||
|
BAR = 1
|
||||||
|
|
||||||
|
class Bar(Foo):
|
||||||
|
BAZ = 2
|
||||||
|
BOP = 3
|
||||||
|
|
||||||
|
class Bop:
|
||||||
|
WIZ = 4
|
||||||
|
|||||||
@@ -98,3 +98,17 @@ field27 = list[str]
|
|||||||
field28 = builtins.str
|
field28 = builtins.str
|
||||||
field29 = str
|
field29 = str
|
||||||
field30 = str | bytes | None
|
field30 = str | bytes | None
|
||||||
|
|
||||||
|
# We shouldn't emit Y052 for `enum` subclasses.
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
class Foo(Enum):
|
||||||
|
FOO = 0
|
||||||
|
BAR = 1
|
||||||
|
|
||||||
|
class Bar(Foo):
|
||||||
|
BAZ = 2
|
||||||
|
BOP = 3
|
||||||
|
|
||||||
|
class Bop:
|
||||||
|
WIZ = 4
|
||||||
|
|||||||
45
crates/ruff_linter/resources/test/fixtures/flake8_quotes/doubles_escaped_unnecessary.py
vendored
Normal file
45
crates/ruff_linter/resources/test/fixtures/flake8_quotes/doubles_escaped_unnecessary.py
vendored
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
this_should_raise_Q004 = 'This is a \"string\"'
|
||||||
|
this_should_raise_Q004 = 'This is \\ a \\\"string\"'
|
||||||
|
this_is_fine = '"This" is a \"string\"'
|
||||||
|
this_is_fine = "This is a 'string'"
|
||||||
|
this_is_fine = "\"This\" is a 'string'"
|
||||||
|
this_is_fine = r'This is a \"string\"'
|
||||||
|
this_is_fine = R'This is a \"string\"'
|
||||||
|
this_should_raise_Q004 = (
|
||||||
|
'This is a'
|
||||||
|
'\"string\"'
|
||||||
|
)
|
||||||
|
|
||||||
|
# Same as above, but with f-strings
|
||||||
|
f'This is a \"string\"' # Q004
|
||||||
|
f'This is \\ a \\\"string\"' # Q004
|
||||||
|
f'"This" is a \"string\"'
|
||||||
|
f"This is a 'string'"
|
||||||
|
f"\"This\" is a 'string'"
|
||||||
|
fr'This is a \"string\"'
|
||||||
|
fR'This is a \"string\"'
|
||||||
|
this_should_raise_Q004 = (
|
||||||
|
f'This is a'
|
||||||
|
f'\"string\"' # Q004
|
||||||
|
)
|
||||||
|
|
||||||
|
# Nested f-strings (Python 3.12+)
|
||||||
|
#
|
||||||
|
# The first one is interesting because the fix for it is valid pre 3.12:
|
||||||
|
#
|
||||||
|
# f"'foo' {'nested'}"
|
||||||
|
#
|
||||||
|
# but as the actual string itself is invalid pre 3.12, we don't catch it.
|
||||||
|
f'\"foo\" {'nested'}' # Q004
|
||||||
|
f'\"foo\" {f'nested'}' # Q004
|
||||||
|
f'\"foo\" {f'\"nested\"'} \"\"' # Q004
|
||||||
|
|
||||||
|
f'normal {f'nested'} normal'
|
||||||
|
f'\"normal\" {f'nested'} normal' # Q004
|
||||||
|
f'\"normal\" {f'nested'} "double quotes"'
|
||||||
|
f'\"normal\" {f'\"nested\" {'other'} normal'} "double quotes"' # Q004
|
||||||
|
f'\"normal\" {f'\"nested\" {'other'} "double quotes"'} normal' # Q004
|
||||||
|
|
||||||
|
# Make sure we do not unescape quotes
|
||||||
|
this_is_fine = 'This is an \\"escaped\\" quote'
|
||||||
|
this_should_raise_Q004 = 'This is an \\\"escaped\\\" quote with an extra backslash'
|
||||||
43
crates/ruff_linter/resources/test/fixtures/flake8_quotes/singles_escaped_unnecessary.py
vendored
Normal file
43
crates/ruff_linter/resources/test/fixtures/flake8_quotes/singles_escaped_unnecessary.py
vendored
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
this_should_raise_Q004 = "This is a \'string\'"
|
||||||
|
this_should_raise_Q004 = "'This' is a \'string\'"
|
||||||
|
this_is_fine = 'This is a "string"'
|
||||||
|
this_is_fine = '\'This\' is a "string"'
|
||||||
|
this_is_fine = r"This is a \'string\'"
|
||||||
|
this_is_fine = R"This is a \'string\'"
|
||||||
|
this_should_raise_Q004 = (
|
||||||
|
"This is a"
|
||||||
|
"\'string\'"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Same as above, but with f-strings
|
||||||
|
f"This is a \'string\'" # Q004
|
||||||
|
f"'This' is a \'string\'" # Q004
|
||||||
|
f'This is a "string"'
|
||||||
|
f'\'This\' is a "string"'
|
||||||
|
fr"This is a \'string\'"
|
||||||
|
fR"This is a \'string\'"
|
||||||
|
this_should_raise_Q004 = (
|
||||||
|
f"This is a"
|
||||||
|
f"\'string\'" # Q004
|
||||||
|
)
|
||||||
|
|
||||||
|
# Nested f-strings (Python 3.12+)
|
||||||
|
#
|
||||||
|
# The first one is interesting because the fix for it is valid pre 3.12:
|
||||||
|
#
|
||||||
|
# f'"foo" {"nested"}'
|
||||||
|
#
|
||||||
|
# but as the actual string itself is invalid pre 3.12, we don't catch it.
|
||||||
|
f"\'foo\' {"foo"}" # Q004
|
||||||
|
f"\'foo\' {f"foo"}" # Q004
|
||||||
|
f"\'foo\' {f"\'foo\'"} \'\'" # Q004
|
||||||
|
|
||||||
|
f"normal {f"nested"} normal"
|
||||||
|
f"\'normal\' {f"nested"} normal" # Q004
|
||||||
|
f"\'normal\' {f"nested"} 'single quotes'"
|
||||||
|
f"\'normal\' {f"\'nested\' {"other"} normal"} 'single quotes'" # Q004
|
||||||
|
f"\'normal\' {f"\'nested\' {"other"} 'single quotes'"} normal" # Q004
|
||||||
|
|
||||||
|
# Make sure we do not unescape quotes
|
||||||
|
this_is_fine = "This is an \\'escaped\\' quote"
|
||||||
|
this_should_raise_Q004 = "This is an \\\'escaped\\\' quote with an extra backslash"
|
||||||
@@ -82,3 +82,14 @@ raise IndexError();
|
|||||||
|
|
||||||
# RSE102
|
# RSE102
|
||||||
raise Foo()
|
raise Foo()
|
||||||
|
|
||||||
|
# OK
|
||||||
|
raise ctypes.WinError()
|
||||||
|
|
||||||
|
|
||||||
|
def func():
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# OK
|
||||||
|
raise func()
|
||||||
|
|||||||
@@ -134,3 +134,32 @@ with A() as a:
|
|||||||
f" something { my_dict["key"] } something else "
|
f" something { my_dict["key"] } something else "
|
||||||
|
|
||||||
f"foo {f"bar {x}"} baz"
|
f"foo {f"bar {x}"} baz"
|
||||||
|
|
||||||
|
# Allow cascading for some statements.
|
||||||
|
import anyio
|
||||||
|
import asyncio
|
||||||
|
import trio
|
||||||
|
|
||||||
|
async with asyncio.timeout(1):
|
||||||
|
async with A() as a:
|
||||||
|
pass
|
||||||
|
|
||||||
|
async with A():
|
||||||
|
async with asyncio.timeout(1):
|
||||||
|
pass
|
||||||
|
|
||||||
|
async with asyncio.timeout(1):
|
||||||
|
async with asyncio.timeout_at(1):
|
||||||
|
async with anyio.CancelScope():
|
||||||
|
async with anyio.fail_after(1):
|
||||||
|
async with anyio.move_on_after(1):
|
||||||
|
async with trio.fail_after(1):
|
||||||
|
async with trio.fail_at(1):
|
||||||
|
async with trio.move_on_after(1):
|
||||||
|
async with trio.move_on_at(1):
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Do not supress combination, if a context manager is already combined with another.
|
||||||
|
async with asyncio.timeout(1), A():
|
||||||
|
async with B():
|
||||||
|
pass
|
||||||
|
|||||||
@@ -25,3 +25,11 @@ a = {}.get(key, None)
|
|||||||
|
|
||||||
# SIM910
|
# SIM910
|
||||||
({}).get(key, None)
|
({}).get(key, None)
|
||||||
|
|
||||||
|
# SIM910
|
||||||
|
ages = {"Tom": 23, "Maria": 23, "Dog": 11}
|
||||||
|
age = ages.get("Cat", None)
|
||||||
|
|
||||||
|
# OK
|
||||||
|
ages = ["Tom", "Maria", "Dog"]
|
||||||
|
age = ages.get("Cat", None)
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
import trio
|
|
||||||
from trio import sleep
|
|
||||||
|
|
||||||
|
|
||||||
async def func():
|
async def func():
|
||||||
|
import trio
|
||||||
|
from trio import sleep
|
||||||
|
|
||||||
await trio.sleep(0) # TRIO115
|
await trio.sleep(0) # TRIO115
|
||||||
await trio.sleep(1) # OK
|
await trio.sleep(1) # OK
|
||||||
await trio.sleep(0, 1) # OK
|
await trio.sleep(0, 1) # OK
|
||||||
@@ -21,8 +20,16 @@ async def func():
|
|||||||
trio.sleep(bar)
|
trio.sleep(bar)
|
||||||
|
|
||||||
|
|
||||||
trio.sleep(0) # TRIO115
|
def func():
|
||||||
|
trio.run(trio.sleep(0)) # TRIO115
|
||||||
|
|
||||||
|
|
||||||
|
from trio import Event, sleep
|
||||||
|
|
||||||
|
|
||||||
def func():
|
def func():
|
||||||
trio.run(trio.sleep(0)) # TRIO115
|
sleep(0) # TRIO115
|
||||||
|
|
||||||
|
|
||||||
|
async def func():
|
||||||
|
await sleep(seconds=0) # TRIO115
|
||||||
|
|||||||
@@ -172,3 +172,14 @@ def f():
|
|||||||
from module import Member
|
from module import Member
|
||||||
|
|
||||||
x: Member = 1
|
x: Member = 1
|
||||||
|
|
||||||
|
|
||||||
|
def f():
|
||||||
|
from typing_extensions import TYPE_CHECKING
|
||||||
|
|
||||||
|
from pandas import y
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
_type = x
|
||||||
|
elif True:
|
||||||
|
_type = y
|
||||||
|
|||||||
10
crates/ruff_linter/resources/test/fixtures/flake8_type_checking/TCH004_16.py
vendored
Normal file
10
crates/ruff_linter/resources/test/fixtures/flake8_type_checking/TCH004_16.py
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing_extensions import TYPE_CHECKING
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from pandas import DataFrame
|
||||||
|
|
||||||
|
|
||||||
|
def example() -> DataFrame:
|
||||||
|
pass
|
||||||
10
crates/ruff_linter/resources/test/fixtures/flake8_type_checking/TCH004_17.py
vendored
Normal file
10
crates/ruff_linter/resources/test/fixtures/flake8_type_checking/TCH004_17.py
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing_extensions import TYPE_CHECKING
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from pandas import DataFrame
|
||||||
|
|
||||||
|
|
||||||
|
def example() -> DataFrame:
|
||||||
|
x = DataFrame()
|
||||||
@@ -37,3 +37,9 @@ if False:
|
|||||||
|
|
||||||
if 0:
|
if 0:
|
||||||
x: List
|
x: List
|
||||||
|
|
||||||
|
|
||||||
|
from typing_extensions import TYPE_CHECKING
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
pass # TCH005
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from collections.abc import Sequence # TCH003
|
from pandas import DataFrame
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
|
||||||
class MyBaseClass:
|
class Parent(BaseModel):
|
||||||
pass
|
...
|
||||||
|
|
||||||
|
|
||||||
class Foo(MyBaseClass):
|
class Child(Parent):
|
||||||
foo: Sequence
|
baz: DataFrame
|
||||||
|
|||||||
34
crates/ruff_linter/resources/test/fixtures/flake8_type_checking/singledispatch.py
vendored
Normal file
34
crates/ruff_linter/resources/test/fixtures/flake8_type_checking/singledispatch.py
vendored
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
"""Test module."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from functools import singledispatch
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
from numpy import asarray
|
||||||
|
from numpy.typing import ArrayLike
|
||||||
|
from scipy.sparse import spmatrix
|
||||||
|
from pandas import DataFrame
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from numpy import ndarray
|
||||||
|
|
||||||
|
|
||||||
|
@singledispatch
|
||||||
|
def to_array_or_mat(a: ArrayLike | spmatrix) -> ndarray | spmatrix:
|
||||||
|
"""Convert arg to array or leaves it as sparse matrix."""
|
||||||
|
msg = f"Unhandled type {type(a)}"
|
||||||
|
raise NotImplementedError(msg)
|
||||||
|
|
||||||
|
|
||||||
|
@to_array_or_mat.register
|
||||||
|
def _(a: ArrayLike) -> ndarray:
|
||||||
|
return asarray(a)
|
||||||
|
|
||||||
|
|
||||||
|
@to_array_or_mat.register
|
||||||
|
def _(a: spmatrix) -> spmatrix:
|
||||||
|
return a
|
||||||
|
|
||||||
|
|
||||||
|
def _(a: DataFrame) -> DataFrame:
|
||||||
|
return a
|
||||||
9
crates/ruff_linter/resources/test/fixtures/flake8_type_checking/typing_modules_1.py
vendored
Normal file
9
crates/ruff_linter/resources/test/fixtures/flake8_type_checking/typing_modules_1.py
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing_extensions import Self
|
||||||
|
|
||||||
|
|
||||||
|
def func():
|
||||||
|
from pandas import DataFrame
|
||||||
|
|
||||||
|
df: DataFrame
|
||||||
9
crates/ruff_linter/resources/test/fixtures/flake8_type_checking/typing_modules_2.py
vendored
Normal file
9
crates/ruff_linter/resources/test/fixtures/flake8_type_checking/typing_modules_2.py
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import typing_extensions
|
||||||
|
|
||||||
|
|
||||||
|
def func():
|
||||||
|
from pandas import DataFrame
|
||||||
|
|
||||||
|
df: DataFrame
|
||||||
2
crates/ruff_linter/resources/test/fixtures/isort/force_sort_within_sections_future.py
vendored
Normal file
2
crates/ruff_linter/resources/test/fixtures/isort/force_sort_within_sections_future.py
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
import __future__
|
||||||
|
from __future__ import annotations
|
||||||
5
crates/ruff_linter/resources/test/fixtures/isort/force_sort_within_sections_with_as_names.py
vendored
Normal file
5
crates/ruff_linter/resources/test/fixtures/isort/force_sort_within_sections_with_as_names.py
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import encodings
|
||||||
|
from datetime import timezone as tz
|
||||||
|
from datetime import timedelta
|
||||||
|
import datetime as dt
|
||||||
|
import datetime
|
||||||
5
crates/ruff_linter/resources/test/fixtures/isort/from_first.py
vendored
Normal file
5
crates/ruff_linter/resources/test/fixtures/isort/from_first.py
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
from __future__ import blah
|
||||||
|
|
||||||
|
from os import path
|
||||||
|
|
||||||
|
import os
|
||||||
2
crates/ruff_linter/resources/test/fixtures/isort/future_from.py
vendored
Normal file
2
crates/ruff_linter/resources/test/fixtures/isort/future_from.py
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
import __future__
|
||||||
|
from __future__ import annotations
|
||||||
3
crates/ruff_linter/resources/test/fixtures/isort/length_sort_from_imports.py
vendored
Normal file
3
crates/ruff_linter/resources/test/fixtures/isort/length_sort_from_imports.py
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
from mediuuuuuuuuuuum import a
|
||||||
|
from short import b
|
||||||
|
from loooooooooooooooooooooog import c
|
||||||
11
crates/ruff_linter/resources/test/fixtures/isort/length_sort_non_ascii_members.py
vendored
Normal file
11
crates/ruff_linter/resources/test/fixtures/isort/length_sort_non_ascii_members.py
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
from module1 import (
|
||||||
|
loooooooooooooong,
|
||||||
|
σηορτ,
|
||||||
|
mediuuuuum,
|
||||||
|
shoort,
|
||||||
|
looooooooooooooong,
|
||||||
|
μεδιυυυυυμ,
|
||||||
|
short,
|
||||||
|
mediuuuuuum,
|
||||||
|
λοοοοοοοοοοοοοονγ,
|
||||||
|
)
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user