Compare commits
95 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
818582fe8a | ||
|
|
90574c1088 | ||
|
|
3061a35e7c | ||
|
|
87681697ae | ||
|
|
e9ec2a7b36 | ||
|
|
b0bb75dc1c | ||
|
|
ebca5c2df8 | ||
|
|
16b10c42f0 | ||
|
|
4a6e5d1549 | ||
|
|
b078050732 | ||
|
|
5f796b39b4 | ||
|
|
9d34da23bd | ||
|
|
bde12c3bb3 | ||
|
|
f735660801 | ||
|
|
34cd22dfc1 | ||
|
|
9fafe16a55 | ||
|
|
e9a4cb1c1d | ||
|
|
9db825c731 | ||
|
|
2c7464604a | ||
|
|
cd2099f772 | ||
|
|
091d36cd30 | ||
|
|
02f156c6cb | ||
|
|
9f7350961e | ||
|
|
118a93260a | ||
|
|
1c16255884 | ||
|
|
16c4552946 | ||
|
|
0ba3989b3d | ||
|
|
3435e15cba | ||
|
|
781bbbc286 | ||
|
|
acf0b82f19 | ||
|
|
057414ddd4 | ||
|
|
ca94e9aa26 | ||
|
|
797b5bd261 | ||
|
|
a64f62f439 | ||
|
|
058ee8e6bf | ||
|
|
39fc1f0c1b | ||
|
|
34842b4c4b | ||
|
|
dfa6fa8f83 | ||
|
|
6131c819ed | ||
|
|
79ba420faa | ||
|
|
d16ba890ae | ||
|
|
6b6851bf1f | ||
|
|
056718ce75 | ||
|
|
4521fdf021 | ||
|
|
8e479628f2 | ||
|
|
2a11c4b1f1 | ||
|
|
a8cde5a936 | ||
|
|
1822b57ed5 | ||
|
|
c679570041 | ||
|
|
edcb3a7217 | ||
|
|
6e43dc7270 | ||
|
|
570d0864f2 | ||
|
|
d22e96916c | ||
|
|
043d31dcdf | ||
|
|
1392e4cced | ||
|
|
59ee89a091 | ||
|
|
6a7c3728ee | ||
|
|
0a60eb0aca | ||
|
|
3e96803033 | ||
|
|
c59035139c | ||
|
|
7632d7eda7 | ||
|
|
b4dbe62da0 | ||
|
|
9106d5338b | ||
|
|
534d8d049c | ||
|
|
e692c4a2cc | ||
|
|
e0b39fa63e | ||
|
|
320a48977b | ||
|
|
0d05aaeb6e | ||
|
|
1e4b1533ad | ||
|
|
df4f5358f9 | ||
|
|
58c383401c | ||
|
|
018b9a2977 | ||
|
|
658cb87ddd | ||
|
|
0d35087bc6 | ||
|
|
b721125af9 | ||
|
|
20d6b21d77 | ||
|
|
1a27992f47 | ||
|
|
89cebe1ce2 | ||
|
|
bdb1505262 | ||
|
|
8c018e8261 | ||
|
|
debd909b2c | ||
|
|
fa54538bd1 | ||
|
|
939f738a71 | ||
|
|
b0f30bef8f | ||
|
|
28c45eb2a3 | ||
|
|
4dc45912e8 | ||
|
|
5ef8bff341 | ||
|
|
2ab8f77223 | ||
|
|
8b72f55a09 | ||
|
|
19121219fb | ||
|
|
d9355c989a | ||
|
|
ec80d1cd85 | ||
|
|
9bb470c7d4 | ||
|
|
dca3fcd8d1 | ||
|
|
10f75c9620 |
55
.github/workflows/ci.yaml
vendored
55
.github/workflows/ci.yaml
vendored
@@ -12,7 +12,7 @@ env:
|
||||
RUSTUP_MAX_RETRIES: 10
|
||||
|
||||
jobs:
|
||||
cargo_build:
|
||||
cargo-build:
|
||||
name: "cargo build"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@@ -36,17 +36,14 @@ jobs:
|
||||
${{ runner.os }}-build-
|
||||
${{ runner.os }}-
|
||||
- run: cargo build --all --release
|
||||
- run: ./target/release/ruff_dev generate-rules-table
|
||||
- run: ./target/release/ruff_dev generate-options
|
||||
- run: git diff --quiet README.md || echo "::error file=README.md::This file is outdated. You may have to rerun 'cargo dev generate-options' and/or 'cargo dev generate-rules-table'."
|
||||
- run: ./target/release/ruff_dev generate-check-code-prefix
|
||||
- run: git diff --quiet src/checks_gen.rs || echo "::error file=src/checks_gen.rs::This file is outdated. You may have to rerun 'cargo dev generate-check-code-prefix'."
|
||||
- run: git diff --exit-code -- README.md src/checks_gen.rs
|
||||
- run: ./target/release/ruff_dev generate-json-schema
|
||||
- run: git diff --quiet ruff.schema.json || echo "::error file=ruff.schema.json::This file is outdated. You may have to rerun 'cargo dev generate-json-schema'."
|
||||
- run: git diff --exit-code -- ruff.schema.json
|
||||
- run: ./target/release/ruff_dev generate-all
|
||||
- run: git diff --quiet README.md || echo "::error file=README.md::This file is outdated. Run 'cargo +nightly dev generate-all'."
|
||||
- run: git diff --quiet src/checks_gen.rs || echo "::error file=src/checks_gen.rs::This file is outdated. Run 'cargo +nightly dev generate-all'."
|
||||
- run: git diff --quiet ruff.schema.json || echo "::error file=ruff.schema.json::This file is outdated. Run 'cargo +nightly dev generate-all'."
|
||||
- run: git diff --quiet playground/src/ruff_options.ts || echo "::error file=playground/src/ruff_options.ts::This file is outdated. Run 'cargo +nightly dev generate-all'."
|
||||
- run: git diff --exit-code -- README.md src/checks_gen.rs ruff.schema.json playground/src/ruff_options.ts
|
||||
|
||||
cargo_fmt:
|
||||
cargo-fmt:
|
||||
name: "cargo fmt"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@@ -82,6 +79,7 @@ jobs:
|
||||
toolchain: nightly-2022-11-01
|
||||
override: true
|
||||
components: clippy
|
||||
target: wasm32-unknown-unknown
|
||||
- uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: cache-cargo
|
||||
@@ -95,8 +93,9 @@ jobs:
|
||||
${{ runner.os }}-build-
|
||||
${{ runner.os }}-
|
||||
- run: cargo clippy --workspace --all-targets --all-features -- -D warnings -W clippy::pedantic
|
||||
- run: cargo clippy --workspace --target wasm32-unknown-unknown --all-features -- -D warnings -W clippy::pedantic
|
||||
|
||||
cargo_test:
|
||||
cargo-test:
|
||||
name: "cargo test"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@@ -122,7 +121,37 @@ jobs:
|
||||
- run: cargo test --all
|
||||
- run: cargo test --package ruff --test black_compatibility_test -- --ignored
|
||||
|
||||
maturin_build:
|
||||
# TODO(charlie): Re-enable the `wasm-pack` tests.
|
||||
# See: https://github.com/charliermarsh/ruff/issues/1425
|
||||
# wasm-pack-test:
|
||||
# name: "wasm-pack test"
|
||||
# runs-on: ubuntu-latest
|
||||
# env:
|
||||
# WASM_BINDGEN_TEST_TIMEOUT: 60
|
||||
# steps:
|
||||
# - uses: actions/checkout@v3
|
||||
# - uses: actions-rs/toolchain@v1
|
||||
# with:
|
||||
# profile: minimal
|
||||
# toolchain: nightly-2022-11-01
|
||||
# override: true
|
||||
# - uses: actions/cache@v3
|
||||
# env:
|
||||
# cache-name: cache-cargo
|
||||
# with:
|
||||
# path: |
|
||||
# ~/.cargo/registry
|
||||
# ~/.cargo/git
|
||||
# key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/Cargo.lock') }}
|
||||
# restore-keys: |
|
||||
# ${{ runner.os }}-build-${{ env.cache-name }}-
|
||||
# ${{ runner.os }}-build-
|
||||
# ${{ runner.os }}-
|
||||
# - uses: jetli/wasm-pack-action@v0.4.0
|
||||
# - uses: jetli/wasm-bindgen-action@v0.2.0
|
||||
# - run: wasm-pack test --node
|
||||
|
||||
maturin-build:
|
||||
name: "maturin build"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
50
.github/workflows/playground.yaml
vendored
Normal file
50
.github/workflows/playground.yaml
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
name: "[Playground] Release"
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: [main]
|
||||
|
||||
env:
|
||||
CARGO_INCREMENTAL: 0
|
||||
CARGO_NET_RETRY: 10
|
||||
RUSTUP_MAX_RETRIES: 10
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
CF_API_TOKEN_EXISTS: ${{ secrets.CF_API_TOKEN != '' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: nightly-2022-11-01
|
||||
override: true
|
||||
target: wasm32-unknown-unknown
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
cache: "npm"
|
||||
cache-dependency-path: playground/package-lock.json
|
||||
- uses: jetli/wasm-pack-action@v0.4.0
|
||||
- uses: jetli/wasm-bindgen-action@v0.2.0
|
||||
- name: "Run wasm-pack"
|
||||
run: wasm-pack build --target web --out-dir playground/src/pkg
|
||||
- name: "Install Node dependencies"
|
||||
run: npm ci
|
||||
working-directory: playground
|
||||
- name: "Run TypeScript checks"
|
||||
run: npm run check
|
||||
working-directory: playground
|
||||
- name: "Build JavaScript bundle"
|
||||
run: npm run build
|
||||
working-directory: playground
|
||||
- name: "Deploy to Cloudflare Pages"
|
||||
if: ${{ env.CF_API_TOKEN_EXISTS == 'true' }}
|
||||
uses: cloudflare/wrangler-action@2.0.0
|
||||
with:
|
||||
apiToken: ${{ secrets.CF_API_TOKEN }}
|
||||
accountId: ${{ secrets.CF_ACCOUNT_ID }}
|
||||
command: pages publish playground/dist --project-name=ruff --branch ${GITHUB_HEAD_REF} --commit-hash ${GITHUB_SHA}
|
||||
@@ -1,6 +1,6 @@
|
||||
repos:
|
||||
- repo: https://github.com/charliermarsh/ruff-pre-commit
|
||||
rev: v0.0.193
|
||||
rev: v0.0.202
|
||||
hooks:
|
||||
- id: ruff
|
||||
|
||||
|
||||
@@ -59,18 +59,20 @@ pattern implemented therein.
|
||||
|
||||
To trigger the rule, you'll likely want to augment the logic in `src/check_ast.rs`, which defines
|
||||
the Python AST visitor, responsible for iterating over the abstract syntax tree and collecting
|
||||
lint-rule violations as it goes. If you need to inspect the AST, you can run `cargo dev print-ast`
|
||||
with a Python file. Grep for the `Check::new` invocations to understand how other, similar rules
|
||||
are implemented.
|
||||
lint-rule violations as it goes. If you need to inspect the AST, you can run
|
||||
`cargo +nightly dev print-ast` with a Python file. Grep for the `Check::new` invocations to
|
||||
understand how other, similar rules are implemented.
|
||||
|
||||
To add a test fixture, create a file under `resources/test/fixtures`, named to match the `CheckCode`
|
||||
you defined earlier (e.g., `E402.py`). This file should contain a variety of violations and
|
||||
non-violations designed to evaluate and demonstrate the behavior of your lint rule. Run Ruff locally
|
||||
with (e.g.) `cargo run resources/test/fixtures/E402.py --no-cache`. Once you're satisfied with the
|
||||
with (e.g.) `cargo run resources/test/fixtures/E402.py --no-cache --select E402`. Once you're satisfied with the
|
||||
output, codify the behavior as a snapshot test by adding a new `testcase` macro to the `mod tests`
|
||||
section of `src/linter.rs`, like so:
|
||||
|
||||
```rust
|
||||
use test_case::test_case;
|
||||
|
||||
#[test_case(CheckCode::A001, Path::new("A001.py"); "A001")]
|
||||
...
|
||||
```
|
||||
@@ -79,9 +81,7 @@ Then, run `cargo test`. Your test will fail, but you'll be prompted to follow-up
|
||||
`cargo insta review`. Accept the generated snapshot, then commit the snapshot file alongside the
|
||||
rest of your changes.
|
||||
|
||||
Finally, to update the documentation, run `cargo dev generate-rules-table` from the repo root. To
|
||||
update the generated prefix map, run `cargo dev generate-check-code-prefix`. Both of these commands
|
||||
should be run whenever a new check is added to the codebase.
|
||||
Finally, regenerate the documentation and generated code with `cargo +nightly dev generate-all`.
|
||||
|
||||
### Example: Adding a new configuration option
|
||||
|
||||
@@ -105,8 +105,7 @@ You may also want to add the new configuration option to the `flake8-to-ruff` to
|
||||
responsible for converting `flake8` configuration files to Ruff's TOML format. This logic
|
||||
lives in `flake8_to_ruff/src/converter.rs`.
|
||||
|
||||
Run `cargo dev generate-options` to update the documentation for supported configuration options,
|
||||
and `cargo dev generate-json-schema` to update the JSON schema for `tool.ruff` in `pyproject.toml`.
|
||||
Finally, regenerate the documentation and generated code with `cargo +nightly dev generate-all`.
|
||||
|
||||
## Release process
|
||||
|
||||
|
||||
265
Cargo.lock
generated
265
Cargo.lock
generated
@@ -61,9 +61,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.66"
|
||||
version = "1.0.68"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6"
|
||||
checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61"
|
||||
|
||||
[[package]]
|
||||
name = "ascii"
|
||||
@@ -86,7 +86,7 @@ version = "2.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa3d466004a8b4cb1bc34044240a2fd29d17607e2e3bd613eb44fd48e8100da3"
|
||||
dependencies = [
|
||||
"bstr 1.0.1",
|
||||
"bstr 1.1.0",
|
||||
"doc-comment",
|
||||
"predicates",
|
||||
"predicates-core",
|
||||
@@ -160,9 +160,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "bstr"
|
||||
version = "1.0.1"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fca0852af221f458706eb0725c03e4ed6c46af9ac98e6a689d5e634215d594dd"
|
||||
checksum = "b45ea9b00a7b3f2988e9a65ad3917e62123c38dba709b666506207be96d1790b"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"once_cell",
|
||||
@@ -193,9 +193,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.77"
|
||||
version = "1.0.78"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4"
|
||||
checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
@@ -280,9 +280,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.0.29"
|
||||
version = "4.0.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4d63b9e9c07271b9957ad22c173bae2a4d9a81127680962039296abcd2f8251d"
|
||||
checksum = "a7db700bc935f9e43e88d00b0850dae18a63773cfbec6d8e070fccf7fef89a39"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"clap_derive",
|
||||
@@ -295,11 +295,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_complete"
|
||||
version = "4.0.6"
|
||||
version = "4.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b7b3c9eae0de7bf8e3f904a5e40612b21fb2e2e566456d177809a48b892d24da"
|
||||
checksum = "10861370d2ba66b0f5989f83ebf35db6421713fd92351790e7fdd6c36774c56b"
|
||||
dependencies = [
|
||||
"clap 4.0.29",
|
||||
"clap 4.0.32",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -308,7 +308,7 @@ version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4160b4a4f72ef58bd766bad27c09e6ef1cc9d82a22f6a0f55d152985a4a48e31"
|
||||
dependencies = [
|
||||
"clap 4.0.29",
|
||||
"clap 4.0.32",
|
||||
"clap_complete",
|
||||
"clap_complete_fig",
|
||||
]
|
||||
@@ -319,7 +319,7 @@ version = "4.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46b30e010e669cd021e5004f3be26cff6b7c08d2a8a0d65b48d43a8cc0efd6c3"
|
||||
dependencies = [
|
||||
"clap 4.0.29",
|
||||
"clap 4.0.32",
|
||||
"clap_complete",
|
||||
]
|
||||
|
||||
@@ -422,6 +422,26 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "console_error_panic_hook"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "console_log"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "501a375961cef1a0d44767200e66e4a559283097e91d0730b1d75dfb2f8a1494"
|
||||
dependencies = [
|
||||
"log",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.8.3"
|
||||
@@ -524,9 +544,9 @@ checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
|
||||
|
||||
[[package]]
|
||||
name = "cxx"
|
||||
version = "1.0.83"
|
||||
version = "1.0.85"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bdf07d07d6531bfcdbe9b8b739b104610c6508dcc4d63b410585faf338241daf"
|
||||
checksum = "5add3fc1717409d029b20c5b6903fc0c0b02fa6741d820054f4a2efa5e5816fd"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cxxbridge-flags",
|
||||
@@ -536,9 +556,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cxx-build"
|
||||
version = "1.0.83"
|
||||
version = "1.0.85"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2eb5b96ecdc99f72657332953d4d9c50135af1bac34277801cc3937906ebd39"
|
||||
checksum = "b4c87959ba14bc6fbc61df77c3fcfe180fc32b93538c4f1031dd802ccb5f2ff0"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"codespan-reporting",
|
||||
@@ -551,15 +571,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cxxbridge-flags"
|
||||
version = "1.0.83"
|
||||
version = "1.0.85"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac040a39517fd1674e0f32177648334b0f4074625b5588a64519804ba0553b12"
|
||||
checksum = "69a3e162fde4e594ed2b07d0f83c6c67b745e7f28ce58c6df5e6b6bef99dfb59"
|
||||
|
||||
[[package]]
|
||||
name = "cxxbridge-macro"
|
||||
version = "1.0.83"
|
||||
version = "1.0.85"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1362b0ddcfc4eb0a1f57b68bd77dd99f0e826958a96abd0ae9bd092e114ffed6"
|
||||
checksum = "3e7e2adeb6a0d4a282e581096b06e1791532b7d576dcde5ccd9382acf55db8e6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -712,9 +732,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "filetime"
|
||||
version = "0.2.18"
|
||||
version = "0.2.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4b9663d381d07ae25dc88dbdf27df458faa83a9b25336bcac83d5e452b5fc9d3"
|
||||
checksum = "4e884668cd0c7480504233e951174ddc3b382f7c2666e3b7310b5c4e7b0c37f9"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"libc",
|
||||
@@ -730,10 +750,10 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
|
||||
|
||||
[[package]]
|
||||
name = "flake8-to-ruff"
|
||||
version = "0.0.193-dev.0"
|
||||
version = "0.0.202-dev.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap 4.0.29",
|
||||
"clap 4.0.32",
|
||||
"configparser",
|
||||
"once_cell",
|
||||
"regex",
|
||||
@@ -952,9 +972,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "insta"
|
||||
version = "1.22.0"
|
||||
version = "1.23.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "197f4e300af8b23664d4077bf5c40e0afa9ba66a567bb5a51d3def3c7b287d1c"
|
||||
checksum = "e48b08a091dfe5b09a6a9688c468fdd5b4396e92ce09e2eb932f0884b02788a4"
|
||||
dependencies = [
|
||||
"console",
|
||||
"lazy_static",
|
||||
@@ -985,9 +1005,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "is-terminal"
|
||||
version = "0.4.1"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "927609f78c2913a6f6ac3c27a4fe87f43e2a35367c0c4b0f8265e8f49a104330"
|
||||
checksum = "28dfb6c8100ccc63462345b67d1bbc3679177c75ee4bf59bf29c8b1d110b8189"
|
||||
dependencies = [
|
||||
"hermit-abi 0.2.6",
|
||||
"io-lifetimes",
|
||||
@@ -1006,9 +1026,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.4"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc"
|
||||
checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
|
||||
|
||||
[[package]]
|
||||
name = "joinery"
|
||||
@@ -1115,9 +1135,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.138"
|
||||
version = "0.2.139"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
|
||||
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
|
||||
|
||||
[[package]]
|
||||
name = "libcst"
|
||||
@@ -1145,9 +1165,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "link-cplusplus"
|
||||
version = "1.0.7"
|
||||
version = "1.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9272ab7b96c9046fbc5bc56c06c117cb639fe2d509df0c421cad82d2915cf369"
|
||||
checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
@@ -1160,9 +1180,9 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.1.3"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f9f08d8963a6c613f4b1a78f4f4a4dbfadf8e6545b2d72861731e4858b8b47f"
|
||||
checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
@@ -1234,6 +1254,12 @@ dependencies = [
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "natord"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "308d96db8debc727c3fd9744aac51751243420e46edf401010908da7f8d5e57c"
|
||||
|
||||
[[package]]
|
||||
name = "new_debug_unreachable"
|
||||
version = "1.0.4"
|
||||
@@ -1334,11 +1360,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.14.0"
|
||||
version = "1.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5"
|
||||
checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
|
||||
dependencies = [
|
||||
"hermit-abi 0.1.19",
|
||||
"hermit-abi 0.2.6",
|
||||
"libc",
|
||||
]
|
||||
|
||||
@@ -1385,9 +1411,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "paste"
|
||||
version = "1.0.9"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1"
|
||||
checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba"
|
||||
|
||||
[[package]]
|
||||
name = "path-absolutize"
|
||||
@@ -1625,9 +1651,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.47"
|
||||
version = "1.0.49"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
|
||||
checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
@@ -1657,9 +1683,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.21"
|
||||
version = "1.0.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
|
||||
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
@@ -1753,11 +1779,10 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.6.0"
|
||||
version = "1.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e060280438193c554f654141c9ea9417886713b7acd75974c85b18a69a88e0b"
|
||||
checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7"
|
||||
dependencies = [
|
||||
"crossbeam-deque",
|
||||
"either",
|
||||
"rayon-core",
|
||||
]
|
||||
@@ -1853,7 +1878,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.0.193"
|
||||
version = "0.0.202"
|
||||
dependencies = [
|
||||
"annotate-snippets 0.9.1",
|
||||
"anyhow",
|
||||
@@ -1862,12 +1887,15 @@ dependencies = [
|
||||
"bincode",
|
||||
"bitflags",
|
||||
"cachedir",
|
||||
"cfg-if 1.0.0",
|
||||
"chrono",
|
||||
"clap 4.0.29",
|
||||
"clap 4.0.32",
|
||||
"clap_complete_command",
|
||||
"clearscreen",
|
||||
"colored",
|
||||
"common-path",
|
||||
"console_error_panic_hook",
|
||||
"console_log",
|
||||
"criterion",
|
||||
"dirs 4.0.0",
|
||||
"fern",
|
||||
@@ -1878,8 +1906,10 @@ dependencies = [
|
||||
"ignore",
|
||||
"insta",
|
||||
"itertools",
|
||||
"js-sys",
|
||||
"libcst",
|
||||
"log",
|
||||
"natord",
|
||||
"nohash-hasher",
|
||||
"notify",
|
||||
"num-bigint",
|
||||
@@ -1895,9 +1925,12 @@ dependencies = [
|
||||
"rustpython-common",
|
||||
"rustpython-parser",
|
||||
"schemars",
|
||||
"semver",
|
||||
"serde",
|
||||
"serde-wasm-bindgen",
|
||||
"serde_json",
|
||||
"shellexpand",
|
||||
"similar",
|
||||
"strum",
|
||||
"strum_macros",
|
||||
"test-case",
|
||||
@@ -1907,14 +1940,16 @@ dependencies = [
|
||||
"update-informer",
|
||||
"ureq",
|
||||
"walkdir",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-test",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruff_dev"
|
||||
version = "0.0.193"
|
||||
version = "0.0.202"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap 4.0.29",
|
||||
"clap 4.0.32",
|
||||
"codegen",
|
||||
"itertools",
|
||||
"libcst",
|
||||
@@ -1927,11 +1962,12 @@ dependencies = [
|
||||
"serde_json",
|
||||
"strum",
|
||||
"strum_macros",
|
||||
"textwrap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruff_macros"
|
||||
version = "0.0.193"
|
||||
version = "0.0.202"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1947,9 +1983,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.36.4"
|
||||
version = "0.36.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb93e85278e08bb5788653183213d3a60fc242b10cb9be96586f5a73dcb67c23"
|
||||
checksum = "a3807b5d10909833d3e9acd1eb5fb988f79376ff10fce42937de71a449c4c588"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"errno",
|
||||
@@ -1974,7 +2010,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rustpython-ast"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=1b6cb170e925a43d605b3fed9f6b878e63e47744#1b6cb170e925a43d605b3fed9f6b878e63e47744"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=68d26955b3e24198a150315e7959719b03709dee#68d26955b3e24198a150315e7959719b03709dee"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"rustpython-common",
|
||||
@@ -1984,7 +2020,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rustpython-common"
|
||||
version = "0.0.0"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=1b6cb170e925a43d605b3fed9f6b878e63e47744#1b6cb170e925a43d605b3fed9f6b878e63e47744"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=68d26955b3e24198a150315e7959719b03709dee#68d26955b3e24198a150315e7959719b03709dee"
|
||||
dependencies = [
|
||||
"ascii",
|
||||
"cfg-if 1.0.0",
|
||||
@@ -2007,7 +2043,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rustpython-compiler-core"
|
||||
version = "0.1.2"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=1b6cb170e925a43d605b3fed9f6b878e63e47744#1b6cb170e925a43d605b3fed9f6b878e63e47744"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=68d26955b3e24198a150315e7959719b03709dee#68d26955b3e24198a150315e7959719b03709dee"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"bitflags",
|
||||
@@ -2024,7 +2060,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rustpython-parser"
|
||||
version = "0.1.2"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=1b6cb170e925a43d605b3fed9f6b878e63e47744#1b6cb170e925a43d605b3fed9f6b878e63e47744"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=68d26955b3e24198a150315e7959719b03709dee#68d26955b3e24198a150315e7959719b03709dee"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"anyhow",
|
||||
@@ -2048,15 +2084,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.9"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8"
|
||||
checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.11"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
|
||||
checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde"
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
@@ -2091,6 +2127,12 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scoped-tls"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.1.0"
|
||||
@@ -2099,9 +2141,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
|
||||
[[package]]
|
||||
name = "scratch"
|
||||
version = "1.0.2"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898"
|
||||
checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2"
|
||||
|
||||
[[package]]
|
||||
name = "sct"
|
||||
@@ -2115,24 +2157,35 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.14"
|
||||
version = "1.0.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4"
|
||||
checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.148"
|
||||
version = "1.0.151"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e53f64bb4ba0191d6d0676e1b141ca55047d83b74f5607e6d8eb88126c52c2dc"
|
||||
checksum = "97fed41fc1a24994d044e6db6935e69511a1153b52c15eb42493b26fa87feba0"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.148"
|
||||
name = "serde-wasm-bindgen"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a55492425aa53521babf6137309e7d34c20bbfbbfcfe2c7f3a047fd1f6b92c0c"
|
||||
checksum = "e3b4c031cd0d9014307d82b8abf653c0290fbdaeb4c02d00c63cf52f728628bf"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"serde",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.151"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "255abe9a125a985c05190d687b320c12f9b1f0b99445e608c21ba0782c719ad8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -2208,9 +2261,9 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||
|
||||
[[package]]
|
||||
name = "str_indices"
|
||||
version = "0.4.0"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d9199fa80c817e074620be84374a520062ebac833f358d74b37060ce4a0f2c0"
|
||||
checksum = "5f026164926842ec52deb1938fae44f83dfdb82d0a5b0270c5bd5935ab74d6dd"
|
||||
|
||||
[[package]]
|
||||
name = "string_cache"
|
||||
@@ -2255,9 +2308,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.105"
|
||||
version = "1.0.107"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60b9b43d45702de4c839cb9b51d9f529c5dd26a4aff255b42b1ebc03e88ee908"
|
||||
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -2362,18 +2415,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.37"
|
||||
version = "1.0.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e"
|
||||
checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.37"
|
||||
version = "1.0.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb"
|
||||
checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -2447,9 +2500,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.5.9"
|
||||
version = "0.5.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7"
|
||||
checksum = "1333c76748e868a4d9d1017b5ab53171dfd095f70c712fdb4653a406547f598f"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
@@ -2536,9 +2589,9 @@ checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.5"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
|
||||
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-linebreak"
|
||||
@@ -2707,6 +2760,18 @@ dependencies = [
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-futures"
|
||||
version = "0.4.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.83"
|
||||
@@ -2736,6 +2801,30 @@ version = "0.2.83"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-test"
|
||||
version = "0.3.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09d2fff962180c3fadf677438054b1db62bee4aa32af26a45388af07d1287e1d"
|
||||
dependencies = [
|
||||
"console_error_panic_hook",
|
||||
"js-sys",
|
||||
"scoped-tls",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"wasm-bindgen-test-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-test-macro"
|
||||
version = "0.3.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4683da3dfc016f704c9f82cf401520c4f1cb3ee440f7f52b3d6ac29506a49ca7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.60"
|
||||
@@ -2758,9 +2847,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "webpki-roots"
|
||||
version = "0.22.5"
|
||||
version = "0.22.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "368bfe657969fb01238bb756d351dcade285e0f6fcbd36dcb23359a5169975be"
|
||||
checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87"
|
||||
dependencies = [
|
||||
"webpki",
|
||||
]
|
||||
|
||||
46
Cargo.toml
46
Cargo.toml
@@ -6,12 +6,19 @@ members = [
|
||||
|
||||
[package]
|
||||
name = "ruff"
|
||||
version = "0.0.193"
|
||||
version = "0.0.202"
|
||||
authors = ["Charlie Marsh <charlie.r.marsh@gmail.com>"]
|
||||
edition = "2021"
|
||||
rust-version = "1.65.0"
|
||||
documentation = "https://github.com/charliermarsh/ruff"
|
||||
homepage = "https://github.com/charliermarsh/ruff"
|
||||
repository = "https://github.com/charliermarsh/ruff"
|
||||
readme = "README.md"
|
||||
license = "MIT"
|
||||
|
||||
[lib]
|
||||
name = "ruff"
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[dependencies]
|
||||
annotate-snippets = { version = "0.9.1", features = ["color"] }
|
||||
@@ -20,9 +27,10 @@ atty = { version = "0.2.14" }
|
||||
bincode = { version = "1.3.3" }
|
||||
bitflags = { version = "1.3.2" }
|
||||
cachedir = { version = "0.3.0" }
|
||||
cfg-if = { version = "1.0.0" }
|
||||
chrono = { version = "0.4.21", default-features = false, features = ["clock"] }
|
||||
clap = { version = "4.0.1", features = ["derive"] }
|
||||
clap_complete_command = "0.4.0"
|
||||
clap_complete_command = { version = "0.4.0" }
|
||||
colored = { version = "2.0.0" }
|
||||
common-path = { version = "1.0.0" }
|
||||
dirs = { version = "4.0.0" }
|
||||
@@ -34,46 +42,57 @@ ignore = { version = "0.4.18" }
|
||||
itertools = { version = "0.10.5" }
|
||||
libcst = { git = "https://github.com/charliermarsh/LibCST", rev = "f2f0b7a487a8725d161fe8b3ed73a6758b21e177" }
|
||||
log = { version = "0.4.17" }
|
||||
natord = { version = "1.0.9" }
|
||||
nohash-hasher = { version = "0.2.0" }
|
||||
notify = { version = "5.0.0" }
|
||||
num-bigint = { version = "0.4.3" }
|
||||
once_cell = { version = "1.16.0" }
|
||||
path-absolutize = { version = "3.0.14", features = ["once_cell_cache", "use_unix_paths_on_wasm"] }
|
||||
quick-junit = { version = "0.3.2" }
|
||||
rayon = { version = "1.5.3" }
|
||||
regex = { version = "1.6.0" }
|
||||
ropey = { version = "1.5.0", features = ["cr_lines", "simd"], default-features = false }
|
||||
ruff_macros = { version = "0.0.193", path = "ruff_macros" }
|
||||
ruff_macros = { version = "0.0.202", path = "ruff_macros" }
|
||||
rustc-hash = { version = "1.1.0" }
|
||||
rustpython-ast = { features = ["unparse"], git = "https://github.com/RustPython/RustPython.git", rev = "1b6cb170e925a43d605b3fed9f6b878e63e47744" }
|
||||
rustpython-common = { git = "https://github.com/RustPython/RustPython.git", rev = "1b6cb170e925a43d605b3fed9f6b878e63e47744" }
|
||||
rustpython-parser = { features = ["lalrpop"], git = "https://github.com/RustPython/RustPython.git", rev = "1b6cb170e925a43d605b3fed9f6b878e63e47744" }
|
||||
rustpython-ast = { features = ["unparse"], git = "https://github.com/RustPython/RustPython.git", rev = "68d26955b3e24198a150315e7959719b03709dee" }
|
||||
rustpython-common = { git = "https://github.com/RustPython/RustPython.git", rev = "68d26955b3e24198a150315e7959719b03709dee" }
|
||||
rustpython-parser = { features = ["lalrpop"], git = "https://github.com/RustPython/RustPython.git", rev = "68d26955b3e24198a150315e7959719b03709dee" }
|
||||
schemars = { version = "0.8.11" }
|
||||
semver = { version = "1.0.16" }
|
||||
serde = { version = "1.0.147", features = ["derive"] }
|
||||
serde_json = { version = "1.0.87" }
|
||||
shellexpand = { version = "3.0.0" }
|
||||
similar = { version = "2.2.1" }
|
||||
strum = { version = "0.24.1", features = ["strum_macros"] }
|
||||
strum_macros = { version = "0.24.3" }
|
||||
textwrap = { version = "0.16.0" }
|
||||
titlecase = { version = "2.2.1" }
|
||||
toml = { version = "0.5.9" }
|
||||
update-informer = { version = "0.5.0", default-features = false, features = ["pypi"], optional = true }
|
||||
walkdir = { version = "2.3.2" }
|
||||
|
||||
[target.'cfg(not(target_family = "wasm"))'.dependencies]
|
||||
clearscreen = { version = "1.0.10" } # uses which
|
||||
clearscreen = { version = "1.0.10" }
|
||||
rayon = { version = "1.5.3" }
|
||||
update-informer = { version = "0.5.0", default-features = false, features = ["pypi"], optional = true }
|
||||
|
||||
# https://docs.rs/getrandom/0.2.7/getrandom/#webassembly-support
|
||||
# For (future) wasm-pack support
|
||||
[target.'cfg(all(target_family = "wasm", target_os = "unknown"))'.dependencies]
|
||||
getrandom = { version = "0.2.7", features = ["js"] }
|
||||
console_error_panic_hook = { version = "0.1.7" }
|
||||
console_log = { version = "0.2.0" }
|
||||
serde-wasm-bindgen = { version = "0.4" }
|
||||
js-sys = { version = "0.3.60" }
|
||||
wasm-bindgen = { version = "0.2.83" }
|
||||
|
||||
[dev-dependencies]
|
||||
assert_cmd = { version = "2.0.4" }
|
||||
criterion = { version = "0.4.0" }
|
||||
insta = { version = "1.19.1", features = ["yaml"] }
|
||||
test-case = { version = "2.2.2" }
|
||||
ureq = { version = "2.5.0", features = [] }
|
||||
wasm-bindgen-test = { version = "0.3.33" }
|
||||
|
||||
[target.'cfg(not(target_family = "wasm"))'.dev-dependencies]
|
||||
assert_cmd = { version = "2.0.4" }
|
||||
criterion = { version = "0.4.0" }
|
||||
|
||||
[features]
|
||||
default = ["update-informer"]
|
||||
@@ -91,6 +110,11 @@ opt-level = 3
|
||||
[profile.dev.package.similar]
|
||||
opt-level = 3
|
||||
|
||||
# Reduce complexity of a parser function that would trigger a locals limit in a wasm tool.
|
||||
# https://github.com/bytecodealliance/wasm-tools/blob/b5c3d98e40590512a3b12470ef358d5c7b983b15/crates/wasmparser/src/limits.rs#L29
|
||||
[profile.dev.package.rustpython-parser]
|
||||
opt-level = 1
|
||||
|
||||
[[bench]]
|
||||
name = "source_code_locator"
|
||||
harness = false
|
||||
|
||||
25
LICENSE
25
LICENSE
@@ -388,6 +388,31 @@ are:
|
||||
SOFTWARE.
|
||||
"""
|
||||
|
||||
- flake8-implicit-str-concat, licensed as follows:
|
||||
"""
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2019 Dylan Turner
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
"""
|
||||
|
||||
- flake8-import-conventions, licensed as follows:
|
||||
"""
|
||||
MIT License
|
||||
|
||||
309
README.md
309
README.md
@@ -23,15 +23,20 @@ An extremely fast Python linter, written in Rust.
|
||||
- 🔧 Autofix support, for automatic error correction (e.g., automatically remove unused imports)
|
||||
- ⚖️ [Near-parity](#how-does-ruff-compare-to-flake8) with the built-in Flake8 rule set
|
||||
- 🔌 Native re-implementations of popular Flake8 plugins, like [`flake8-bugbear`](https://pypi.org/project/flake8-bugbear/)
|
||||
- 🌎 Monorepo-friendly configuration via hierarchical and cascading settings
|
||||
|
||||
Ruff aims to be orders of magnitude faster than alternative tools while integrating more
|
||||
functionality behind a single, common interface. Ruff can be used to replace Flake8 (plus a variety
|
||||
of plugins), [`isort`](https://pypi.org/project/isort/), [`pydocstyle`](https://pypi.org/project/pydocstyle/),
|
||||
[`yesqa`](https://github.com/asottile/yesqa), [`eradicate`](https://pypi.org/project/eradicate/),
|
||||
and even a subset of [`pyupgrade`](https://pypi.org/project/pyupgrade/) and [`autoflake`](https://pypi.org/project/autoflake/)
|
||||
all while executing tens or hundreds of times faster than any individual tool. Ruff goes beyond the
|
||||
responsibilities of a traditional linter, instead functioning as an advanced code transformation
|
||||
tool capable of upgrading type annotations, rewriting class definitions, sorting imports, and more.
|
||||
functionality behind a single, common interface.
|
||||
|
||||
Ruff can be used to replace Flake8 (plus a variety of plugins), [`isort`](https://pypi.org/project/isort/),
|
||||
[`pydocstyle`](https://pypi.org/project/pydocstyle/), [`yesqa`](https://github.com/asottile/yesqa),
|
||||
[`eradicate`](https://pypi.org/project/eradicate/), [`pyupgrade`](https://pypi.org/project/pyupgrade/),
|
||||
and [`autoflake`](https://pypi.org/project/autoflake/), all while executing tens or hundreds of
|
||||
times faster than any individual tool.
|
||||
|
||||
Ruff goes beyond the responsibilities of a traditional linter, instead functioning as an advanced
|
||||
code transformation tool capable of upgrading type annotations, rewriting class definitions, sorting
|
||||
imports, and more.
|
||||
|
||||
Ruff is extremely actively developed and used in major open-source projects like:
|
||||
|
||||
@@ -39,6 +44,7 @@ Ruff is extremely actively developed and used in major open-source projects like
|
||||
- [Bokeh](https://github.com/bokeh/bokeh)
|
||||
- [Zulip](https://github.com/zulip/zulip)
|
||||
- [Pydantic](https://github.com/pydantic/pydantic)
|
||||
- [Sphinx](https://github.com/sphinx-doc/sphinx)
|
||||
- [Hatch](https://github.com/pypa/hatch)
|
||||
- [Jupyter](https://github.com/jupyter-server/jupyter_server)
|
||||
- [Synapse](https://github.com/matrix-org/synapse)
|
||||
@@ -89,6 +95,7 @@ of [Conda](https://docs.conda.io/en/latest/):
|
||||
1. [flake8-comprehensions (C4)](#flake8-comprehensions-c4)
|
||||
1. [flake8-debugger (T10)](#flake8-debugger-t10)
|
||||
1. [flake8-errmsg (EM)](#flake8-errmsg-em)
|
||||
1. [flake8-implicit-str-concat (ISC)](#flake8-implicit-str-concat-isc)
|
||||
1. [flake8-import-conventions (ICN)](#flake8-import-conventions-icn)
|
||||
1. [flake8-print (T20)](#flake8-print-t20)
|
||||
1. [flake8-quotes (Q)](#flake8-quotes-q)
|
||||
@@ -162,7 +169,7 @@ Ruff also works with [pre-commit](https://pre-commit.com):
|
||||
```yaml
|
||||
- repo: https://github.com/charliermarsh/ruff-pre-commit
|
||||
# Ruff version.
|
||||
rev: 'v0.0.193'
|
||||
rev: 'v0.0.202'
|
||||
hooks:
|
||||
- id: ruff
|
||||
# Respect `exclude` and `extend-exclude` settings.
|
||||
@@ -214,21 +221,14 @@ dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
|
||||
# Assume Python 3.10.
|
||||
target-version = "py310"
|
||||
|
||||
[tool.ruff.flake8-import-conventions.aliases]
|
||||
altair = "alt"
|
||||
"matplotlib.pyplot" = "plt"
|
||||
numpy = "np"
|
||||
pandas = "pd"
|
||||
seaborn = "sns"
|
||||
|
||||
[tool.ruff.mccabe]
|
||||
# Unlike Flake8, default to a complexity level of 10.
|
||||
max-complexity = 10
|
||||
```
|
||||
|
||||
As an example, the following would configure Ruff to: (1) avoid checking for line-length
|
||||
violations (`E501`); (2), always autofix, but never remove unused imports (`F401`); and (3) ignore
|
||||
import-at-top-of-file errors (`E402`) in `__init__.py` files:
|
||||
violations (`E501`); (2) never remove unused imports (`F401`); and (3) ignore import-at-top-of-file
|
||||
errors (`E402`) in `__init__.py` files:
|
||||
|
||||
```toml
|
||||
[tool.ruff]
|
||||
@@ -238,8 +238,7 @@ select = ["E", "F"]
|
||||
# Never enforce `E501` (line length violations).
|
||||
ignore = ["E501"]
|
||||
|
||||
# Always autofix, but never try to fix `F401` (unused imports).
|
||||
fix = true
|
||||
# Never try to fix `F401` (unused imports).
|
||||
unfixable = ["F401"]
|
||||
|
||||
# Ignore `E402` (import violations) in all `__init__.py` files, and in `path/to/file.py`.
|
||||
@@ -259,6 +258,38 @@ select = ["E", "F", "Q"]
|
||||
docstring-quotes = "double"
|
||||
```
|
||||
|
||||
Ruff mirrors Flake8's error code system, in which each error code consists of a one-to-three letter
|
||||
prefix, followed by three digits (e.g., `F401`). The prefix indicates that "source" of the error
|
||||
code (e.g., `F` for Pyflakes, `E` for `pycodestyle`, `ANN` for `flake8-annotations`). The set of
|
||||
enabled errors is determined by the `select` and `ignore` options, which support both the full
|
||||
error code (e.g., `F401`) and the prefix (e.g., `F`).
|
||||
|
||||
As a special-case, Ruff also supports the `ALL` error code, which enables all error codes. Note that
|
||||
some of the `pydocstyle` error codes are conflicting (e.g., `D203` and `D211`) as they represent
|
||||
alternative docstring formats. Enabling `ALL` without further configuration may result in suboptimal
|
||||
behavior, especially for the `pydocstyle` plugin.
|
||||
|
||||
As an alternative to `pyproject.toml`, Ruff will also respect a `ruff.toml` file, which implements
|
||||
an equivalent schema (though the `[tool.ruff]` hierarchy can be omitted). For example, the above
|
||||
`pyproject.toml` described above would be represented via the following `ruff.toml`:
|
||||
|
||||
```toml
|
||||
# Enable Pyflakes and pycodestyle rules.
|
||||
select = ["E", "F"]
|
||||
|
||||
# Never enforce `E501` (line length violations).
|
||||
ignore = ["E501"]
|
||||
|
||||
# Always autofix, but never try to fix `F401` (unused imports).
|
||||
fix = true
|
||||
unfixable = ["F401"]
|
||||
|
||||
# Ignore `E402` (import violations) in all `__init__.py` files, and in `path/to/file.py`.
|
||||
[per-file-ignores]
|
||||
"__init__.py" = ["E402"]
|
||||
"path/to/file.py" = ["E402"]
|
||||
```
|
||||
|
||||
For a full list of configurable options, see the [API reference](#reference).
|
||||
|
||||
Some common configuration settings can be provided via the command-line:
|
||||
@@ -279,7 +310,7 @@ Arguments:
|
||||
|
||||
Options:
|
||||
--config <CONFIG>
|
||||
Path to the `pyproject.toml` file to use for configuration
|
||||
Path to the `pyproject.toml` or `ruff.toml` file to use for configuration
|
||||
-v, --verbose
|
||||
Enable verbose logging
|
||||
-q, --quiet
|
||||
@@ -292,14 +323,18 @@ Options:
|
||||
Run in watch mode by re-running whenever files change
|
||||
--fix
|
||||
Attempt to automatically fix lint errors
|
||||
--fix-only
|
||||
Fix any fixable lint errors, but don't report on leftover violations. Implies `--fix`
|
||||
--diff
|
||||
Avoid writing any fixed files back; instead, output a diff for each changed file to stdout
|
||||
-n, --no-cache
|
||||
Disable cache reads
|
||||
--select <SELECT>
|
||||
List of error codes to enable
|
||||
Comma-separated list of error codes to enable (or ALL, to enable all checks)
|
||||
--extend-select <EXTEND_SELECT>
|
||||
Like --select, but adds additional error codes on top of the selected ones
|
||||
--ignore <IGNORE>
|
||||
List of error codes to ignore
|
||||
Comma-separated list of error codes to disable
|
||||
--extend-ignore <EXTEND_IGNORE>
|
||||
Like --ignore, but adds additional error codes on top of the ignored ones
|
||||
--exclude <EXCLUDE>
|
||||
@@ -313,19 +348,21 @@ Options:
|
||||
--per-file-ignores <PER_FILE_IGNORES>
|
||||
List of mappings from file pattern to code to exclude
|
||||
--format <FORMAT>
|
||||
Output serialization format for error messages [possible values: text, json, junit, grouped, github]
|
||||
Output serialization format for error messages [possible values: text, json, junit, grouped, github, gitlab]
|
||||
--show-source
|
||||
Show violations with source code
|
||||
--respect-gitignore
|
||||
Respect file exclusions via `.gitignore` and other standard ignore files
|
||||
--force-exclude
|
||||
Enforce exclusions, even for paths passed to Ruff directly on the command-line
|
||||
--update-check
|
||||
Enable or disable automatic update checks
|
||||
--show-files
|
||||
See the files Ruff will be run against with the current settings
|
||||
--show-settings
|
||||
See the settings Ruff will use to check a given Python file
|
||||
--add-noqa
|
||||
Enable automatic additions of noqa directives to failing lines
|
||||
Enable automatic additions of `noqa` directives to failing lines
|
||||
--dummy-variable-rgx <DUMMY_VARIABLE_RGX>
|
||||
Regular expression matching the name of dummy variables
|
||||
--target-version <TARGET_VERSION>
|
||||
@@ -333,7 +370,7 @@ Options:
|
||||
--line-length <LINE_LENGTH>
|
||||
Set the line-length for length-associated checks and automatic formatting
|
||||
--max-complexity <MAX_COMPLEXITY>
|
||||
Max McCabe complexity allowed for a function
|
||||
Maximum McCabe complexity allowed for a given function
|
||||
--stdin-filename <STDIN_FILENAME>
|
||||
The name of the file when passing it through stdin
|
||||
--explain <EXPLAIN>
|
||||
@@ -383,6 +420,9 @@ extend = "../pyproject.toml"
|
||||
line-length = 100
|
||||
```
|
||||
|
||||
All of the above rules apply equivalently to `ruff.toml` files. If Ruff detects both a `ruff.toml`
|
||||
and `pyproject.toml` file, it will defer to the `ruff.toml`.
|
||||
|
||||
### Python file discovery
|
||||
|
||||
When passed a path on the command-line, Ruff will automatically discover all Python files in that
|
||||
@@ -620,7 +660,7 @@ For more, see [pyupgrade](https://pypi.org/project/pyupgrade/3.2.0/) on PyPI.
|
||||
| UP001 | UselessMetaclassType | `__metaclass__ = type` is implied | 🛠 |
|
||||
| UP003 | TypeOfPrimitive | Use `str` instead of `type(...)` | 🛠 |
|
||||
| UP004 | UselessObjectInheritance | Class `...` inherits from object | 🛠 |
|
||||
| UP005 | DeprecatedUnittestAlias | `assertEquals` is deprecated, use `assertEqual` instead | 🛠 |
|
||||
| UP005 | DeprecatedUnittestAlias | `assertEquals` is deprecated, use `assertEqual` | 🛠 |
|
||||
| UP006 | UsePEP585Annotation | Use `list` instead of `List` for type annotations | 🛠 |
|
||||
| UP007 | UsePEP604Annotation | Use `X \| Y` for type annotations | 🛠 |
|
||||
| UP008 | SuperCallWithParameters | Use `super()` instead of `super(__class__, self)` | 🛠 |
|
||||
@@ -634,6 +674,12 @@ For more, see [pyupgrade](https://pypi.org/project/pyupgrade/3.2.0/) on PyPI.
|
||||
| UP016 | RemoveSixCompat | Unnecessary `six` compatibility usage | 🛠 |
|
||||
| UP017 | DatetimeTimezoneUTC | Use `datetime.UTC` alias | 🛠 |
|
||||
| UP018 | NativeLiterals | Unnecessary call to `str` and `bytes` | 🛠 |
|
||||
| UP019 | TypingTextStrAlias | `typing.Text` is deprecated, use `str` | 🛠 |
|
||||
| UP020 | OpenAlias | Use builtin `open` | 🛠 |
|
||||
| UP021 | ReplaceUniversalNewlines | `universal_newlines` is deprecated, use `text` | 🛠 |
|
||||
| UP022 | ReplaceStdoutStderr | Sending stdout and stderr to pipe is deprecated, use `capture_output` | 🛠 |
|
||||
| UP023 | RewriteCElementTree | `cElementTree` is deprecated, use `ElementTree` | 🛠 |
|
||||
| UP025 | RewriteUnicodeLiteral | Remove unicode literals from strings | 🛠 |
|
||||
|
||||
### pep8-naming (N)
|
||||
|
||||
@@ -809,6 +855,16 @@ For more, see [flake8-errmsg](https://pypi.org/project/flake8-errmsg/0.4.0/) on
|
||||
| EM102 | FStringInException | Exception must not use an f-string literal, assign to variable first | |
|
||||
| EM103 | DotFormatInException | Exception must not use a `.format()` string directly, assign to variable first | |
|
||||
|
||||
### flake8-implicit-str-concat (ISC)
|
||||
|
||||
For more, see [flake8-implicit-str-concat](https://pypi.org/project/flake8-implicit-str-concat/0.3.0/) on PyPI.
|
||||
|
||||
| Code | Name | Message | Fix |
|
||||
| ---- | ---- | ------- | --- |
|
||||
| ISC001 | SingleLineImplicitStringConcatenation | Implicitly concatenated string literals on one line | |
|
||||
| ISC002 | MultiLineImplicitStringConcatenation | Implicitly concatenated string literals over continuation line | |
|
||||
| ISC003 | ExplicitStringConcatenation | Explicitly concatenated string should be implicitly concatenated | |
|
||||
|
||||
### flake8-import-conventions (ICN)
|
||||
|
||||
| Code | Name | Message | Fix |
|
||||
@@ -864,6 +920,7 @@ For more, see [flake8-tidy-imports](https://pypi.org/project/flake8-tidy-imports
|
||||
|
||||
| Code | Name | Message | Fix |
|
||||
| ---- | ---- | ------- | --- |
|
||||
| TID251 | BannedApi | `...` is banned: ... | |
|
||||
| TID252 | BannedRelativeImport | Relative imports are banned | |
|
||||
|
||||
### flake8-unused-arguments (ARG)
|
||||
@@ -930,6 +987,7 @@ For more, see [pygrep-hooks](https://github.com/pre-commit/pygrep-hooks) on GitH
|
||||
| PGH001 | NoEval | No builtin `eval()` allowed | |
|
||||
| PGH002 | DeprecatedLogWarn | `warn` is deprecated in favor of `warning` | |
|
||||
| PGH003 | BlanketTypeIgnore | Use specific error codes when ignoring type issues | |
|
||||
| PGH004 | BlanketNOQA | Use specific error codes when using `noqa` | |
|
||||
|
||||
### Pylint (PLC, PLE, PLR, PLW)
|
||||
|
||||
@@ -957,6 +1015,7 @@ For more, see [Pylint](https://pypi.org/project/pylint/2.15.7/) on PyPI.
|
||||
| RUF001 | AmbiguousUnicodeCharacterString | String contains ambiguous unicode character '𝐁' (did you mean 'B'?) | 🛠 |
|
||||
| RUF002 | AmbiguousUnicodeCharacterDocstring | Docstring contains ambiguous unicode character '𝐁' (did you mean 'B'?) | 🛠 |
|
||||
| RUF003 | AmbiguousUnicodeCharacterComment | Comment contains ambiguous unicode character '𝐁' (did you mean 'B'?) | |
|
||||
| RUF004 | KeywordArgumentBeforeStarArgument | Keyword argument `...` must come after starred arguments | |
|
||||
| RUF100 | UnusedNOQA | Unused blanket `noqa` directive | 🛠 |
|
||||
|
||||
<!-- End auto-generated sections. -->
|
||||
@@ -1226,10 +1285,12 @@ natively, including:
|
||||
- [`flake8-docstrings`](https://pypi.org/project/flake8-docstrings/)
|
||||
- [`flake8-eradicate`](https://pypi.org/project/flake8-eradicate/)
|
||||
- [`flake8-errmsg`](https://pypi.org/project/flake8-errmsg/)
|
||||
- [`flake8-implicit-str-concat`](https://pypi.org/project/flake8-implicit-str-concat/)
|
||||
- [`flake8-import-conventions`](https://github.com/joaopalmeiro/flake8-import-conventions)
|
||||
- [`flake8-print`](https://pypi.org/project/flake8-print/)
|
||||
- [`flake8-quotes`](https://pypi.org/project/flake8-quotes/)
|
||||
- [`flake8-return`](https://pypi.org/project/flake8-return/)
|
||||
- [`flake8-simplify`](https://pypi.org/project/flake8-simplify/) (1/37)
|
||||
- [`flake8-super`](https://pypi.org/project/flake8-super/)
|
||||
- [`flake8-tidy-imports`](https://pypi.org/project/flake8-tidy-imports/) (1/3)
|
||||
- [`isort`](https://pypi.org/project/isort/)
|
||||
@@ -1237,7 +1298,7 @@ natively, including:
|
||||
- [`pep8-naming`](https://pypi.org/project/pep8-naming/)
|
||||
- [`pydocstyle`](https://pypi.org/project/pydocstyle/)
|
||||
- [`pygrep-hooks`](https://github.com/pre-commit/pygrep-hooks) (3/10)
|
||||
- [`pyupgrade`](https://pypi.org/project/pyupgrade/) (18/33)
|
||||
- [`pyupgrade`](https://pypi.org/project/pyupgrade/) (20/33)
|
||||
- [`yesqa`](https://github.com/asottile/yesqa)
|
||||
|
||||
Note that, in some cases, Ruff uses different error code prefixes than would be found in the
|
||||
@@ -1281,10 +1342,12 @@ Today, Ruff can be used to replace Flake8 when used with any of the following pl
|
||||
- [`flake8-docstrings`](https://pypi.org/project/flake8-docstrings/)
|
||||
- [`flake8-eradicate`](https://pypi.org/project/flake8-eradicate/)
|
||||
- [`flake8-errmsg`](https://pypi.org/project/flake8-errmsg/)
|
||||
- [`flake8-implicit-str-concat`](https://pypi.org/project/flake8-implicit-str-concat/)
|
||||
- [`flake8-import-conventions`](https://github.com/joaopalmeiro/flake8-import-conventions)
|
||||
- [`flake8-print`](https://pypi.org/project/flake8-print/)
|
||||
- [`flake8-quotes`](https://pypi.org/project/flake8-quotes/)
|
||||
- [`flake8-return`](https://pypi.org/project/flake8-return/)
|
||||
- [`flake8-simplify`](https://pypi.org/project/flake8-simplify/) (1/37)
|
||||
- [`flake8-super`](https://pypi.org/project/flake8-super/)
|
||||
- [`flake8-tidy-imports`](https://pypi.org/project/flake8-tidy-imports/) (1/3)
|
||||
- [`mccabe`](https://pypi.org/project/mccabe/)
|
||||
@@ -1294,7 +1357,7 @@ Today, Ruff can be used to replace Flake8 when used with any of the following pl
|
||||
Ruff can also replace [`isort`](https://pypi.org/project/isort/),
|
||||
[`yesqa`](https://github.com/asottile/yesqa), [`eradicate`](https://pypi.org/project/eradicate/),
|
||||
[`pygrep-hooks`](https://github.com/pre-commit/pygrep-hooks) (3/10), and a subset of the rules
|
||||
implemented in [`pyupgrade`](https://pypi.org/project/pyupgrade/) (17/33).
|
||||
implemented in [`pyupgrade`](https://pypi.org/project/pyupgrade/) (20/33).
|
||||
|
||||
If you're looking to use Ruff, but rely on an unsupported Flake8 plugin, free to file an Issue.
|
||||
|
||||
@@ -1341,6 +1404,22 @@ src = ["src", "tests"]
|
||||
known-first-party = ["my_module1", "my_module2"]
|
||||
```
|
||||
|
||||
### Does Ruff support Jupyter Notebooks?
|
||||
|
||||
Ruff is integrated into [nbQA](https://github.com/nbQA-dev/nbQA), a tool for running linters and
|
||||
code formatters over Jupyter Notebooks.
|
||||
|
||||
After installing `ruff` and `nbqa`, you can run Ruff over a notebook like so:
|
||||
|
||||
```shell
|
||||
> nbqa ruff Untitled.ipynb
|
||||
Untitled.ipynb:cell_1:2:5: F841 Local variable `x` is assigned to but never used
|
||||
Untitled.ipynb:cell_2:1:1: E402 Module level import not at top of file
|
||||
Untitled.ipynb:cell_2:1:8: F401 `os` imported but unused
|
||||
Found 3 error(s).
|
||||
1 potentially fixable with the --fix option.
|
||||
```
|
||||
|
||||
### Does Ruff support NumPy- or Google-style docstrings?
|
||||
|
||||
Yes! To enable a specific docstring convention, start by enabling all `pydocstyle` error codes, and
|
||||
@@ -1411,6 +1490,18 @@ extend-ignore = [
|
||||
]
|
||||
```
|
||||
|
||||
Note that Ruff _also_ supports a [`convention`](#convention) setting:
|
||||
|
||||
```toml
|
||||
[tool.ruff.pydocstyle]
|
||||
convention = "google"
|
||||
```
|
||||
|
||||
However, this setting is purely used to implement robust detection of Google and NumPy-style
|
||||
sections, and thus avoid the [false negatives](https://github.com/PyCQA/pydocstyle/issues/459) seen
|
||||
in `pydocstyle`; it does not affect which errors are enabled, which is driven by the `select` and
|
||||
`ignore` settings, as described above.
|
||||
|
||||
## Development
|
||||
|
||||
Ruff is written in Rust (1.65.0). You'll need to install the [Rust toolchain](https://www.rust-lang.org/tools/install)
|
||||
@@ -1426,8 +1517,8 @@ For development, we use [nightly Rust](https://rust-lang.github.io/rustup/concep
|
||||
|
||||
```shell
|
||||
cargo +nightly fmt
|
||||
cargo +nightly clippy
|
||||
cargo +nightly test
|
||||
cargo +nightly clippy --fix --workspace --all-targets --all-features -- -W clippy::pedantic
|
||||
cargo +nightly test --all
|
||||
```
|
||||
|
||||
## Releases
|
||||
@@ -1798,6 +1889,23 @@ fix = true
|
||||
|
||||
---
|
||||
|
||||
#### [`fix-only`](#fix-only)
|
||||
|
||||
Like `fix`, but disables reporting on leftover violation. Implies `fix`.
|
||||
|
||||
**Default value**: `false`
|
||||
|
||||
**Type**: `bool`
|
||||
|
||||
**Example usage**:
|
||||
|
||||
```toml
|
||||
[tool.ruff]
|
||||
fix-only = true
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### [`fixable`](#fixable)
|
||||
|
||||
A list of check code prefixes to consider autofix-able.
|
||||
@@ -1846,8 +1954,9 @@ force-exclude = true
|
||||
|
||||
The style in which violation messages should be formatted: `"text"`
|
||||
(default), `"grouped"` (group messages by file), `"json"`
|
||||
(machine-readable), `"junit"` (machine-readable XML), or `"github"`
|
||||
(GitHub Actions annotations).
|
||||
(machine-readable), `"junit"` (machine-readable XML), `"github"`
|
||||
(GitHub Actions annotations) or `"gitlab"`
|
||||
(GitLab CI code quality report).
|
||||
|
||||
**Default value**: `"text"`
|
||||
|
||||
@@ -1948,6 +2057,25 @@ when considering any matching files.
|
||||
|
||||
---
|
||||
|
||||
#### [`required-version`](#required-version)
|
||||
|
||||
Require a specific version of Ruff to be running (useful for unifying
|
||||
results across many environments, e.g., with a `pyproject.toml`
|
||||
file).
|
||||
|
||||
**Default value**: `None`
|
||||
|
||||
**Type**: `String`
|
||||
|
||||
**Example usage**:
|
||||
|
||||
```toml
|
||||
[tool.ruff]
|
||||
required-version = "0.0.193"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### [`respect-gitignore`](#respect-gitignore)
|
||||
|
||||
Whether to automatically exclude files that are ignored by `.ignore`,
|
||||
@@ -2090,6 +2218,24 @@ unfixable = ["F401"]
|
||||
|
||||
---
|
||||
|
||||
#### [`update-check`](#update-check)
|
||||
|
||||
Enable or disable automatic update checks (overridden by the
|
||||
`--update-check` and `--no-update-check` command-line flags).
|
||||
|
||||
**Default value**: `true`
|
||||
|
||||
**Type**: `bool`
|
||||
|
||||
**Example usage**:
|
||||
|
||||
```toml
|
||||
[tool.ruff]
|
||||
update-check = false
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `flake8-annotations`
|
||||
|
||||
#### [`allow-star-arg-any`](#allow-star-arg-any)
|
||||
@@ -2333,7 +2479,7 @@ multiline-quotes = "single"
|
||||
#### [`ban-relative-imports`](#ban-relative-imports)
|
||||
|
||||
Whether to ban all relative imports (`"all"`), or only those imports
|
||||
that extend into the parent module and beyond (`"parents"`).
|
||||
that extend into the parent module or beyond (`"parents"`).
|
||||
|
||||
**Default value**: `"parents"`
|
||||
|
||||
@@ -2349,6 +2495,27 @@ ban-relative-imports = "all"
|
||||
|
||||
---
|
||||
|
||||
#### [`banned-api`](#banned-api)
|
||||
|
||||
Specific modules or module members that may not be imported or accessed.
|
||||
Note that this check is only meant to flag accidental uses,
|
||||
and can be circumvented via `eval` or `importlib`.
|
||||
|
||||
**Default value**: `{}`
|
||||
|
||||
**Type**: `HashMap<String, BannedApi>`
|
||||
|
||||
**Example usage**:
|
||||
|
||||
```toml
|
||||
[tool.ruff.flake8-tidy-imports]
|
||||
[tool.ruff.flake8-tidy-imports.banned-api]
|
||||
"cgi".msg = "The cgi module is deprecated, see https://peps.python.org/pep-0594/#cgi."
|
||||
"typing.TypedDict".msg = "Use typing_extensions.TypedDict instead."
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `flake8-unused-arguments`
|
||||
|
||||
#### [`ignore-variadic-names`](#ignore-variadic-names)
|
||||
@@ -2406,6 +2573,23 @@ extra-standard-library = ["path"]
|
||||
|
||||
---
|
||||
|
||||
#### [`force-single-line`](#force-single-line)
|
||||
|
||||
Forces all from imports to appear on their own line.
|
||||
|
||||
**Default value**: `false`
|
||||
|
||||
**Type**: `bool`
|
||||
|
||||
**Example usage**:
|
||||
|
||||
```toml
|
||||
[tool.ruff.isort]
|
||||
force-single-line = true
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### [`force-wrap-aliases`](#force-wrap-aliases)
|
||||
|
||||
Force `import from` statements with multiple members and at least one
|
||||
@@ -2475,6 +2659,43 @@ known-third-party = ["src"]
|
||||
|
||||
---
|
||||
|
||||
#### [`single-line-exclusions`](#single-line-exclusions)
|
||||
|
||||
One or more modules to exclude from the single line rule.
|
||||
|
||||
**Default value**: `[]`
|
||||
|
||||
**Type**: `Vec<String>`
|
||||
|
||||
**Example usage**:
|
||||
|
||||
```toml
|
||||
[tool.ruff.isort]
|
||||
single-line-exclusions = ["os", "json"]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### [`split-on-trailing-comma`](#split-on-trailing-comma)
|
||||
|
||||
If a comma is placed after the last member in a multi-line import, then
|
||||
the imports will never be folded into one line.
|
||||
|
||||
See isort's [`split-on-trailing-comma`](https://pycqa.github.io/isort/docs/configuration/options.html#split-on-trailing-comma) option.
|
||||
|
||||
**Default value**: `true`
|
||||
|
||||
**Type**: `bool`
|
||||
|
||||
**Example usage**:
|
||||
|
||||
```toml
|
||||
[tool.ruff.isort]
|
||||
split-on-trailing-comma = false
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `mccabe`
|
||||
|
||||
#### [`max-complexity`](#max-complexity)
|
||||
@@ -2556,6 +2777,28 @@ staticmethod-decorators = ["staticmethod", "stcmthd"]
|
||||
|
||||
---
|
||||
|
||||
### `pydocstyle`
|
||||
|
||||
#### [`convention`](#convention)
|
||||
|
||||
Whether to use Google-style or Numpy-style conventions when detecting
|
||||
docstring sections. By default, conventions will be inferred from
|
||||
the available sections.
|
||||
|
||||
**Default value**: `None`
|
||||
|
||||
**Type**: `Convention`
|
||||
|
||||
**Example usage**:
|
||||
|
||||
```toml
|
||||
[tool.ruff.pydocstyle]
|
||||
# Use Google-style docstrings.
|
||||
convention = "google"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `pyupgrade`
|
||||
|
||||
#### [`keep-runtime-typing`](#keep-runtime-typing)
|
||||
|
||||
4
flake8_to_ruff/Cargo.lock
generated
4
flake8_to_ruff/Cargo.lock
generated
@@ -771,7 +771,7 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
|
||||
|
||||
[[package]]
|
||||
name = "flake8_to_ruff"
|
||||
version = "0.0.193"
|
||||
version = "0.0.202"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
@@ -1975,7 +1975,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.0.193"
|
||||
version = "0.0.202"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "flake8-to-ruff"
|
||||
version = "0.0.193-dev.0"
|
||||
version = "0.0.202-dev.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
|
||||
@@ -4,11 +4,12 @@ use anyhow::Result;
|
||||
use ruff::checks_gen::CheckCodePrefix;
|
||||
use ruff::flake8_quotes::settings::Quote;
|
||||
use ruff::flake8_tidy_imports::settings::Strictness;
|
||||
use ruff::pydocstyle::settings::Convention;
|
||||
use ruff::settings::options::Options;
|
||||
use ruff::settings::pyproject::Pyproject;
|
||||
use ruff::{
|
||||
flake8_annotations, flake8_bugbear, flake8_errmsg, flake8_quotes, flake8_tidy_imports, mccabe,
|
||||
pep8_naming,
|
||||
pep8_naming, pydocstyle,
|
||||
};
|
||||
|
||||
use crate::black::Black;
|
||||
@@ -91,6 +92,7 @@ pub fn convert(
|
||||
let mut flake8_tidy_imports = flake8_tidy_imports::settings::Options::default();
|
||||
let mut mccabe = mccabe::settings::Options::default();
|
||||
let mut pep8_naming = pep8_naming::settings::Options::default();
|
||||
let mut pydocstyle = pydocstyle::settings::Options::default();
|
||||
for (key, value) in flake8 {
|
||||
if let Some(value) = value {
|
||||
match key.as_str() {
|
||||
@@ -162,17 +164,17 @@ pub fn convert(
|
||||
// flake8-quotes
|
||||
"quotes" | "inline-quotes" | "inline_quotes" => match value.trim() {
|
||||
"'" | "single" => flake8_quotes.inline_quotes = Some(Quote::Single),
|
||||
"\"" | "double" => flake8_quotes.inline_quotes = Some(Quote::Single),
|
||||
"\"" | "double" => flake8_quotes.inline_quotes = Some(Quote::Double),
|
||||
_ => eprintln!("Unexpected '{key}' value: {value}"),
|
||||
},
|
||||
"multiline-quotes" | "multiline_quotes" => match value.trim() {
|
||||
"'" | "single" => flake8_quotes.multiline_quotes = Some(Quote::Single),
|
||||
"\"" | "double" => flake8_quotes.multiline_quotes = Some(Quote::Single),
|
||||
"\"" | "double" => flake8_quotes.multiline_quotes = Some(Quote::Double),
|
||||
_ => eprintln!("Unexpected '{key}' value: {value}"),
|
||||
},
|
||||
"docstring-quotes" | "docstring_quotes" => match value.trim() {
|
||||
"'" | "single" => flake8_quotes.docstring_quotes = Some(Quote::Single),
|
||||
"\"" | "double" => flake8_quotes.docstring_quotes = Some(Quote::Single),
|
||||
"\"" | "double" => flake8_quotes.docstring_quotes = Some(Quote::Double),
|
||||
_ => eprintln!("Unexpected '{key}' value: {value}"),
|
||||
},
|
||||
"avoid-escape" | "avoid_escape" => match parser::parse_bool(value.as_ref()) {
|
||||
@@ -200,9 +202,12 @@ pub fn convert(
|
||||
_ => eprintln!("Unexpected '{key}' value: {value}"),
|
||||
},
|
||||
// flake8-docstrings
|
||||
"docstring-convention" => {
|
||||
// No-op (handled above).
|
||||
}
|
||||
"docstring-convention" => match value.trim() {
|
||||
"google" => pydocstyle.convention = Some(Convention::Google),
|
||||
"numpy" => pydocstyle.convention = Some(Convention::Numpy),
|
||||
"pep257" | "all" => pydocstyle.convention = None,
|
||||
_ => eprintln!("Unexpected '{key}' value: {value}"),
|
||||
},
|
||||
// mccabe
|
||||
"max-complexity" | "max_complexity" => match value.clone().parse::<usize>() {
|
||||
Ok(max_complexity) => mccabe.max_complexity = Some(max_complexity),
|
||||
@@ -247,6 +252,9 @@ pub fn convert(
|
||||
if pep8_naming != pep8_naming::settings::Options::default() {
|
||||
options.pep8_naming = Some(pep8_naming);
|
||||
}
|
||||
if pydocstyle != pydocstyle::settings::Options::default() {
|
||||
options.pydocstyle = Some(pydocstyle);
|
||||
}
|
||||
|
||||
// Extract any settings from the existing `pyproject.toml`.
|
||||
if let Some(black) = black {
|
||||
@@ -271,9 +279,10 @@ mod tests {
|
||||
|
||||
use anyhow::Result;
|
||||
use ruff::checks_gen::CheckCodePrefix;
|
||||
use ruff::flake8_quotes;
|
||||
use ruff::pydocstyle::settings::Convention;
|
||||
use ruff::settings::options::Options;
|
||||
use ruff::settings::pyproject::Pyproject;
|
||||
use ruff::{flake8_quotes, pydocstyle};
|
||||
|
||||
use crate::converter::convert;
|
||||
use crate::plugin::Plugin;
|
||||
@@ -287,6 +296,7 @@ mod tests {
|
||||
)?;
|
||||
let expected = Pyproject::new(Options {
|
||||
allowed_confusables: None,
|
||||
cache_dir: None,
|
||||
dummy_variable_rgx: None,
|
||||
exclude: None,
|
||||
extend: None,
|
||||
@@ -295,6 +305,7 @@ mod tests {
|
||||
extend_select: None,
|
||||
external: None,
|
||||
fix: None,
|
||||
fix_only: None,
|
||||
fixable: None,
|
||||
format: None,
|
||||
force_exclude: None,
|
||||
@@ -302,6 +313,7 @@ mod tests {
|
||||
ignore_init_module_imports: None,
|
||||
line_length: None,
|
||||
per_file_ignores: None,
|
||||
required_version: None,
|
||||
respect_gitignore: None,
|
||||
select: Some(vec![
|
||||
CheckCodePrefix::E,
|
||||
@@ -312,7 +324,7 @@ mod tests {
|
||||
src: None,
|
||||
target_version: None,
|
||||
unfixable: None,
|
||||
cache_dir: None,
|
||||
update_check: None,
|
||||
flake8_annotations: None,
|
||||
flake8_bugbear: None,
|
||||
flake8_errmsg: None,
|
||||
@@ -323,6 +335,7 @@ mod tests {
|
||||
isort: None,
|
||||
mccabe: None,
|
||||
pep8_naming: None,
|
||||
pydocstyle: None,
|
||||
pyupgrade: None,
|
||||
});
|
||||
assert_eq!(actual, expected);
|
||||
@@ -342,6 +355,7 @@ mod tests {
|
||||
)?;
|
||||
let expected = Pyproject::new(Options {
|
||||
allowed_confusables: None,
|
||||
cache_dir: None,
|
||||
dummy_variable_rgx: None,
|
||||
exclude: None,
|
||||
extend: None,
|
||||
@@ -350,6 +364,7 @@ mod tests {
|
||||
extend_select: None,
|
||||
external: None,
|
||||
fix: None,
|
||||
fix_only: None,
|
||||
fixable: None,
|
||||
format: None,
|
||||
force_exclude: None,
|
||||
@@ -357,6 +372,7 @@ mod tests {
|
||||
ignore_init_module_imports: None,
|
||||
line_length: Some(100),
|
||||
per_file_ignores: None,
|
||||
required_version: None,
|
||||
respect_gitignore: None,
|
||||
select: Some(vec![
|
||||
CheckCodePrefix::E,
|
||||
@@ -367,7 +383,7 @@ mod tests {
|
||||
src: None,
|
||||
target_version: None,
|
||||
unfixable: None,
|
||||
cache_dir: None,
|
||||
update_check: None,
|
||||
flake8_annotations: None,
|
||||
flake8_bugbear: None,
|
||||
flake8_errmsg: None,
|
||||
@@ -378,6 +394,7 @@ mod tests {
|
||||
isort: None,
|
||||
mccabe: None,
|
||||
pep8_naming: None,
|
||||
pydocstyle: None,
|
||||
pyupgrade: None,
|
||||
});
|
||||
assert_eq!(actual, expected);
|
||||
@@ -397,6 +414,7 @@ mod tests {
|
||||
)?;
|
||||
let expected = Pyproject::new(Options {
|
||||
allowed_confusables: None,
|
||||
cache_dir: None,
|
||||
dummy_variable_rgx: None,
|
||||
exclude: None,
|
||||
extend: None,
|
||||
@@ -405,6 +423,7 @@ mod tests {
|
||||
extend_select: None,
|
||||
external: None,
|
||||
fix: None,
|
||||
fix_only: None,
|
||||
fixable: None,
|
||||
format: None,
|
||||
force_exclude: None,
|
||||
@@ -412,6 +431,7 @@ mod tests {
|
||||
ignore_init_module_imports: None,
|
||||
line_length: Some(100),
|
||||
per_file_ignores: None,
|
||||
required_version: None,
|
||||
respect_gitignore: None,
|
||||
select: Some(vec![
|
||||
CheckCodePrefix::E,
|
||||
@@ -422,7 +442,7 @@ mod tests {
|
||||
src: None,
|
||||
target_version: None,
|
||||
unfixable: None,
|
||||
cache_dir: None,
|
||||
update_check: None,
|
||||
flake8_annotations: None,
|
||||
flake8_bugbear: None,
|
||||
flake8_errmsg: None,
|
||||
@@ -433,6 +453,7 @@ mod tests {
|
||||
isort: None,
|
||||
mccabe: None,
|
||||
pep8_naming: None,
|
||||
pydocstyle: None,
|
||||
pyupgrade: None,
|
||||
});
|
||||
assert_eq!(actual, expected);
|
||||
@@ -452,6 +473,7 @@ mod tests {
|
||||
)?;
|
||||
let expected = Pyproject::new(Options {
|
||||
allowed_confusables: None,
|
||||
cache_dir: None,
|
||||
dummy_variable_rgx: None,
|
||||
exclude: None,
|
||||
extend: None,
|
||||
@@ -460,6 +482,7 @@ mod tests {
|
||||
extend_select: None,
|
||||
external: None,
|
||||
fix: None,
|
||||
fix_only: None,
|
||||
fixable: None,
|
||||
format: None,
|
||||
force_exclude: None,
|
||||
@@ -467,6 +490,7 @@ mod tests {
|
||||
ignore_init_module_imports: None,
|
||||
line_length: None,
|
||||
per_file_ignores: None,
|
||||
required_version: None,
|
||||
respect_gitignore: None,
|
||||
select: Some(vec![
|
||||
CheckCodePrefix::E,
|
||||
@@ -477,7 +501,7 @@ mod tests {
|
||||
src: None,
|
||||
target_version: None,
|
||||
unfixable: None,
|
||||
cache_dir: None,
|
||||
update_check: None,
|
||||
flake8_annotations: None,
|
||||
flake8_bugbear: None,
|
||||
flake8_errmsg: None,
|
||||
@@ -488,6 +512,7 @@ mod tests {
|
||||
isort: None,
|
||||
mccabe: None,
|
||||
pep8_naming: None,
|
||||
pydocstyle: None,
|
||||
pyupgrade: None,
|
||||
});
|
||||
assert_eq!(actual, expected);
|
||||
@@ -507,6 +532,7 @@ mod tests {
|
||||
)?;
|
||||
let expected = Pyproject::new(Options {
|
||||
allowed_confusables: None,
|
||||
cache_dir: None,
|
||||
dummy_variable_rgx: None,
|
||||
exclude: None,
|
||||
extend: None,
|
||||
@@ -515,6 +541,7 @@ mod tests {
|
||||
extend_select: None,
|
||||
external: None,
|
||||
fix: None,
|
||||
fix_only: None,
|
||||
fixable: None,
|
||||
format: None,
|
||||
force_exclude: None,
|
||||
@@ -522,6 +549,7 @@ mod tests {
|
||||
ignore_init_module_imports: None,
|
||||
line_length: None,
|
||||
per_file_ignores: None,
|
||||
required_version: None,
|
||||
respect_gitignore: None,
|
||||
select: Some(vec![
|
||||
CheckCodePrefix::E,
|
||||
@@ -532,7 +560,7 @@ mod tests {
|
||||
src: None,
|
||||
target_version: None,
|
||||
unfixable: None,
|
||||
cache_dir: None,
|
||||
update_check: None,
|
||||
flake8_annotations: None,
|
||||
flake8_bugbear: None,
|
||||
flake8_errmsg: None,
|
||||
@@ -548,6 +576,7 @@ mod tests {
|
||||
isort: None,
|
||||
mccabe: None,
|
||||
pep8_naming: None,
|
||||
pydocstyle: None,
|
||||
pyupgrade: None,
|
||||
});
|
||||
assert_eq!(actual, expected);
|
||||
@@ -570,6 +599,7 @@ mod tests {
|
||||
)?;
|
||||
let expected = Pyproject::new(Options {
|
||||
allowed_confusables: None,
|
||||
cache_dir: None,
|
||||
dummy_variable_rgx: None,
|
||||
exclude: None,
|
||||
extend: None,
|
||||
@@ -578,6 +608,7 @@ mod tests {
|
||||
extend_select: None,
|
||||
external: None,
|
||||
fix: None,
|
||||
fix_only: None,
|
||||
fixable: None,
|
||||
format: None,
|
||||
force_exclude: None,
|
||||
@@ -585,6 +616,7 @@ mod tests {
|
||||
ignore_init_module_imports: None,
|
||||
line_length: None,
|
||||
per_file_ignores: None,
|
||||
required_version: None,
|
||||
respect_gitignore: None,
|
||||
select: Some(vec![
|
||||
CheckCodePrefix::D100,
|
||||
@@ -631,7 +663,7 @@ mod tests {
|
||||
src: None,
|
||||
target_version: None,
|
||||
unfixable: None,
|
||||
cache_dir: None,
|
||||
update_check: None,
|
||||
flake8_annotations: None,
|
||||
flake8_bugbear: None,
|
||||
flake8_errmsg: None,
|
||||
@@ -642,6 +674,9 @@ mod tests {
|
||||
isort: None,
|
||||
mccabe: None,
|
||||
pep8_naming: None,
|
||||
pydocstyle: Some(pydocstyle::settings::Options {
|
||||
convention: Some(Convention::Numpy),
|
||||
}),
|
||||
pyupgrade: None,
|
||||
});
|
||||
assert_eq!(actual, expected);
|
||||
@@ -661,6 +696,7 @@ mod tests {
|
||||
)?;
|
||||
let expected = Pyproject::new(Options {
|
||||
allowed_confusables: None,
|
||||
cache_dir: None,
|
||||
dummy_variable_rgx: None,
|
||||
exclude: None,
|
||||
extend: None,
|
||||
@@ -669,6 +705,7 @@ mod tests {
|
||||
extend_select: None,
|
||||
external: None,
|
||||
fix: None,
|
||||
fix_only: None,
|
||||
fixable: None,
|
||||
format: None,
|
||||
force_exclude: None,
|
||||
@@ -676,6 +713,7 @@ mod tests {
|
||||
ignore_init_module_imports: None,
|
||||
line_length: None,
|
||||
per_file_ignores: None,
|
||||
required_version: None,
|
||||
respect_gitignore: None,
|
||||
select: Some(vec![
|
||||
CheckCodePrefix::E,
|
||||
@@ -687,7 +725,7 @@ mod tests {
|
||||
src: None,
|
||||
target_version: None,
|
||||
unfixable: None,
|
||||
cache_dir: None,
|
||||
update_check: None,
|
||||
flake8_annotations: None,
|
||||
flake8_bugbear: None,
|
||||
flake8_errmsg: None,
|
||||
@@ -703,6 +741,7 @@ mod tests {
|
||||
isort: None,
|
||||
mccabe: None,
|
||||
pep8_naming: None,
|
||||
pydocstyle: None,
|
||||
pyupgrade: None,
|
||||
});
|
||||
assert_eq!(actual, expected);
|
||||
|
||||
@@ -16,16 +16,17 @@ pub enum Plugin {
|
||||
Flake8Datetimez,
|
||||
Flake8Debugger,
|
||||
Flake8Docstrings,
|
||||
Flake8ErrMsg,
|
||||
Flake8Eradicate,
|
||||
Flake8ErrMsg,
|
||||
Flake8ImplicitStrConcat,
|
||||
Flake8Print,
|
||||
Flake8Quotes,
|
||||
Flake8Return,
|
||||
Flake8Simplify,
|
||||
Flake8TidyImports,
|
||||
McCabe,
|
||||
PandasVet,
|
||||
PEP8Naming,
|
||||
PandasVet,
|
||||
Pyupgrade,
|
||||
}
|
||||
|
||||
@@ -45,6 +46,7 @@ impl FromStr for Plugin {
|
||||
"flake8-docstrings" => Ok(Plugin::Flake8Docstrings),
|
||||
"flake8-eradicate" => Ok(Plugin::Flake8Eradicate),
|
||||
"flake8-errmsg" => Ok(Plugin::Flake8ErrMsg),
|
||||
"flake8-implicit-str-concat" => Ok(Plugin::Flake8ImplicitStrConcat),
|
||||
"flake8-print" => Ok(Plugin::Flake8Print),
|
||||
"flake8-quotes" => Ok(Plugin::Flake8Quotes),
|
||||
"flake8-return" => Ok(Plugin::Flake8Return),
|
||||
@@ -76,14 +78,15 @@ impl fmt::Debug for Plugin {
|
||||
Plugin::Flake8Docstrings => "flake8-docstrings",
|
||||
Plugin::Flake8Eradicate => "flake8-eradicate",
|
||||
Plugin::Flake8ErrMsg => "flake8-errmsg",
|
||||
Plugin::Flake8ImplicitStrConcat => "flake8-implicit-str-concat",
|
||||
Plugin::Flake8Print => "flake8-print",
|
||||
Plugin::Flake8Quotes => "flake8-quotes",
|
||||
Plugin::Flake8Return => "flake8-return",
|
||||
Plugin::Flake8Simplify => "flake8-simplify",
|
||||
Plugin::Flake8TidyImports => "flake8-tidy-imports",
|
||||
Plugin::McCabe => "mccabe",
|
||||
Plugin::PandasVet => "pandas-vet",
|
||||
Plugin::PEP8Naming => "pep8-naming",
|
||||
Plugin::PandasVet => "pandas-vet",
|
||||
Plugin::Pyupgrade => "pyupgrade",
|
||||
}
|
||||
)
|
||||
@@ -106,6 +109,7 @@ impl Plugin {
|
||||
// TODO(charlie): Handle rename of `E` to `ERA`.
|
||||
Plugin::Flake8Eradicate => CheckCodePrefix::ERA,
|
||||
Plugin::Flake8ErrMsg => CheckCodePrefix::EM,
|
||||
Plugin::Flake8ImplicitStrConcat => CheckCodePrefix::ISC,
|
||||
Plugin::Flake8Print => CheckCodePrefix::T2,
|
||||
Plugin::Flake8Quotes => CheckCodePrefix::Q,
|
||||
Plugin::Flake8Return => CheckCodePrefix::RET,
|
||||
@@ -146,6 +150,7 @@ impl Plugin {
|
||||
}
|
||||
Plugin::Flake8Eradicate => vec![CheckCodePrefix::ERA],
|
||||
Plugin::Flake8ErrMsg => vec![CheckCodePrefix::EM],
|
||||
Plugin::Flake8ImplicitStrConcat => vec![CheckCodePrefix::ISC],
|
||||
Plugin::Flake8Print => vec![CheckCodePrefix::T2],
|
||||
Plugin::Flake8Quotes => vec![CheckCodePrefix::Q],
|
||||
Plugin::Flake8Return => vec![CheckCodePrefix::RET],
|
||||
@@ -449,6 +454,7 @@ pub fn infer_plugins_from_codes(codes: &BTreeSet<CheckCodePrefix>) -> Vec<Plugin
|
||||
Plugin::Flake8Docstrings,
|
||||
Plugin::Flake8Eradicate,
|
||||
Plugin::Flake8ErrMsg,
|
||||
Plugin::Flake8ImplicitStrConcat,
|
||||
Plugin::Flake8Print,
|
||||
Plugin::Flake8Quotes,
|
||||
Plugin::Flake8Return,
|
||||
|
||||
25
playground/.eslintrc
Normal file
25
playground/.eslintrc
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"plugins": ["@typescript-eslint", "prettier"],
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/eslint-recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:react/recommended",
|
||||
"plugin:react/jsx-runtime",
|
||||
"plugin:react-hooks/recommended",
|
||||
"plugin:import/recommended",
|
||||
"plugin:import/typescript",
|
||||
"plugin:prettier/recommended"
|
||||
],
|
||||
"rules": {
|
||||
// Disable some recommended rules that we don't want to enforce.
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"@typescript-eslint/no-empty-function": "off"
|
||||
},
|
||||
"settings": {
|
||||
"react": {
|
||||
"version": "detect"
|
||||
}
|
||||
}
|
||||
}
|
||||
130
playground/.gitignore
vendored
Normal file
130
playground/.gitignore
vendored
Normal file
@@ -0,0 +1,130 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Snowpack dependency directory (https://snowpack.dev/)
|
||||
web_modules/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional stylelint cache
|
||||
.stylelintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variable files
|
||||
.env
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
.parcel-cache
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
out
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# vuepress v2.x temp and cache directory
|
||||
.temp
|
||||
.cache
|
||||
|
||||
# Docusaurus cache and generated files
|
||||
.docusaurus
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
.vscode-test
|
||||
|
||||
# yarn v2
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
3
playground/.prettierrc.json
Normal file
3
playground/.prettierrc.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"trailingComma": "all"
|
||||
}
|
||||
14
playground/README.md
Normal file
14
playground/README.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# playground
|
||||
|
||||
In-browser playground for Ruff. Available [https://ruff.pages.dev/](https://ruff.pages.dev/).
|
||||
|
||||
## Getting started
|
||||
|
||||
- To build the WASM module, run `wasm-pack build --target web --out-dir playground/src/pkg` from the
|
||||
root directory.
|
||||
- Install TypeScript dependencies with: `npm install`.
|
||||
- Start the development server with: `npm run dev`.
|
||||
|
||||
## Implementation
|
||||
|
||||
Design based on [Tailwind Play](https://play.tailwindcss.com/). Themed with [`ayu`](https://github.com/dempfi/ayu).
|
||||
30
playground/index.html
Normal file
30
playground/index.html
Normal file
@@ -0,0 +1,30 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta
|
||||
name="description"
|
||||
content="An in-browser playground for Ruff, an extremely fast Python linter written in Rust."
|
||||
/>
|
||||
<meta name="keywords" content="ruff, python, rust, webassembly, wasm" />
|
||||
<title>Ruff Playground</title>
|
||||
<link
|
||||
rel="icon"
|
||||
href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🛠️</text></svg>"
|
||||
/>
|
||||
<link rel="stylesheet" href="https://rsms.me/inter/inter.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<div style="display: flex; position: fixed; right: 16px; bottom: 16px">
|
||||
<a href="https://GitHub.com/charliermarsh/ruff"
|
||||
><img
|
||||
src="https://img.shields.io/github/stars/charliermarsh/ruff.svg?style=social&label=GitHub&maxAge=2592000&?logoWidth=100"
|
||||
alt="GitHub stars"
|
||||
style="width: 120px"
|
||||
/></a>
|
||||
</div>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
6785
playground/package-lock.json
generated
Normal file
6785
playground/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
42
playground/package.json
Normal file
42
playground/package.json
Normal file
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"name": "playground",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "tsc && vite build",
|
||||
"check": "npm run lint && npm run tsc",
|
||||
"dev": "vite",
|
||||
"fmt": "prettier --cache -w .",
|
||||
"lint": "eslint --cache --ext .ts,.tsx src",
|
||||
"preview": "vite preview",
|
||||
"tsc": "tsc"
|
||||
},
|
||||
"dependencies": {
|
||||
"@monaco-editor/react": "^4.4.6",
|
||||
"classnames": "^2.3.2",
|
||||
"lz-string": "^1.4.4",
|
||||
"monaco-editor": "^0.34.1",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.0.26",
|
||||
"@types/react-dom": "^18.0.9",
|
||||
"@typescript-eslint/eslint-plugin": "^5.47.1",
|
||||
"@typescript-eslint/parser": "^5.47.1",
|
||||
"@vitejs/plugin-react-swc": "^3.0.0",
|
||||
"autoprefixer": "^10.4.13",
|
||||
"eslint": "^8.30.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"eslint-plugin-react": "^7.31.11",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"postcss": "^8.4.20",
|
||||
"prettier": "^2.8.1",
|
||||
"tailwindcss": "^3.2.4",
|
||||
"typescript": "^4.9.3",
|
||||
"vite": "^4.0.0"
|
||||
}
|
||||
}
|
||||
6
playground/postcss.config.cjs
Normal file
6
playground/postcss.config.cjs
Normal file
@@ -0,0 +1,6 @@
|
||||
module.exports = {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
};
|
||||
151
playground/src/Editor/Editor.tsx
Normal file
151
playground/src/Editor/Editor.tsx
Normal file
@@ -0,0 +1,151 @@
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { DEFAULT_PYTHON_SOURCE } from "../constants";
|
||||
import init, { check, Check, currentVersion, defaultSettings } from "../pkg";
|
||||
import { ErrorMessage } from "./ErrorMessage";
|
||||
import Header from "./Header";
|
||||
import { useTheme } from "./theme";
|
||||
import { persist, restore, stringify } from "./settings";
|
||||
import SettingsEditor from "./SettingsEditor";
|
||||
import SourceEditor from "./SourceEditor";
|
||||
import MonacoThemes from "./MonacoThemes";
|
||||
|
||||
type Tab = "Source" | "Settings";
|
||||
|
||||
export default function Editor() {
|
||||
const [initialized, setInitialized] = useState<boolean>(false);
|
||||
const [version, setVersion] = useState<string | null>(null);
|
||||
const [tab, setTab] = useState<Tab>("Source");
|
||||
const [edit, setEdit] = useState<number>(0);
|
||||
const [settingsSource, setSettingsSource] = useState<string | null>(null);
|
||||
const [pythonSource, setPythonSource] = useState<string | null>(null);
|
||||
const [checks, setChecks] = useState<Check[]>([]);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [theme, setTheme] = useTheme();
|
||||
|
||||
useEffect(() => {
|
||||
init().then(() => setInitialized(true));
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!initialized || settingsSource == null || pythonSource == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
let config: any;
|
||||
let checks: Check[];
|
||||
|
||||
try {
|
||||
config = JSON.parse(settingsSource);
|
||||
} catch (e) {
|
||||
setChecks([]);
|
||||
setError((e as Error).message);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
checks = check(pythonSource, config);
|
||||
} catch (e) {
|
||||
setError(e as string);
|
||||
return;
|
||||
}
|
||||
|
||||
setError(null);
|
||||
setChecks(checks);
|
||||
}, [initialized, settingsSource, pythonSource]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (settingsSource == null || pythonSource == null) {
|
||||
const payload = restore();
|
||||
if (payload) {
|
||||
const [settingsSource, pythonSource] = payload;
|
||||
setSettingsSource(settingsSource);
|
||||
setPythonSource(pythonSource);
|
||||
} else {
|
||||
setSettingsSource(stringify(defaultSettings()));
|
||||
setPythonSource(DEFAULT_PYTHON_SOURCE);
|
||||
}
|
||||
}
|
||||
}, [initialized, settingsSource, pythonSource]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
setVersion(currentVersion());
|
||||
}, [initialized]);
|
||||
|
||||
const handleShare = useCallback(() => {
|
||||
if (!initialized || settingsSource == null || pythonSource == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
persist(settingsSource, pythonSource);
|
||||
}, [initialized, settingsSource, pythonSource]);
|
||||
|
||||
const handlePythonSourceChange = useCallback((pythonSource: string) => {
|
||||
setEdit((edit) => edit + 1);
|
||||
setPythonSource(pythonSource);
|
||||
}, []);
|
||||
|
||||
const handleSettingsSourceChange = useCallback((settingsSource: string) => {
|
||||
setEdit((edit) => edit + 1);
|
||||
setSettingsSource(settingsSource);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<main
|
||||
className={
|
||||
"h-full w-full flex flex-auto bg-ayu-background dark:bg-ayu-background-dark"
|
||||
}
|
||||
>
|
||||
<Header
|
||||
edit={edit}
|
||||
tab={tab}
|
||||
theme={theme}
|
||||
version={version}
|
||||
onChangeTab={setTab}
|
||||
onChangeTheme={setTheme}
|
||||
onShare={initialized ? handleShare : undefined}
|
||||
/>
|
||||
|
||||
<MonacoThemes />
|
||||
|
||||
<div className={"mt-12 relative flex-auto"}>
|
||||
{initialized && settingsSource != null && pythonSource != null ? (
|
||||
<>
|
||||
<SourceEditor
|
||||
visible={tab === "Source"}
|
||||
source={pythonSource}
|
||||
theme={theme}
|
||||
checks={checks}
|
||||
onChange={handlePythonSourceChange}
|
||||
/>
|
||||
<SettingsEditor
|
||||
visible={tab === "Settings"}
|
||||
source={settingsSource}
|
||||
theme={theme}
|
||||
onChange={handleSettingsSourceChange}
|
||||
/>
|
||||
</>
|
||||
) : null}
|
||||
</div>
|
||||
{error && tab === "Source" ? (
|
||||
<div
|
||||
style={{
|
||||
position: "fixed",
|
||||
left: "10%",
|
||||
right: "10%",
|
||||
bottom: "10%",
|
||||
}}
|
||||
>
|
||||
<ErrorMessage>{error}</ErrorMessage>
|
||||
</div>
|
||||
) : null}
|
||||
</main>
|
||||
);
|
||||
}
|
||||
26
playground/src/Editor/ErrorMessage.tsx
Normal file
26
playground/src/Editor/ErrorMessage.tsx
Normal file
@@ -0,0 +1,26 @@
|
||||
function truncate(str: string, length: number) {
|
||||
if (str.length > length) {
|
||||
return str.slice(0, length) + "...";
|
||||
} else {
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
export function ErrorMessage({ children }: { children: string }) {
|
||||
return (
|
||||
<div
|
||||
className="bg-orange-100 border-l-4 border-orange-500 text-orange-700 p-4"
|
||||
role="alert"
|
||||
>
|
||||
<p className="font-bold">Error</p>
|
||||
<p className="block sm:inline">
|
||||
{truncate(
|
||||
children.startsWith("Error: ")
|
||||
? children.slice("Error: ".length)
|
||||
: children,
|
||||
120,
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
99
playground/src/Editor/Header.tsx
Normal file
99
playground/src/Editor/Header.tsx
Normal file
@@ -0,0 +1,99 @@
|
||||
import classNames from "classnames";
|
||||
import ThemeButton from "./ThemeButton";
|
||||
import ShareButton from "./ShareButton";
|
||||
import { Theme } from "./theme";
|
||||
import VersionTag from "./VersionTag";
|
||||
|
||||
export type Tab = "Source" | "Settings";
|
||||
|
||||
export default function Header({
|
||||
edit,
|
||||
tab,
|
||||
theme,
|
||||
version,
|
||||
onChangeTab,
|
||||
onChangeTheme,
|
||||
onShare,
|
||||
}: {
|
||||
edit: number;
|
||||
tab: Tab;
|
||||
theme: Theme;
|
||||
version: string | null;
|
||||
onChangeTab: (tab: Tab) => void;
|
||||
onChangeTheme: (theme: Theme) => void;
|
||||
onShare?: () => void;
|
||||
}) {
|
||||
return (
|
||||
<div
|
||||
className={classNames(
|
||||
"w-full",
|
||||
"flex",
|
||||
"items-center",
|
||||
"justify-between",
|
||||
"flex-none",
|
||||
"pl-5",
|
||||
"sm:pl-6",
|
||||
"pr-4",
|
||||
"lg:pr-6",
|
||||
"absolute",
|
||||
"z-10",
|
||||
"top-0",
|
||||
"left-0",
|
||||
"-mb-px",
|
||||
"antialiased",
|
||||
"border-b",
|
||||
"border-gray-200",
|
||||
"dark:border-gray-800",
|
||||
)}
|
||||
>
|
||||
<div className="flex space-x-5">
|
||||
<button
|
||||
type="button"
|
||||
className={classNames(
|
||||
"relative flex py-3 text-sm leading-6 font-semibold focus:outline-none",
|
||||
tab === "Source"
|
||||
? "text-ayu-accent"
|
||||
: "text-gray-700 hover:text-gray-900 focus:text-gray-900 dark:text-gray-300 dark:hover:text-white",
|
||||
)}
|
||||
onClick={() => onChangeTab("Source")}
|
||||
>
|
||||
<span
|
||||
className={classNames(
|
||||
"absolute bottom-0 inset-x-0 bg-ayu-accent h-0.5 rounded-full transition-opacity duration-150",
|
||||
tab === "Source" ? "opacity-100" : "opacity-0",
|
||||
)}
|
||||
/>
|
||||
Source
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className={classNames(
|
||||
"relative flex py-3 text-sm leading-6 font-semibold focus:outline-none",
|
||||
tab === "Settings"
|
||||
? "text-ayu-accent"
|
||||
: "text-gray-700 hover:text-gray-900 focus:text-gray-900 dark:text-gray-300 dark:hover:text-white",
|
||||
)}
|
||||
onClick={() => onChangeTab("Settings")}
|
||||
>
|
||||
<span
|
||||
className={classNames(
|
||||
"absolute bottom-0 inset-x-0 bg-ayu-accent h-0.5 rounded-full transition-opacity duration-150",
|
||||
tab === "Settings" ? "opacity-100" : "opacity-0",
|
||||
)}
|
||||
/>
|
||||
Settings
|
||||
</button>
|
||||
{version ? (
|
||||
<div className={"flex items-center"}>
|
||||
<VersionTag>v{version}</VersionTag>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
<div className={"hidden sm:flex items-center min-w-0"}>
|
||||
<ShareButton key={edit} onShare={onShare} />
|
||||
<div className="hidden sm:block mx-6 lg:mx-4 w-px h-6 bg-gray-200 dark:bg-gray-700" />
|
||||
<ThemeButton theme={theme} onChange={onChangeTheme} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
1284
playground/src/Editor/MonacoThemes.tsx
Normal file
1284
playground/src/Editor/MonacoThemes.tsx
Normal file
File diff suppressed because it is too large
Load Diff
57
playground/src/Editor/SettingsEditor.tsx
Normal file
57
playground/src/Editor/SettingsEditor.tsx
Normal file
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* Editor for the settings JSON.
|
||||
*/
|
||||
|
||||
import Editor, { useMonaco } from "@monaco-editor/react";
|
||||
import { useCallback, useEffect } from "react";
|
||||
import schema from "../../../ruff.schema.json";
|
||||
import { Theme } from "./theme";
|
||||
|
||||
export default function SettingsEditor({
|
||||
visible,
|
||||
source,
|
||||
theme,
|
||||
onChange,
|
||||
}: {
|
||||
visible: boolean;
|
||||
source: string;
|
||||
theme: Theme;
|
||||
onChange: (source: string) => void;
|
||||
}) {
|
||||
const monaco = useMonaco();
|
||||
|
||||
useEffect(() => {
|
||||
monaco?.languages.json.jsonDefaults.setDiagnosticsOptions({
|
||||
schemas: [
|
||||
{
|
||||
uri: "https://raw.githubusercontent.com/charliermarsh/ruff/main/ruff.schema.json",
|
||||
fileMatch: ["*"],
|
||||
schema,
|
||||
},
|
||||
],
|
||||
});
|
||||
}, [monaco]);
|
||||
|
||||
const handleChange = useCallback(
|
||||
(value: string | undefined) => {
|
||||
onChange(value ?? "");
|
||||
},
|
||||
[onChange],
|
||||
);
|
||||
return (
|
||||
<Editor
|
||||
options={{
|
||||
readOnly: false,
|
||||
minimap: { enabled: false },
|
||||
fontSize: 14,
|
||||
roundedSelection: false,
|
||||
scrollBeyondLastLine: false,
|
||||
}}
|
||||
wrapperProps={visible ? {} : { style: { display: "none" } }}
|
||||
language={"json"}
|
||||
value={source}
|
||||
theme={theme === "light" ? "Ayu-Light" : "Ayu-Dark"}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
);
|
||||
}
|
||||
53
playground/src/Editor/ShareButton.tsx
Normal file
53
playground/src/Editor/ShareButton.tsx
Normal file
@@ -0,0 +1,53 @@
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
export default function ShareButton({ onShare }: { onShare?: () => void }) {
|
||||
const [copied, setCopied] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (copied) {
|
||||
const timeout = setTimeout(() => setCopied(false), 2000);
|
||||
return () => clearTimeout(timeout);
|
||||
}
|
||||
}, [copied]);
|
||||
|
||||
return copied ? (
|
||||
<button
|
||||
type="button"
|
||||
className="relative flex-none rounded-md text-sm font-semibold leading-6 py-1.5 px-3 cursor-auto text-ayu-accent shadow-copied dark:bg-ayu-accent/10"
|
||||
>
|
||||
<span
|
||||
className="absolute inset-0 flex items-center justify-center invisible"
|
||||
aria-hidden="true"
|
||||
>
|
||||
Share
|
||||
</span>
|
||||
<span className="" aria-hidden="false">
|
||||
Copied!
|
||||
</span>
|
||||
</button>
|
||||
) : (
|
||||
<button
|
||||
type="button"
|
||||
className="relative flex-none rounded-md text-sm font-semibold leading-6 py-1.5 px-3 enabled:hover:bg-ayu-accent/80 bg-ayu-accent text-white shadow-sm dark:shadow-highlight/20 disabled:opacity-50"
|
||||
disabled={!onShare || copied}
|
||||
onClick={
|
||||
onShare
|
||||
? () => {
|
||||
setCopied(true);
|
||||
onShare();
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
<span
|
||||
className="absolute inset-0 flex items-center justify-center"
|
||||
aria-hidden="false"
|
||||
>
|
||||
Share
|
||||
</span>
|
||||
<span className="invisible" aria-hidden="true">
|
||||
Copied!
|
||||
</span>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
115
playground/src/Editor/SourceEditor.tsx
Normal file
115
playground/src/Editor/SourceEditor.tsx
Normal file
@@ -0,0 +1,115 @@
|
||||
/**
|
||||
* Editor for the Python source code.
|
||||
*/
|
||||
|
||||
import Editor, { useMonaco } from "@monaco-editor/react";
|
||||
import { MarkerSeverity, MarkerTag } from "monaco-editor";
|
||||
import { useCallback, useEffect } from "react";
|
||||
import { Check } from "../pkg";
|
||||
import { Theme } from "./theme";
|
||||
|
||||
export default function SourceEditor({
|
||||
visible,
|
||||
source,
|
||||
theme,
|
||||
checks,
|
||||
onChange,
|
||||
}: {
|
||||
visible: boolean;
|
||||
source: string;
|
||||
checks: Check[];
|
||||
theme: Theme;
|
||||
onChange: (pythonSource: string) => void;
|
||||
}) {
|
||||
const monaco = useMonaco();
|
||||
|
||||
useEffect(() => {
|
||||
const editor = monaco?.editor;
|
||||
const model = editor?.getModels()[0];
|
||||
if (!editor || !model) {
|
||||
return;
|
||||
}
|
||||
|
||||
editor.setModelMarkers(
|
||||
model,
|
||||
"owner",
|
||||
checks.map((check) => ({
|
||||
startLineNumber: check.location.row,
|
||||
startColumn: check.location.column + 1,
|
||||
endLineNumber: check.end_location.row,
|
||||
endColumn: check.end_location.column + 1,
|
||||
message: `${check.code}: ${check.message}`,
|
||||
severity: MarkerSeverity.Error,
|
||||
tags:
|
||||
check.code === "F401" || check.code === "F841"
|
||||
? [MarkerTag.Unnecessary]
|
||||
: [],
|
||||
})),
|
||||
);
|
||||
|
||||
const codeActionProvider = monaco?.languages.registerCodeActionProvider(
|
||||
"python",
|
||||
{
|
||||
// @ts-expect-error: The type definition is wrong.
|
||||
provideCodeActions: function (model, position) {
|
||||
const actions = checks
|
||||
.filter((check) => position.startLineNumber === check.location.row)
|
||||
.filter((check) => check.fix)
|
||||
.map((check) => ({
|
||||
title: `Fix ${check.code}`,
|
||||
id: `fix-${check.code}`,
|
||||
kind: "quickfix",
|
||||
edit: check.fix
|
||||
? {
|
||||
edits: [
|
||||
{
|
||||
resource: model.uri,
|
||||
versionId: model.getVersionId(),
|
||||
edit: {
|
||||
range: {
|
||||
startLineNumber: check.fix.location.row,
|
||||
startColumn: check.fix.location.column + 1,
|
||||
endLineNumber: check.fix.end_location.row,
|
||||
endColumn: check.fix.end_location.column + 1,
|
||||
},
|
||||
text: check.fix.content,
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
: undefined,
|
||||
}));
|
||||
return { actions, dispose: () => {} };
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
return () => {
|
||||
codeActionProvider?.dispose();
|
||||
};
|
||||
}, [checks, monaco]);
|
||||
|
||||
const handleChange = useCallback(
|
||||
(value: string | undefined) => {
|
||||
onChange(value ?? "");
|
||||
},
|
||||
[onChange],
|
||||
);
|
||||
|
||||
return (
|
||||
<Editor
|
||||
options={{
|
||||
readOnly: false,
|
||||
minimap: { enabled: false },
|
||||
fontSize: 14,
|
||||
roundedSelection: false,
|
||||
scrollBeyondLastLine: false,
|
||||
}}
|
||||
language={"python"}
|
||||
wrapperProps={visible ? {} : { style: { display: "none" } }}
|
||||
theme={theme === "light" ? "Ayu-Light" : "Ayu-Dark"}
|
||||
value={source}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
);
|
||||
}
|
||||
49
playground/src/Editor/ThemeButton.tsx
Normal file
49
playground/src/Editor/ThemeButton.tsx
Normal file
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Button to toggle between light and dark mode themes.
|
||||
*/
|
||||
import { Theme } from "./theme";
|
||||
|
||||
export default function ThemeButton({
|
||||
theme,
|
||||
onChange,
|
||||
}: {
|
||||
theme: Theme;
|
||||
onChange: (theme: Theme) => void;
|
||||
}) {
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
className="ml-4 sm:ml-0 ring-1 ring-gray-900/5 shadow-sm hover:bg-gray-50 dark:ring-0 dark:bg-gray-800 dark:hover:bg-gray-700 dark:shadow-highlight/4 group focus:outline-none focus-visible:ring-2 rounded-md focus-visible:ring-ayu-accent dark:focus-visible:ring-2 dark:focus-visible:ring-gray-400"
|
||||
onClick={() => onChange(theme === "light" ? "dark" : "light")}
|
||||
>
|
||||
<span className="sr-only">
|
||||
<span className="dark:hidden">Switch to dark theme</span>
|
||||
<span className="hidden dark:inline">Switch to light theme</span>
|
||||
</span>
|
||||
<svg
|
||||
width="36"
|
||||
height="36"
|
||||
viewBox="-6 -6 36 36"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
className="stroke-ayu-accent fill-ayu-accent/10 group-hover:stroke-ayu-accent/80 dark:stroke-gray-400 dark:fill-gray-400/20 dark:group-hover:stroke-gray-300"
|
||||
>
|
||||
<g className="dark:opacity-0">
|
||||
<path d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z"></path>
|
||||
<path
|
||||
d="M12 4v.01M17.66 6.345l-.007.007M20.005 12.005h-.01M17.66 17.665l-.007-.007M12 20.01V20M6.34 17.665l.007-.007M3.995 12.005h.01M6.34 6.344l.007.007"
|
||||
fill="none"
|
||||
/>
|
||||
</g>
|
||||
<g className="opacity-0 dark:opacity-100">
|
||||
<path d="M16 12a4 4 0 1 1-8 0 4 4 0 0 1 8 0Z" />
|
||||
<path
|
||||
d="M12 3v1M18.66 5.345l-.828.828M21.005 12.005h-1M18.66 18.665l-.828-.828M12 21.01V20M5.34 18.666l.835-.836M2.995 12.005h1.01M5.34 5.344l.835.836"
|
||||
fill="none"
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
26
playground/src/Editor/VersionTag.tsx
Normal file
26
playground/src/Editor/VersionTag.tsx
Normal file
@@ -0,0 +1,26 @@
|
||||
import classNames from "classnames";
|
||||
import { ReactNode } from "react";
|
||||
|
||||
export default function VersionTag({ children }: { children: ReactNode }) {
|
||||
return (
|
||||
<div
|
||||
className={classNames(
|
||||
"text-gray-500",
|
||||
"text-xs",
|
||||
"leading-5",
|
||||
"font-semibold",
|
||||
"bg-gray-400/10",
|
||||
"rounded-full",
|
||||
"py-1",
|
||||
"px-3",
|
||||
"flex",
|
||||
"items-center",
|
||||
"dark:bg-gray-800",
|
||||
"dark:text-gray-400",
|
||||
"dark:shadow-highlight/4",
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
3
playground/src/Editor/index.tsx
Normal file
3
playground/src/Editor/index.tsx
Normal file
@@ -0,0 +1,3 @@
|
||||
import Editor from "./Editor";
|
||||
|
||||
export default Editor;
|
||||
50
playground/src/Editor/settings.ts
Normal file
50
playground/src/Editor/settings.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import lzstring from "lz-string";
|
||||
|
||||
export type Settings = { [K: string]: any };
|
||||
|
||||
/**
|
||||
* Stringify a settings object to JSON.
|
||||
*/
|
||||
export function stringify(settings: Settings): string {
|
||||
return JSON.stringify(
|
||||
settings,
|
||||
(k, v) => {
|
||||
if (v instanceof Map) {
|
||||
return Object.fromEntries(v.entries());
|
||||
} else {
|
||||
return v;
|
||||
}
|
||||
},
|
||||
2,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Persist the configuration to a URL.
|
||||
*/
|
||||
export async function persist(settingsSource: string, pythonSource: string) {
|
||||
const hash = lzstring.compressToEncodedURIComponent(
|
||||
settingsSource + "$$$" + pythonSource,
|
||||
);
|
||||
await navigator.clipboard.writeText(
|
||||
window.location.href.split("#")[0] + "#" + hash,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the configuration from a URL.
|
||||
*/
|
||||
export function restore(): [string, string] | null {
|
||||
const value = lzstring.decompressFromEncodedURIComponent(
|
||||
window.location.hash.slice(1),
|
||||
);
|
||||
|
||||
if (value) {
|
||||
const parts = value.split("$$$");
|
||||
const settingsSource = parts[0];
|
||||
const pythonSource = parts[1];
|
||||
return [settingsSource, pythonSource];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
35
playground/src/Editor/theme.ts
Normal file
35
playground/src/Editor/theme.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Light and dark mode theming.
|
||||
*/
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
export type Theme = "dark" | "light";
|
||||
|
||||
export function useTheme(): [Theme, (theme: Theme) => void] {
|
||||
const [localTheme, setLocalTheme] = useState<Theme>("light");
|
||||
|
||||
const setTheme = (mode: Theme) => {
|
||||
if (mode === "dark") {
|
||||
document.body.classList.add("dark");
|
||||
} else {
|
||||
document.body.classList.remove("dark");
|
||||
}
|
||||
localStorage.setItem("theme", mode);
|
||||
setLocalTheme(mode);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const initialTheme = localStorage.getItem("theme");
|
||||
if (initialTheme === "dark") {
|
||||
setTheme("dark");
|
||||
} else if (initialTheme === "light") {
|
||||
setTheme("light");
|
||||
} else if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
|
||||
setTheme("dark");
|
||||
} else {
|
||||
setTheme("light");
|
||||
}
|
||||
}, []);
|
||||
|
||||
return [localTheme, setTheme];
|
||||
}
|
||||
7
playground/src/Editor/utils.ts
Normal file
7
playground/src/Editor/utils.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
export async function copyTextToClipboard(text: string) {
|
||||
if ("clipboard" in navigator) {
|
||||
return await navigator.clipboard.writeText(text);
|
||||
} else {
|
||||
return document.execCommand("copy", true, text);
|
||||
}
|
||||
}
|
||||
31
playground/src/constants.ts
Normal file
31
playground/src/constants.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
export const DEFAULT_PYTHON_SOURCE =
|
||||
"import os\n" +
|
||||
"\n" +
|
||||
"# Define a function that takes an integer n and returns the nth number in the Fibonacci\n" +
|
||||
"# sequence.\n" +
|
||||
"def fibonacci(n):\n" +
|
||||
' """Compute the nth number in the Fibonacci sequence."""\n' +
|
||||
" x = 1\n" +
|
||||
" if n == 0:\n" +
|
||||
" return 0\n" +
|
||||
" elif n == 1:\n" +
|
||||
" return 1\n" +
|
||||
" else:\n" +
|
||||
" return fibonacci(n - 1) + fibonacci(n - 2)\n" +
|
||||
"\n" +
|
||||
"\n" +
|
||||
"# Use a for loop to generate and print the first 10 numbers in the Fibonacci sequence.\n" +
|
||||
"for i in range(10):\n" +
|
||||
" print(fibonacci(i))\n" +
|
||||
"\n" +
|
||||
"# Output:\n" +
|
||||
"# 0\n" +
|
||||
"# 1\n" +
|
||||
"# 1\n" +
|
||||
"# 2\n" +
|
||||
"# 3\n" +
|
||||
"# 5\n" +
|
||||
"# 8\n" +
|
||||
"# 13\n" +
|
||||
"# 21\n" +
|
||||
"# 34\n";
|
||||
24
playground/src/index.css
Normal file
24
playground/src/index.css
Normal file
@@ -0,0 +1,24 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body,
|
||||
html,
|
||||
#root {
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.shadow-copied {
|
||||
--tw-shadow: 0 0 0 1px #f07171, inset 0 0 0 1px #f07171;
|
||||
--tw-shadow-colored: 0 0 0 1px var(--tw-shadow-color),
|
||||
inset 0 0 0 1px var(--tw-shadow-color);
|
||||
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000),
|
||||
var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
||||
}
|
||||
10
playground/src/main.tsx
Normal file
10
playground/src/main.tsx
Normal file
@@ -0,0 +1,10 @@
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom/client";
|
||||
import Editor from "./Editor";
|
||||
import "./index.css";
|
||||
|
||||
ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
|
||||
<React.StrictMode>
|
||||
<Editor />
|
||||
</React.StrictMode>,
|
||||
);
|
||||
6
playground/src/third-party.d.ts
vendored
Normal file
6
playground/src/third-party.d.ts
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
declare module "lz-string" {
|
||||
function decompressFromEncodedURIComponent(
|
||||
input: string | null,
|
||||
): string | null;
|
||||
function compressToEncodedURIComponent(input: string | null): string;
|
||||
}
|
||||
1
playground/src/vite-env.d.ts
vendored
Normal file
1
playground/src/vite-env.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/// <reference types="vite/client" />
|
||||
22
playground/tailwind.config.cjs
Normal file
22
playground/tailwind.config.cjs
Normal file
@@ -0,0 +1,22 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
const defaultTheme = require("tailwindcss/defaultTheme");
|
||||
|
||||
module.exports = {
|
||||
darkMode: "class",
|
||||
content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
"ayu-accent": "#f07171",
|
||||
"ayu-background": {
|
||||
DEFAULT: "#f8f9fa",
|
||||
dark: "#0b0e14",
|
||||
},
|
||||
},
|
||||
fontFamily: {
|
||||
sans: ["Inter var", ...defaultTheme.fontFamily.sans],
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [],
|
||||
};
|
||||
21
playground/tsconfig.json
Normal file
21
playground/tsconfig.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"useDefineForClassFields": true,
|
||||
"lib": ["DOM", "DOM.Iterable", "ESNext"],
|
||||
"allowJs": false,
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": false,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "react-jsx"
|
||||
},
|
||||
"include": ["src"],
|
||||
"references": [{ "path": "./tsconfig.node.json" }]
|
||||
}
|
||||
9
playground/tsconfig.node.json
Normal file
9
playground/tsconfig.node.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Node",
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"include": ["vite.config.ts"]
|
||||
}
|
||||
7
playground/vite.config.ts
Normal file
7
playground/vite.config.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { defineConfig } from "vite";
|
||||
import react from "@vitejs/plugin-react-swc";
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
});
|
||||
@@ -34,7 +34,13 @@ bindings = "bin"
|
||||
strip = true
|
||||
|
||||
[tool.ruff]
|
||||
update-check = true
|
||||
|
||||
[tool.ruff.isort]
|
||||
force-wrap-aliases = true
|
||||
combine-as-imports = true
|
||||
force-single-line = true
|
||||
single-line-exclusions = ["os", "logging.handlers"]
|
||||
|
||||
[tool.ruff.pydocstyle]
|
||||
convention = "google"
|
||||
|
||||
36
resources/test/fixtures/flake8_implicit_str_concat/ISC.py
vendored
Normal file
36
resources/test/fixtures/flake8_implicit_str_concat/ISC.py
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
_ = "a" "b" "c"
|
||||
|
||||
_ = "abc" + "def"
|
||||
|
||||
_ = "abc" \
|
||||
"def"
|
||||
|
||||
_ = (
|
||||
"abc" +
|
||||
"def"
|
||||
)
|
||||
|
||||
_ = (
|
||||
f"abc" +
|
||||
"def"
|
||||
)
|
||||
|
||||
_ = (
|
||||
b"abc" +
|
||||
b"def"
|
||||
)
|
||||
|
||||
_ = (
|
||||
"abc"
|
||||
"def"
|
||||
)
|
||||
|
||||
_ = (
|
||||
f"abc"
|
||||
"def"
|
||||
)
|
||||
|
||||
_ = (
|
||||
b"abc"
|
||||
b"def"
|
||||
)
|
||||
33
resources/test/fixtures/flake8_tidy_imports/TID251.py
vendored
Normal file
33
resources/test/fixtures/flake8_tidy_imports/TID251.py
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
## Banned modules ##
|
||||
import cgi
|
||||
|
||||
from cgi import *
|
||||
|
||||
from cgi import a, b, c
|
||||
|
||||
# banning a module also bans any submodules
|
||||
import cgi.foo.bar
|
||||
|
||||
from cgi.foo import bar
|
||||
|
||||
from cgi.foo.bar import *
|
||||
|
||||
## Banned module members ##
|
||||
|
||||
from typing import TypedDict
|
||||
|
||||
import typing
|
||||
|
||||
# attribute access is checked
|
||||
typing.TypedDict
|
||||
|
||||
typing.TypedDict.anything
|
||||
|
||||
# function calls are checked
|
||||
typing.TypedDict()
|
||||
|
||||
typing.TypedDict.anything()
|
||||
|
||||
# import aliases are resolved
|
||||
import typing as totally_not_typing
|
||||
totally_not_typing.TypedDict
|
||||
11
resources/test/fixtures/flake8_tidy_imports/TID251_false_positives.py
vendored
Normal file
11
resources/test/fixtures/flake8_tidy_imports/TID251_false_positives.py
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
# module members cannot be imported with that syntax
|
||||
import typing.TypedDict
|
||||
|
||||
# we don't track reassignments
|
||||
import typing, other
|
||||
typing = other
|
||||
typing.TypedDict()
|
||||
|
||||
# yet another false positive
|
||||
def foo(typing):
|
||||
typing.TypedDict()
|
||||
@@ -1,4 +1,5 @@
|
||||
from abc import abstractmethod
|
||||
from typing import overload
|
||||
from typing_extensions import override
|
||||
|
||||
|
||||
@@ -135,3 +136,20 @@ class C:
|
||||
@override
|
||||
def f(x):
|
||||
print("Hello, world!")
|
||||
|
||||
|
||||
###
|
||||
# Unused arguments attached to overloads (OK).
|
||||
###
|
||||
@overload
|
||||
def f(a: str, b: str) -> str:
|
||||
...
|
||||
|
||||
|
||||
@overload
|
||||
def f(a: int, b: int) -> str:
|
||||
...
|
||||
|
||||
|
||||
def f(a, b):
|
||||
return f"{a}{b}"
|
||||
|
||||
3
resources/test/fixtures/isort/comments.py
vendored
3
resources/test/fixtures/isort/comments.py
vendored
@@ -23,3 +23,6 @@ from A import (
|
||||
b, # Comment 10
|
||||
c, # Comment 11
|
||||
)
|
||||
|
||||
from D import a_long_name_to_force_multiple_lines # Comment 12
|
||||
from D import another_long_name_to_force_multiple_lines # Comment 13
|
||||
|
||||
18
resources/test/fixtures/isort/force_single_line.py
vendored
Normal file
18
resources/test/fixtures/isort/force_single_line.py
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
import sys, math
|
||||
from os import path, uname
|
||||
from logging.handlers import StreamHandler, FileHandler
|
||||
|
||||
# comment 1
|
||||
from third_party import lib1, lib2, \
|
||||
lib3, lib7, lib5, lib6
|
||||
# comment 2
|
||||
from third_party import lib4
|
||||
|
||||
from foo import bar # comment 3
|
||||
from foo2 import bar2 # comment 4
|
||||
|
||||
# comment 5
|
||||
from bar import (
|
||||
a, # comment 6
|
||||
b, # comment 7
|
||||
)
|
||||
38
resources/test/fixtures/isort/magic_trailing_comma.py
vendored
Normal file
38
resources/test/fixtures/isort/magic_trailing_comma.py
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
# This has a magic trailing comma, will be sorted, but not rolled into one line
|
||||
from sys import (
|
||||
stderr,
|
||||
argv,
|
||||
stdout,
|
||||
exit,
|
||||
)
|
||||
|
||||
# No magic comma, this will be rolled into one line.
|
||||
from os import (
|
||||
path,
|
||||
environ,
|
||||
execl,
|
||||
execv
|
||||
)
|
||||
|
||||
from glob import (
|
||||
glob,
|
||||
iglob,
|
||||
escape, # Ends with a comment, should still treat as magic trailing comma.
|
||||
)
|
||||
|
||||
# These will be combined, but without a trailing comma.
|
||||
from foo import bar
|
||||
from foo import baz
|
||||
|
||||
# These will be combined, _with_ a trailing comma.
|
||||
from module1 import member1
|
||||
from module1 import (
|
||||
member2,
|
||||
member3,
|
||||
)
|
||||
|
||||
# These will be combined, _with_ a trailing comma.
|
||||
from module2 import member1, member2
|
||||
from module2 import (
|
||||
member3,
|
||||
)
|
||||
16
resources/test/fixtures/isort/natural_order.py
vendored
Normal file
16
resources/test/fixtures/isort/natural_order.py
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
import numpy1
|
||||
import numpy10
|
||||
import numpy2
|
||||
from numpy import (
|
||||
cos,
|
||||
int8,
|
||||
sin,
|
||||
int32,
|
||||
int64,
|
||||
tan,
|
||||
uint8,
|
||||
uint16,
|
||||
int16,
|
||||
uint32,
|
||||
uint64,
|
||||
)
|
||||
84
resources/test/fixtures/pydocstyle/D417.py
vendored
Normal file
84
resources/test/fixtures/pydocstyle/D417.py
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
def f(x, y, z):
|
||||
"""Do f.
|
||||
|
||||
Args:
|
||||
x: the value
|
||||
with a hanging indent
|
||||
|
||||
Returns:
|
||||
the value
|
||||
"""
|
||||
return x
|
||||
|
||||
|
||||
def f(x, y, z):
|
||||
"""Do f.
|
||||
|
||||
Args:
|
||||
x:
|
||||
The whole thing has a hanging indent.
|
||||
|
||||
Returns:
|
||||
the value
|
||||
"""
|
||||
return x
|
||||
|
||||
|
||||
def f(x, y, z):
|
||||
"""Do f.
|
||||
|
||||
Args:
|
||||
x:
|
||||
The whole thing has a hanging indent.
|
||||
|
||||
Returns: the value
|
||||
"""
|
||||
return x
|
||||
|
||||
|
||||
def f(x, y, z):
|
||||
"""Do f.
|
||||
|
||||
Args:
|
||||
x: the value def
|
||||
ghi
|
||||
|
||||
Returns:
|
||||
the value
|
||||
"""
|
||||
return x
|
||||
|
||||
|
||||
def f(x, y, z):
|
||||
"""Do f.
|
||||
|
||||
Args:
|
||||
x: the value
|
||||
z: A final argument
|
||||
|
||||
Returns:
|
||||
the value
|
||||
"""
|
||||
return x
|
||||
|
||||
|
||||
def f(x, y, z):
|
||||
"""Do g.
|
||||
|
||||
Args:
|
||||
x: the value
|
||||
z: A final argument
|
||||
|
||||
Returns: the value
|
||||
"""
|
||||
return x
|
||||
|
||||
|
||||
def f(x, y, z):
|
||||
"""Do h.
|
||||
|
||||
Args:
|
||||
x: the value
|
||||
z: A final argument
|
||||
"""
|
||||
return x
|
||||
11
resources/test/fixtures/pygrep-hooks/PGH004_0.py
vendored
Normal file
11
resources/test/fixtures/pygrep-hooks/PGH004_0.py
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
x = 1 # noqa
|
||||
x = 1 # NOQA:F401,W203
|
||||
# noqa
|
||||
# NOQA
|
||||
# noqa:F401
|
||||
# noqa:F401,W203
|
||||
|
||||
x = 1
|
||||
x = 1 # noqa: F401, W203
|
||||
# noqa: F401
|
||||
# noqa: F401, W203
|
||||
4
resources/test/fixtures/pyproject.toml
vendored
4
resources/test/fixtures/pyproject.toml
vendored
@@ -42,6 +42,10 @@ staticmethod-decorators = ["staticmethod"]
|
||||
[tool.ruff.flake8-tidy-imports]
|
||||
ban-relative-imports = "parents"
|
||||
|
||||
[tool.ruff.flake8-tidy-imports.banned-api]
|
||||
"cgi".msg = "The cgi module is deprecated."
|
||||
"typing.TypedDict".msg = "Use typing_extensions.TypedDict instead."
|
||||
|
||||
[tool.ruff.flake8-errmsg]
|
||||
max-string-length = 20
|
||||
|
||||
|
||||
20
resources/test/fixtures/pyupgrade/UP019.py
vendored
Normal file
20
resources/test/fixtures/pyupgrade/UP019.py
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
import typing
|
||||
import typing as Hello
|
||||
from typing import Text
|
||||
from typing import Text as Goodbye
|
||||
|
||||
|
||||
def print_word(word: Text) -> None:
|
||||
print(word)
|
||||
|
||||
|
||||
def print_second_word(word: typing.Text) -> None:
|
||||
print(word)
|
||||
|
||||
|
||||
def print_third_word(word: Hello.Text) -> None:
|
||||
print(word)
|
||||
|
||||
|
||||
def print_fourth_word(word: Goodbye) -> None:
|
||||
print(word)
|
||||
9
resources/test/fixtures/pyupgrade/UP020.py
vendored
Normal file
9
resources/test/fixtures/pyupgrade/UP020.py
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
from io import open
|
||||
|
||||
with open("f.txt") as f:
|
||||
print(f.read())
|
||||
|
||||
import io
|
||||
|
||||
with io.open("f.txt", mode="r", buffering=-1, **kwargs) as f:
|
||||
print(f.read())
|
||||
12
resources/test/fixtures/pyupgrade/UP021.py
vendored
Normal file
12
resources/test/fixtures/pyupgrade/UP021.py
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
import subprocess
|
||||
import subprocess as somename
|
||||
from subprocess import run
|
||||
from subprocess import run as anothername
|
||||
|
||||
subprocess.run(["foo"], universal_newlines=True, check=True)
|
||||
somename.run(["foo"], universal_newlines=True)
|
||||
|
||||
run(["foo"], universal_newlines=True, check=False)
|
||||
anothername(["foo"], universal_newlines=True)
|
||||
|
||||
subprocess.run(["foo"], check=True)
|
||||
42
resources/test/fixtures/pyupgrade/UP022.py
vendored
Normal file
42
resources/test/fixtures/pyupgrade/UP022.py
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
from subprocess import run
|
||||
import subprocess
|
||||
|
||||
output = run(["foo"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
|
||||
output = subprocess.run(["foo"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
|
||||
output = subprocess.run(stdout=subprocess.PIPE, args=["foo"], stderr=subprocess.PIPE)
|
||||
|
||||
output = subprocess.run(
|
||||
["foo"], stdout=subprocess.PIPE, check=True, stderr=subprocess.PIPE
|
||||
)
|
||||
|
||||
output = subprocess.run(
|
||||
["foo"], stderr=subprocess.PIPE, check=True, stdout=subprocess.PIPE
|
||||
)
|
||||
|
||||
output = subprocess.run(
|
||||
["foo"],
|
||||
stdout=subprocess.PIPE,
|
||||
check=True,
|
||||
stderr=subprocess.PIPE,
|
||||
text=True,
|
||||
encoding="utf-8",
|
||||
close_fds=True,
|
||||
)
|
||||
|
||||
if output:
|
||||
output = subprocess.run(
|
||||
["foo"],
|
||||
stdout=subprocess.PIPE,
|
||||
check=True,
|
||||
stderr=subprocess.PIPE,
|
||||
text=True,
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
|
||||
# Examples that should NOT trigger the rule
|
||||
from foo import PIPE
|
||||
subprocess.run(["foo"], stdout=PIPE, stderr=PIPE)
|
||||
run(["foo"], stdout=None, stderr=PIPE)
|
||||
31
resources/test/fixtures/pyupgrade/UP023.py
vendored
Normal file
31
resources/test/fixtures/pyupgrade/UP023.py
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
# These two imports have something after cElementTree, so they should be fixed.
|
||||
from xml.etree.cElementTree import XML, Element, SubElement
|
||||
import xml.etree.cElementTree as ET
|
||||
|
||||
# Weird spacing should not cause issues.
|
||||
from xml.etree.cElementTree import XML
|
||||
import xml.etree.cElementTree as ET
|
||||
|
||||
# Multi line imports should also work fine.
|
||||
from xml.etree.cElementTree import (
|
||||
XML,
|
||||
Element,
|
||||
SubElement,
|
||||
)
|
||||
if True:
|
||||
import xml.etree.cElementTree as ET
|
||||
from xml.etree import cElementTree as CET
|
||||
|
||||
from xml.etree import cElementTree as ET
|
||||
|
||||
import contextlib, xml.etree.cElementTree as ET
|
||||
|
||||
# This should fix the second, but not the first invocation.
|
||||
import xml.etree.cElementTree, xml.etree.cElementTree as ET
|
||||
|
||||
# The below items should NOT be changed.
|
||||
import xml.etree.cElementTree
|
||||
|
||||
from .xml.etree.cElementTree import XML
|
||||
|
||||
from xml.etree import cElementTree
|
||||
27
resources/test/fixtures/pyupgrade/UP025.py
vendored
Normal file
27
resources/test/fixtures/pyupgrade/UP025.py
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
# These should change
|
||||
x = u"Hello"
|
||||
|
||||
u'world'
|
||||
|
||||
print(u"Hello")
|
||||
|
||||
print(u'world')
|
||||
|
||||
import foo
|
||||
|
||||
foo(u"Hello", U"world", a=u"Hello", b=u"world")
|
||||
|
||||
# These should stay quoted they way they are
|
||||
|
||||
x = u'hello'
|
||||
x = u"""hello"""
|
||||
x = u'''hello'''
|
||||
x = u'Hello "World"'
|
||||
|
||||
# These should not change
|
||||
u = "Hello"
|
||||
|
||||
u = u
|
||||
|
||||
def hello():
|
||||
return"Hello"
|
||||
15
resources/test/fixtures/ruff/RUF004.py
vendored
Normal file
15
resources/test/fixtures/ruff/RUF004.py
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
def f(*args, **kwargs):
|
||||
pass
|
||||
|
||||
|
||||
a = (1, 2)
|
||||
b = (3, 4)
|
||||
c = (5, 6)
|
||||
d = (7, 8)
|
||||
|
||||
f(a, b)
|
||||
f(a, kw=b)
|
||||
f(*a, kw=b)
|
||||
f(kw=a, *b)
|
||||
f(kw=a, *b, *c)
|
||||
f(*a, kw=b, *c, kw1=d)
|
||||
@@ -1,4 +1,3 @@
|
||||
[tool.ruff]
|
||||
extend = "../../pyproject.toml"
|
||||
src = ["."]
|
||||
# Enable I001, and re-enable F841, to test extension priority.
|
||||
186
ruff.schema.json
186
ruff.schema.json
@@ -93,6 +93,13 @@
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"fix-only": {
|
||||
"description": "Like `fix`, but disables reporting on leftover violation. Implies `fix`.",
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"fixable": {
|
||||
"description": "A list of check code prefixes to consider autofix-able.",
|
||||
"type": [
|
||||
@@ -104,7 +111,7 @@
|
||||
}
|
||||
},
|
||||
"flake8-annotations": {
|
||||
"description": "Plugins Options for the `flake8-annotations` plugin.",
|
||||
"description": "Options for the `flake8-annotations` plugin.",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Flake8AnnotationsOptions"
|
||||
@@ -188,7 +195,7 @@
|
||||
]
|
||||
},
|
||||
"format": {
|
||||
"description": "The style in which violation messages should be formatted: `\"text\"` (default), `\"grouped\"` (group messages by file), `\"json\"` (machine-readable), `\"junit\"` (machine-readable XML), or `\"github\"` (GitHub Actions annotations).",
|
||||
"description": "The style in which violation messages should be formatted: `\"text\"` (default), `\"grouped\"` (group messages by file), `\"json\"` (machine-readable), `\"junit\"` (machine-readable XML), `\"github\"` (GitHub Actions annotations) or `\"gitlab\"` (GitLab CI code quality report).",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/SerializationFormat"
|
||||
@@ -270,6 +277,17 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"pydocstyle": {
|
||||
"description": "Options for the `pydocstyle` plugin.",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Pydocstyle"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"pyupgrade": {
|
||||
"description": "Options for the `pyupgrade` plugin.",
|
||||
"anyOf": [
|
||||
@@ -281,6 +299,17 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"required-version": {
|
||||
"description": "Require a specific version of Ruff to be running (useful for unifying results across many environments, e.g., with a `pyproject.toml` file).",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Version"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"respect-gitignore": {
|
||||
"description": "Whether to automatically exclude files that are ignored by `.ignore`, `.gitignore`, `.git/info/exclude`, and global `gitignore` files. Enabled by default.",
|
||||
"type": [
|
||||
@@ -335,10 +364,30 @@
|
||||
"items": {
|
||||
"$ref": "#/definitions/CheckCodePrefix"
|
||||
}
|
||||
},
|
||||
"update-check": {
|
||||
"description": "Enable or disable automatic update checks (overridden by the `--update-check` and `--no-update-check` command-line flags).",
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"definitions": {
|
||||
"BannedApi": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"msg"
|
||||
],
|
||||
"properties": {
|
||||
"msg": {
|
||||
"description": "The message to display when the API is used.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"CheckCodePrefix": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
@@ -348,6 +397,7 @@
|
||||
"A001",
|
||||
"A002",
|
||||
"A003",
|
||||
"ALL",
|
||||
"ANN",
|
||||
"ANN0",
|
||||
"ANN00",
|
||||
@@ -633,6 +683,12 @@
|
||||
"ICN0",
|
||||
"ICN00",
|
||||
"ICN001",
|
||||
"ISC",
|
||||
"ISC0",
|
||||
"ISC00",
|
||||
"ISC001",
|
||||
"ISC002",
|
||||
"ISC003",
|
||||
"M",
|
||||
"M0",
|
||||
"M001",
|
||||
@@ -696,6 +752,7 @@
|
||||
"PGH001",
|
||||
"PGH002",
|
||||
"PGH003",
|
||||
"PGH004",
|
||||
"PLC",
|
||||
"PLC0",
|
||||
"PLC04",
|
||||
@@ -776,6 +833,7 @@
|
||||
"RUF001",
|
||||
"RUF002",
|
||||
"RUF003",
|
||||
"RUF004",
|
||||
"RUF1",
|
||||
"RUF10",
|
||||
"RUF100",
|
||||
@@ -803,6 +861,7 @@
|
||||
"TID",
|
||||
"TID2",
|
||||
"TID25",
|
||||
"TID251",
|
||||
"TID252",
|
||||
"U",
|
||||
"U0",
|
||||
@@ -824,6 +883,7 @@
|
||||
"U015",
|
||||
"U016",
|
||||
"U017",
|
||||
"U019",
|
||||
"UP",
|
||||
"UP0",
|
||||
"UP00",
|
||||
@@ -845,6 +905,13 @@
|
||||
"UP016",
|
||||
"UP017",
|
||||
"UP018",
|
||||
"UP019",
|
||||
"UP02",
|
||||
"UP020",
|
||||
"UP021",
|
||||
"UP022",
|
||||
"UP023",
|
||||
"UP025",
|
||||
"W",
|
||||
"W2",
|
||||
"W29",
|
||||
@@ -871,6 +938,24 @@
|
||||
"YTT303"
|
||||
]
|
||||
},
|
||||
"Convention": {
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Use Google-style docstrings.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"google"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Use NumPy-style docstrings.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"numpy"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"Flake8AnnotationsOptions": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -1012,7 +1097,7 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"ban-relative-imports": {
|
||||
"description": "Whether to ban all relative imports (`\"all\"`), or only those imports that extend into the parent module and beyond (`\"parents\"`).",
|
||||
"description": "Whether to ban all relative imports (`\"all\"`), or only those imports that extend into the parent module or beyond (`\"parents\"`).",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Strictness"
|
||||
@@ -1021,6 +1106,16 @@
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"banned-api": {
|
||||
"description": "Specific modules or module members that may not be imported or accessed. Note that this check is only meant to flag accidental uses, and can be circumvented via `eval` or `importlib`.",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
],
|
||||
"additionalProperties": {
|
||||
"$ref": "#/definitions/BannedApi"
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
@@ -1058,6 +1153,13 @@
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"force-single-line": {
|
||||
"description": "Forces all from imports to appear on their own line.",
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"force-wrap-aliases": {
|
||||
"description": "Force `import from` statements with multiple members and at least one alias (e.g., `import A as B`) to wrap such that every line contains exactly one member. For example, this formatting would be retained, rather than condensing to a single line:\n\n```py from .utils import ( test_directory as test_directory, test_id as test_id ) ```\n\nNote that this setting is only effective when combined with `combine-as-imports = true`. When `combine-as-imports` isn't enabled, every aliased `import from` will be given its own line, in which case, wrapping is not necessary.",
|
||||
"type": [
|
||||
@@ -1084,6 +1186,23 @@
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"single-line-exclusions": {
|
||||
"description": "One or more modules to exclude from the single line rule.",
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
],
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"split-on-trailing-comma": {
|
||||
"description": "If a comma is placed after the last member in a multi-line import, then the imports will never be folded into one line.\n\nSee isort's [`split-on-trailing-comma`](https://pycqa.github.io/isort/docs/configuration/options.html#split-on-trailing-comma) option.",
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
@@ -1152,6 +1271,23 @@
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"Pydocstyle": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"convention": {
|
||||
"description": "Whether to use Google-style or Numpy-style conventions when detecting docstring sections. By default, conventions will be inferred from the available sections.",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Convention"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"PythonVersion": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
@@ -1167,10 +1303,21 @@
|
||||
]
|
||||
},
|
||||
"Quote": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"single",
|
||||
"double"
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Use single quotes (`'`).",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"single"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Use double quotes (`\"`).",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"double"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"SerializationFormat": {
|
||||
@@ -1180,15 +1327,30 @@
|
||||
"json",
|
||||
"junit",
|
||||
"grouped",
|
||||
"github"
|
||||
"github",
|
||||
"gitlab"
|
||||
]
|
||||
},
|
||||
"Strictness": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"parents",
|
||||
"all"
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Ban imports that extend into the parent module or beyond.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"parents"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Ban all relative imports.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"all"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"Version": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ruff_dev"
|
||||
version = "0.0.193"
|
||||
version = "0.0.202"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
@@ -11,10 +11,11 @@ itertools = { version = "0.10.5" }
|
||||
libcst = { git = "https://github.com/charliermarsh/LibCST", rev = "f2f0b7a487a8725d161fe8b3ed73a6758b21e177" }
|
||||
once_cell = { version = "1.16.0" }
|
||||
ruff = { path = ".." }
|
||||
rustpython-ast = { features = ["unparse"], git = "https://github.com/RustPython/RustPython.git", rev = "1b6cb170e925a43d605b3fed9f6b878e63e47744" }
|
||||
rustpython-common = { git = "https://github.com/RustPython/RustPython.git", rev = "1b6cb170e925a43d605b3fed9f6b878e63e47744" }
|
||||
rustpython-parser = { features = ["lalrpop"], git = "https://github.com/RustPython/RustPython.git", rev = "1b6cb170e925a43d605b3fed9f6b878e63e47744" }
|
||||
rustpython-ast = { features = ["unparse"], git = "https://github.com/RustPython/RustPython.git", rev = "68d26955b3e24198a150315e7959719b03709dee" }
|
||||
rustpython-common = { git = "https://github.com/RustPython/RustPython.git", rev = "68d26955b3e24198a150315e7959719b03709dee" }
|
||||
rustpython-parser = { features = ["lalrpop"], git = "https://github.com/RustPython/RustPython.git", rev = "68d26955b3e24198a150315e7959719b03709dee" }
|
||||
schemars = { version = "0.8.11" }
|
||||
serde_json = {version="1.0.91"}
|
||||
strum = { version = "0.24.1", features = ["strum_macros"] }
|
||||
strum_macros = { version = "0.24.3" }
|
||||
textwrap = { version = "0.16.0" }
|
||||
|
||||
31
ruff_dev/src/generate_all.rs
Normal file
31
ruff_dev/src/generate_all.rs
Normal file
@@ -0,0 +1,31 @@
|
||||
//! Run all code and documentation generation steps.
|
||||
|
||||
use anyhow::Result;
|
||||
use clap::Args;
|
||||
|
||||
use crate::{
|
||||
generate_check_code_prefix, generate_json_schema, generate_options, generate_rules_table,
|
||||
};
|
||||
|
||||
#[derive(Args)]
|
||||
pub struct Cli {
|
||||
/// Write the generated artifacts to stdout (rather than to the filesystem).
|
||||
#[arg(long)]
|
||||
dry_run: bool,
|
||||
}
|
||||
|
||||
pub fn main(cli: &Cli) -> Result<()> {
|
||||
generate_check_code_prefix::main(&generate_check_code_prefix::Cli {
|
||||
dry_run: cli.dry_run,
|
||||
})?;
|
||||
generate_json_schema::main(&generate_json_schema::Cli {
|
||||
dry_run: cli.dry_run,
|
||||
})?;
|
||||
generate_rules_table::main(&generate_rules_table::Cli {
|
||||
dry_run: cli.dry_run,
|
||||
})?;
|
||||
generate_options::main(&generate_options::Cli {
|
||||
dry_run: cli.dry_run,
|
||||
})?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -13,13 +13,15 @@ use itertools::Itertools;
|
||||
use ruff::checks::{CheckCode, PREFIX_REDIRECTS};
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
const ALL: &str = "ALL";
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(author, version, about, long_about = None)]
|
||||
pub struct Cli {
|
||||
/// Write the generated source code to stdout (rather than to
|
||||
/// `src/checks_gen.rs`).
|
||||
#[arg(long)]
|
||||
dry_run: bool,
|
||||
pub(crate) dry_run: bool,
|
||||
}
|
||||
|
||||
pub fn main(cli: &Cli) -> Result<()> {
|
||||
@@ -34,9 +36,15 @@ pub fn main(cli: &Cli) -> Result<()> {
|
||||
let code_suffix_len = code_str.len() - code_prefix_len;
|
||||
for i in 0..=code_suffix_len {
|
||||
let prefix = code_str[..code_prefix_len + i].to_string();
|
||||
let entry = prefix_to_codes.entry(prefix).or_default();
|
||||
entry.insert(check_code.clone());
|
||||
prefix_to_codes
|
||||
.entry(prefix)
|
||||
.or_default()
|
||||
.insert(check_code.clone());
|
||||
}
|
||||
prefix_to_codes
|
||||
.entry(ALL.to_string())
|
||||
.or_default()
|
||||
.insert(check_code.clone());
|
||||
}
|
||||
|
||||
// Add any prefix aliases (e.g., "U" to "UP").
|
||||
@@ -79,6 +87,7 @@ pub fn main(cli: &Cli) -> Result<()> {
|
||||
.derive("Eq")
|
||||
.derive("PartialOrd")
|
||||
.derive("Ord")
|
||||
.push_variant(Variant::new("None"))
|
||||
.push_variant(Variant::new("Zero"))
|
||||
.push_variant(Variant::new("One"))
|
||||
.push_variant(Variant::new("Two"))
|
||||
@@ -129,14 +138,18 @@ pub fn main(cli: &Cli) -> Result<()> {
|
||||
.line("#[allow(clippy::match_same_arms)]")
|
||||
.line("match self {");
|
||||
for prefix in prefix_to_codes.keys() {
|
||||
let num_numeric = prefix.chars().filter(|char| char.is_numeric()).count();
|
||||
let specificity = match num_numeric {
|
||||
0 => "Zero",
|
||||
1 => "One",
|
||||
2 => "Two",
|
||||
3 => "Three",
|
||||
4 => "Four",
|
||||
_ => panic!("Invalid prefix: {prefix}"),
|
||||
let specificity = if prefix == "ALL" {
|
||||
"None"
|
||||
} else {
|
||||
let num_numeric = prefix.chars().filter(|char| char.is_numeric()).count();
|
||||
match num_numeric {
|
||||
0 => "Zero",
|
||||
1 => "One",
|
||||
2 => "Two",
|
||||
3 => "Three",
|
||||
4 => "Four",
|
||||
_ => panic!("Invalid prefix: {prefix}"),
|
||||
}
|
||||
};
|
||||
gen = gen.line(format!(
|
||||
"CheckCodePrefix::{prefix} => SuffixLength::{specificity},"
|
||||
|
||||
@@ -10,7 +10,7 @@ use schemars::schema_for;
|
||||
pub struct Cli {
|
||||
/// Write the generated table to stdout (rather than to `ruff.schema.json`).
|
||||
#[arg(long)]
|
||||
dry_run: bool,
|
||||
pub(crate) dry_run: bool,
|
||||
}
|
||||
|
||||
pub fn main(cli: &Cli) -> Result<()> {
|
||||
|
||||
@@ -18,7 +18,7 @@ const END_PRAGMA: &str = "<!-- End auto-generated options sections. -->";
|
||||
pub struct Cli {
|
||||
/// Write the generated table to stdout (rather than to `README.md`).
|
||||
#[arg(long)]
|
||||
dry_run: bool,
|
||||
pub(crate) dry_run: bool,
|
||||
}
|
||||
|
||||
fn emit_field(output: &mut String, field: &OptionField, group_name: Option<&str>) {
|
||||
|
||||
@@ -21,7 +21,7 @@ const TOC_END_PRAGMA: &str = "<!-- End auto-generated table of contents. -->";
|
||||
pub struct Cli {
|
||||
/// Write the generated table to stdout (rather than to `README.md`).
|
||||
#[arg(long)]
|
||||
dry_run: bool,
|
||||
pub(crate) dry_run: bool,
|
||||
}
|
||||
|
||||
pub fn main(cli: &Cli) -> Result<()> {
|
||||
|
||||
@@ -11,11 +11,12 @@
|
||||
clippy::too_many_lines
|
||||
)]
|
||||
|
||||
pub mod generate_all;
|
||||
pub mod generate_check_code_prefix;
|
||||
pub mod generate_json_schema;
|
||||
pub mod generate_options;
|
||||
pub mod generate_rules_table;
|
||||
pub mod generate_source_code;
|
||||
pub mod print_ast;
|
||||
pub mod print_cst;
|
||||
pub mod print_tokens;
|
||||
pub mod round_trip;
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
use anyhow::Result;
|
||||
use clap::{Parser, Subcommand};
|
||||
use ruff_dev::{
|
||||
generate_check_code_prefix, generate_json_schema, generate_options, generate_rules_table,
|
||||
generate_source_code, print_ast, print_cst, print_tokens,
|
||||
generate_all, generate_check_code_prefix, generate_json_schema, generate_options,
|
||||
generate_rules_table, print_ast, print_cst, print_tokens, round_trip,
|
||||
};
|
||||
|
||||
#[derive(Parser)]
|
||||
@@ -28,6 +28,8 @@ struct Cli {
|
||||
|
||||
#[derive(Subcommand)]
|
||||
enum Commands {
|
||||
/// Run all code and documentation generation steps.
|
||||
GenerateAll(generate_all::Cli),
|
||||
/// Generate the `CheckCodePrefix` enum.
|
||||
GenerateCheckCodePrefix(generate_check_code_prefix::Cli),
|
||||
/// Generate JSON schema for the TOML configuration file.
|
||||
@@ -36,27 +38,28 @@ enum Commands {
|
||||
GenerateRulesTable(generate_rules_table::Cli),
|
||||
/// Generate a Markdown-compatible listing of configuration options.
|
||||
GenerateOptions(generate_options::Cli),
|
||||
/// Run round-trip source code generation on a given Python file.
|
||||
GenerateSourceCode(generate_source_code::Cli),
|
||||
/// Print the AST for a given Python file.
|
||||
PrintAST(print_ast::Cli),
|
||||
/// Print the LibCST CST for a given Python file.
|
||||
PrintCST(print_cst::Cli),
|
||||
/// Print the token stream for a given Python file.
|
||||
PrintTokens(print_tokens::Cli),
|
||||
/// Run round-trip source code generation on a given Python file.
|
||||
RoundTrip(round_trip::Cli),
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let cli = Cli::parse();
|
||||
match &cli.command {
|
||||
Commands::GenerateAll(args) => generate_all::main(args)?,
|
||||
Commands::GenerateCheckCodePrefix(args) => generate_check_code_prefix::main(args)?,
|
||||
Commands::GenerateJSONSchema(args) => generate_json_schema::main(args)?,
|
||||
Commands::GenerateRulesTable(args) => generate_rules_table::main(args)?,
|
||||
Commands::GenerateSourceCode(args) => generate_source_code::main(args)?,
|
||||
Commands::GenerateOptions(args) => generate_options::main(args)?,
|
||||
Commands::PrintAST(args) => print_ast::main(args)?,
|
||||
Commands::PrintCST(args) => print_cst::main(args)?,
|
||||
Commands::PrintTokens(args) => print_tokens::main(args)?,
|
||||
Commands::RoundTrip(args) => round_trip::main(args)?,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -5,7 +5,9 @@ use std::path::PathBuf;
|
||||
|
||||
use anyhow::Result;
|
||||
use clap::Args;
|
||||
use ruff::code_gen::SourceGenerator;
|
||||
use ruff::source_code_generator::SourceCodeGenerator;
|
||||
use ruff::source_code_locator::SourceCodeLocator;
|
||||
use ruff::source_code_style::SourceCodeStyleDetector;
|
||||
use rustpython_parser::parser;
|
||||
|
||||
#[derive(Args)]
|
||||
@@ -18,7 +20,9 @@ pub struct Cli {
|
||||
pub fn main(cli: &Cli) -> Result<()> {
|
||||
let contents = fs::read_to_string(&cli.file)?;
|
||||
let python_ast = parser::parse_program(&contents, &cli.file.to_string_lossy())?;
|
||||
let mut generator = SourceGenerator::new();
|
||||
let locator = SourceCodeLocator::new(&contents);
|
||||
let stylist = SourceCodeStyleDetector::from_contents(&contents, &locator);
|
||||
let mut generator = SourceCodeGenerator::new(stylist.indentation(), stylist.quote());
|
||||
generator.unparse_suite(&python_ast);
|
||||
println!("{}", generator.generate()?);
|
||||
Ok(())
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ruff_macros"
|
||||
version = "0.0.193"
|
||||
version = "0.0.202"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use itertools::Itertools;
|
||||
use log::error;
|
||||
use once_cell::sync::Lazy;
|
||||
use regex::Regex;
|
||||
@@ -381,10 +382,8 @@ pub fn identifier_range(stmt: &Stmt, locator: &SourceCodeLocator) -> Range {
|
||||
| StmtKind::AsyncFunctionDef { .. }
|
||||
) {
|
||||
let contents = locator.slice_source_code_range(&Range::from_located(stmt));
|
||||
for (start, tok, end) in lexer::make_tokenizer(&contents).flatten() {
|
||||
for (start, tok, end) in lexer::make_tokenizer_located(&contents, stmt.location).flatten() {
|
||||
if matches!(tok, Tok::Name { .. }) {
|
||||
let start = to_absolute(start, stmt.location);
|
||||
let end = to_absolute(end, stmt.location);
|
||||
return Range {
|
||||
location: start,
|
||||
end_location: end,
|
||||
@@ -396,6 +395,37 @@ pub fn identifier_range(stmt: &Stmt, locator: &SourceCodeLocator) -> Range {
|
||||
Range::from_located(stmt)
|
||||
}
|
||||
|
||||
/// Return the `Range` of `name` in `Excepthandler`.
|
||||
pub fn excepthandler_name_range(
|
||||
handler: &Excepthandler,
|
||||
locator: &SourceCodeLocator,
|
||||
) -> Option<Range> {
|
||||
let ExcepthandlerKind::ExceptHandler {
|
||||
name, type_, body, ..
|
||||
} = &handler.node;
|
||||
match (name, type_) {
|
||||
(Some(_), Some(type_)) => {
|
||||
let type_end_location = type_.end_location.unwrap();
|
||||
let contents = locator.slice_source_code_range(&Range {
|
||||
location: type_end_location,
|
||||
end_location: body[0].location,
|
||||
});
|
||||
let range = lexer::make_tokenizer_located(&contents, type_end_location)
|
||||
.flatten()
|
||||
.tuple_windows()
|
||||
.find(|(tok, next_tok)| {
|
||||
matches!(tok.1, Tok::As) && matches!(next_tok.1, Tok::Name { .. })
|
||||
})
|
||||
.map(|((..), (location, _, end_location))| Range {
|
||||
location,
|
||||
end_location,
|
||||
});
|
||||
range
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Return `true` if a `Stmt` appears to be part of a multi-statement line, with
|
||||
/// other statements preceding it.
|
||||
pub fn preceded_by_continuation(stmt: &Stmt, locator: &SourceCodeLocator) -> bool {
|
||||
|
||||
@@ -14,6 +14,7 @@ use crate::source_code_locator::SourceCodeLocator;
|
||||
pub enum Mode {
|
||||
Generate,
|
||||
Apply,
|
||||
Diff,
|
||||
None,
|
||||
}
|
||||
|
||||
|
||||
17
src/cache.rs
17
src/cache.rs
@@ -12,7 +12,6 @@ use once_cell::sync::Lazy;
|
||||
use path_absolutize::Absolutize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::autofix::fixer;
|
||||
use crate::message::Message;
|
||||
use crate::settings::{flags, Settings};
|
||||
|
||||
@@ -48,7 +47,7 @@ fn content_dir() -> &'static Path {
|
||||
Path::new("content")
|
||||
}
|
||||
|
||||
fn cache_key<P: AsRef<Path>>(path: P, settings: &Settings, autofix: fixer::Mode) -> u64 {
|
||||
fn cache_key<P: AsRef<Path>>(path: P, settings: &Settings, autofix: flags::Autofix) -> u64 {
|
||||
let mut hasher = DefaultHasher::new();
|
||||
CARGO_PKG_VERSION.hash(&mut hasher);
|
||||
path.as_ref().absolutize().unwrap().hash(&mut hasher);
|
||||
@@ -93,13 +92,8 @@ pub fn get<P: AsRef<Path>>(
|
||||
path: P,
|
||||
metadata: &Metadata,
|
||||
settings: &Settings,
|
||||
autofix: fixer::Mode,
|
||||
cache: flags::Cache,
|
||||
autofix: flags::Autofix,
|
||||
) -> Option<Vec<Message>> {
|
||||
if matches!(cache, flags::Cache::Disabled) {
|
||||
return None;
|
||||
};
|
||||
|
||||
let encoded = read_sync(&settings.cache_dir, cache_key(path, settings, autofix)).ok()?;
|
||||
let (mtime, messages) = match bincode::deserialize::<CheckResult>(&encoded[..]) {
|
||||
Ok(CheckResult {
|
||||
@@ -122,14 +116,9 @@ pub fn set<P: AsRef<Path>>(
|
||||
path: P,
|
||||
metadata: &Metadata,
|
||||
settings: &Settings,
|
||||
autofix: fixer::Mode,
|
||||
autofix: flags::Autofix,
|
||||
messages: &[Message],
|
||||
cache: flags::Cache,
|
||||
) {
|
||||
if matches!(cache, flags::Cache::Disabled) {
|
||||
return;
|
||||
};
|
||||
|
||||
let check_result = CheckResultRef {
|
||||
metadata: &CacheMetadata {
|
||||
mtime: FileTime::from_last_modification_time(metadata).unix_seconds(),
|
||||
|
||||
@@ -33,14 +33,16 @@ use crate::python::typing::SubscriptKind;
|
||||
use crate::settings::types::PythonVersion;
|
||||
use crate::settings::{flags, Settings};
|
||||
use crate::source_code_locator::SourceCodeLocator;
|
||||
use crate::vendored::cformat::{CFormatError, CFormatErrorType};
|
||||
use crate::source_code_style::SourceCodeStyleDetector;
|
||||
use crate::vendor::cformat::{CFormatError, CFormatErrorType};
|
||||
use crate::visibility::{module_visibility, transition_scope, Modifier, Visibility, VisibleScope};
|
||||
use crate::{
|
||||
docstrings, flake8_2020, flake8_annotations, flake8_bandit, flake8_blind_except,
|
||||
flake8_boolean_trap, flake8_bugbear, flake8_builtins, flake8_comprehensions, flake8_datetimez,
|
||||
flake8_debugger, flake8_errmsg, flake8_import_conventions, flake8_print, flake8_return,
|
||||
flake8_simplify, flake8_tidy_imports, flake8_unused_arguments, mccabe, noqa, pandas_vet,
|
||||
pep8_naming, pycodestyle, pydocstyle, pyflakes, pygrep_hooks, pylint, pyupgrade, visibility,
|
||||
flake8_debugger, flake8_errmsg, flake8_implicit_str_concat, flake8_import_conventions,
|
||||
flake8_print, flake8_return, flake8_simplify, flake8_tidy_imports, flake8_unused_arguments,
|
||||
mccabe, noqa, pandas_vet, pep8_naming, pycodestyle, pydocstyle, pyflakes, pygrep_hooks, pylint,
|
||||
pyupgrade, ruff, visibility,
|
||||
};
|
||||
|
||||
const GLOBAL_SCOPE_INDEX: usize = 0;
|
||||
@@ -56,6 +58,7 @@ pub struct Checker<'a> {
|
||||
pub(crate) settings: &'a Settings,
|
||||
pub(crate) noqa_line_for: &'a IntMap<usize, usize>,
|
||||
pub(crate) locator: &'a SourceCodeLocator<'a>,
|
||||
pub(crate) style: &'a SourceCodeStyleDetector<'a>,
|
||||
// Computed checks.
|
||||
checks: Vec<Check>,
|
||||
// Function and class definition tracking (e.g., for docstring enforcement).
|
||||
@@ -107,6 +110,7 @@ impl<'a> Checker<'a> {
|
||||
noqa: flags::Noqa,
|
||||
path: &'a Path,
|
||||
locator: &'a SourceCodeLocator,
|
||||
style: &'a SourceCodeStyleDetector,
|
||||
) -> Checker<'a> {
|
||||
Checker {
|
||||
settings,
|
||||
@@ -115,6 +119,7 @@ impl<'a> Checker<'a> {
|
||||
noqa,
|
||||
path,
|
||||
locator,
|
||||
style,
|
||||
checks: vec![],
|
||||
definitions: vec![],
|
||||
deletions: FxHashSet::default(),
|
||||
@@ -392,10 +397,9 @@ where
|
||||
..
|
||||
} => {
|
||||
if self.settings.enabled.contains(&CheckCode::E743) {
|
||||
if let Some(check) = pycodestyle::checks::ambiguous_function_name(
|
||||
name,
|
||||
Range::from_located(stmt),
|
||||
) {
|
||||
if let Some(check) = pycodestyle::checks::ambiguous_function_name(name, || {
|
||||
helpers::identifier_range(stmt, self.locator)
|
||||
}) {
|
||||
self.add_check(check);
|
||||
}
|
||||
}
|
||||
@@ -580,9 +584,9 @@ where
|
||||
}
|
||||
|
||||
if self.settings.enabled.contains(&CheckCode::E742) {
|
||||
if let Some(check) =
|
||||
pycodestyle::checks::ambiguous_class_name(name, Range::from_located(stmt))
|
||||
{
|
||||
if let Some(check) = pycodestyle::checks::ambiguous_class_name(name, || {
|
||||
helpers::identifier_range(stmt, self.locator)
|
||||
}) {
|
||||
self.add_check(check);
|
||||
}
|
||||
}
|
||||
@@ -645,6 +649,9 @@ where
|
||||
));
|
||||
}
|
||||
}
|
||||
if self.settings.enabled.contains(&CheckCode::UP023) {
|
||||
pyupgrade::plugins::replace_c_element_tree(self, stmt);
|
||||
}
|
||||
|
||||
for alias in names {
|
||||
if alias.node.name.contains('.') && alias.node.asname.is_none() {
|
||||
@@ -715,6 +722,17 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
// flake8_tidy_imports
|
||||
if self.settings.enabled.contains(&CheckCode::TID251) {
|
||||
if let Some(check) = flake8_tidy_imports::checks::name_or_parent_is_banned(
|
||||
alias,
|
||||
&alias.node.name,
|
||||
&self.settings.flake8_tidy_imports.banned_api,
|
||||
) {
|
||||
self.add_check(check);
|
||||
}
|
||||
}
|
||||
|
||||
// pylint
|
||||
if self.settings.enabled.contains(&CheckCode::PLC0414) {
|
||||
pylint::plugins::useless_import_alias(self, alias);
|
||||
@@ -814,6 +832,9 @@ where
|
||||
} => {
|
||||
// Track `import from` statements, to ensure that we can correctly attribute
|
||||
// references like `from typing import Union`.
|
||||
if self.settings.enabled.contains(&CheckCode::UP023) {
|
||||
pyupgrade::plugins::replace_c_element_tree(self, stmt);
|
||||
}
|
||||
if level.map(|level| level == 0).unwrap_or(true) {
|
||||
if let Some(module) = module {
|
||||
self.from_imports
|
||||
@@ -843,6 +864,27 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
if self.settings.enabled.contains(&CheckCode::TID251) {
|
||||
if let Some(module) = module {
|
||||
for name in names {
|
||||
if let Some(check) = flake8_tidy_imports::checks::name_is_banned(
|
||||
module,
|
||||
name,
|
||||
&self.settings.flake8_tidy_imports.banned_api,
|
||||
) {
|
||||
self.add_check(check);
|
||||
}
|
||||
}
|
||||
if let Some(check) = flake8_tidy_imports::checks::name_or_parent_is_banned(
|
||||
stmt,
|
||||
module,
|
||||
&self.settings.flake8_tidy_imports.banned_api,
|
||||
) {
|
||||
self.add_check(check);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for alias in names {
|
||||
if let Some("__future__") = module.as_deref() {
|
||||
let name = alias.node.asname.as_ref().unwrap_or(&alias.node.name);
|
||||
@@ -1487,6 +1529,10 @@ where
|
||||
ExprKind::Name { id, ctx } => {
|
||||
match ctx {
|
||||
ExprContext::Load => {
|
||||
if self.settings.enabled.contains(&CheckCode::UP019) {
|
||||
pyupgrade::plugins::typing_text_str_alias(self, expr);
|
||||
}
|
||||
|
||||
// Ex) List[...]
|
||||
if !self.in_deferred_string_type_definition
|
||||
&& self.settings.enabled.contains(&CheckCode::UP006)
|
||||
@@ -1552,7 +1598,9 @@ where
|
||||
{
|
||||
pyupgrade::plugins::datetime_utc_alias(self, expr);
|
||||
}
|
||||
|
||||
if self.settings.enabled.contains(&CheckCode::UP019) {
|
||||
pyupgrade::plugins::typing_text_str_alias(self, expr);
|
||||
}
|
||||
if self.settings.enabled.contains(&CheckCode::YTT202) {
|
||||
flake8_2020::plugins::name_or_attribute(self, expr);
|
||||
}
|
||||
@@ -1569,6 +1617,15 @@ where
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if self.settings.enabled.contains(&CheckCode::TID251) {
|
||||
flake8_tidy_imports::checks::banned_attribute_access(
|
||||
self,
|
||||
&dealias_call_path(collect_call_paths(expr), &self.import_aliases),
|
||||
expr,
|
||||
&self.settings.flake8_tidy_imports.banned_api,
|
||||
);
|
||||
}
|
||||
}
|
||||
ExprKind::Call {
|
||||
func,
|
||||
@@ -1635,22 +1692,35 @@ where
|
||||
}
|
||||
|
||||
// pyupgrade
|
||||
if self.settings.enabled.contains(&CheckCode::UP003) {
|
||||
pyupgrade::plugins::type_of_primitive(self, expr, func, args);
|
||||
}
|
||||
if self.settings.enabled.contains(&CheckCode::UP005) {
|
||||
pyupgrade::plugins::deprecated_unittest_alias(self, func);
|
||||
}
|
||||
if self.settings.enabled.contains(&CheckCode::UP008) {
|
||||
pyupgrade::plugins::super_call_with_parameters(self, expr, func, args);
|
||||
}
|
||||
if self.settings.enabled.contains(&CheckCode::UP012) {
|
||||
pyupgrade::plugins::unnecessary_encode_utf8(self, expr, func, args, keywords);
|
||||
}
|
||||
if self.settings.enabled.contains(&CheckCode::UP015) {
|
||||
pyupgrade::plugins::redundant_open_modes(self, expr);
|
||||
}
|
||||
if self.settings.enabled.contains(&CheckCode::UP016) {
|
||||
pyupgrade::plugins::remove_six_compat(self, expr);
|
||||
}
|
||||
if self.settings.enabled.contains(&CheckCode::UP018) {
|
||||
pyupgrade::plugins::native_literals(self, expr, func, args, keywords);
|
||||
}
|
||||
|
||||
// flake8-super
|
||||
if self.settings.enabled.contains(&CheckCode::UP008) {
|
||||
pyupgrade::plugins::super_call_with_parameters(self, expr, func, args);
|
||||
if self.settings.enabled.contains(&CheckCode::UP020) {
|
||||
pyupgrade::plugins::open_alias(self, expr, func);
|
||||
}
|
||||
if self.settings.enabled.contains(&CheckCode::UP021) {
|
||||
pyupgrade::plugins::replace_universal_newlines(self, expr, keywords);
|
||||
}
|
||||
if self.settings.enabled.contains(&CheckCode::UP022) {
|
||||
pyupgrade::plugins::replace_stdout_stderr(self, expr, keywords);
|
||||
}
|
||||
|
||||
// flake8-print
|
||||
@@ -1715,7 +1785,6 @@ where
|
||||
self.add_check(check);
|
||||
};
|
||||
}
|
||||
|
||||
if self.settings.enabled.contains(&CheckCode::C401) {
|
||||
if let Some(check) = flake8_comprehensions::checks::unnecessary_generator_set(
|
||||
expr,
|
||||
@@ -1729,7 +1798,6 @@ where
|
||||
self.add_check(check);
|
||||
};
|
||||
}
|
||||
|
||||
if self.settings.enabled.contains(&CheckCode::C402) {
|
||||
if let Some(check) = flake8_comprehensions::checks::unnecessary_generator_dict(
|
||||
expr,
|
||||
@@ -1743,7 +1811,6 @@ where
|
||||
self.add_check(check);
|
||||
};
|
||||
}
|
||||
|
||||
if self.settings.enabled.contains(&CheckCode::C403) {
|
||||
if let Some(check) =
|
||||
flake8_comprehensions::checks::unnecessary_list_comprehension_set(
|
||||
@@ -1759,7 +1826,6 @@ where
|
||||
self.add_check(check);
|
||||
};
|
||||
}
|
||||
|
||||
if self.settings.enabled.contains(&CheckCode::C404) {
|
||||
if let Some(check) =
|
||||
flake8_comprehensions::checks::unnecessary_list_comprehension_dict(
|
||||
@@ -1775,7 +1841,6 @@ where
|
||||
self.add_check(check);
|
||||
};
|
||||
}
|
||||
|
||||
if self.settings.enabled.contains(&CheckCode::C405) {
|
||||
if let Some(check) = flake8_comprehensions::checks::unnecessary_literal_set(
|
||||
expr,
|
||||
@@ -1789,7 +1854,6 @@ where
|
||||
self.add_check(check);
|
||||
};
|
||||
}
|
||||
|
||||
if self.settings.enabled.contains(&CheckCode::C406) {
|
||||
if let Some(check) = flake8_comprehensions::checks::unnecessary_literal_dict(
|
||||
expr,
|
||||
@@ -1803,7 +1867,6 @@ where
|
||||
self.add_check(check);
|
||||
};
|
||||
}
|
||||
|
||||
if self.settings.enabled.contains(&CheckCode::C408) {
|
||||
if let Some(check) = flake8_comprehensions::checks::unnecessary_collection_call(
|
||||
expr,
|
||||
@@ -1817,7 +1880,6 @@ where
|
||||
self.add_check(check);
|
||||
};
|
||||
}
|
||||
|
||||
if self.settings.enabled.contains(&CheckCode::C409) {
|
||||
if let Some(check) =
|
||||
flake8_comprehensions::checks::unnecessary_literal_within_tuple_call(
|
||||
@@ -1832,7 +1894,6 @@ where
|
||||
self.add_check(check);
|
||||
};
|
||||
}
|
||||
|
||||
if self.settings.enabled.contains(&CheckCode::C410) {
|
||||
if let Some(check) =
|
||||
flake8_comprehensions::checks::unnecessary_literal_within_list_call(
|
||||
@@ -1847,7 +1908,6 @@ where
|
||||
self.add_check(check);
|
||||
};
|
||||
}
|
||||
|
||||
if self.settings.enabled.contains(&CheckCode::C411) {
|
||||
if let Some(check) = flake8_comprehensions::checks::unnecessary_list_call(
|
||||
expr,
|
||||
@@ -1860,7 +1920,6 @@ where
|
||||
self.add_check(check);
|
||||
};
|
||||
}
|
||||
|
||||
if self.settings.enabled.contains(&CheckCode::C413) {
|
||||
if let Some(check) =
|
||||
flake8_comprehensions::checks::unnecessary_call_around_sorted(
|
||||
@@ -1875,7 +1934,6 @@ where
|
||||
self.add_check(check);
|
||||
};
|
||||
}
|
||||
|
||||
if self.settings.enabled.contains(&CheckCode::C414) {
|
||||
if let Some(check) =
|
||||
flake8_comprehensions::checks::unnecessary_double_cast_or_process(
|
||||
@@ -1887,7 +1945,6 @@ where
|
||||
self.add_check(check);
|
||||
};
|
||||
}
|
||||
|
||||
if self.settings.enabled.contains(&CheckCode::C415) {
|
||||
if let Some(check) =
|
||||
flake8_comprehensions::checks::unnecessary_subscript_reversal(
|
||||
@@ -1899,7 +1956,6 @@ where
|
||||
self.add_check(check);
|
||||
};
|
||||
}
|
||||
|
||||
if self.settings.enabled.contains(&CheckCode::C417) {
|
||||
if let Some(check) = flake8_comprehensions::checks::unnecessary_map(
|
||||
func,
|
||||
@@ -1910,15 +1966,6 @@ where
|
||||
};
|
||||
}
|
||||
|
||||
// pyupgrade
|
||||
if self.settings.enabled.contains(&CheckCode::UP003) {
|
||||
pyupgrade::plugins::type_of_primitive(self, expr, func, args);
|
||||
}
|
||||
|
||||
if self.settings.enabled.contains(&CheckCode::UP015) {
|
||||
pyupgrade::plugins::redundant_open_modes(self, expr);
|
||||
}
|
||||
|
||||
// flake8-boolean-trap
|
||||
if self.settings.enabled.contains(&CheckCode::FBT003) {
|
||||
flake8_boolean_trap::plugins::check_boolean_positional_value_in_function_call(
|
||||
@@ -1949,7 +1996,6 @@ where
|
||||
if self.settings.enabled.contains(&CheckCode::PD002) {
|
||||
self.add_checks(pandas_vet::checks::inplace_argument(keywords).into_iter());
|
||||
}
|
||||
|
||||
for (code, name) in vec![
|
||||
(CheckCode::PD003, "isnull"),
|
||||
(CheckCode::PD004, "notnull"),
|
||||
@@ -1966,7 +2012,6 @@ where
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if self.settings.enabled.contains(&CheckCode::PD015) {
|
||||
if let Some(check) = pandas_vet::checks::use_of_pd_merge(func) {
|
||||
self.add_check(check);
|
||||
@@ -2060,6 +2105,14 @@ where
|
||||
if self.settings.enabled.contains(&CheckCode::PLR1722) {
|
||||
pylint::plugins::use_sys_exit(self, func);
|
||||
}
|
||||
|
||||
// ruff
|
||||
if self.settings.enabled.contains(&CheckCode::RUF004) {
|
||||
self.add_checks(
|
||||
ruff::checks::keyword_argument_before_star_argument(args, keywords)
|
||||
.into_iter(),
|
||||
);
|
||||
}
|
||||
}
|
||||
ExprKind::Dict { keys, .. } => {
|
||||
let check_repeated_literals = self.settings.enabled.contains(&CheckCode::F601);
|
||||
@@ -2217,6 +2270,15 @@ where
|
||||
}
|
||||
}
|
||||
}
|
||||
ExprKind::BinOp {
|
||||
op: Operator::Add, ..
|
||||
} => {
|
||||
if self.settings.enabled.contains(&CheckCode::ISC003) {
|
||||
if let Some(check) = flake8_implicit_str_concat::checks::explicit(expr) {
|
||||
self.add_check(check);
|
||||
}
|
||||
}
|
||||
}
|
||||
ExprKind::UnaryOp { op, operand } => {
|
||||
let check_not_in = self.settings.enabled.contains(&CheckCode::E713);
|
||||
let check_not_is = self.settings.enabled.contains(&CheckCode::E714);
|
||||
@@ -2316,7 +2378,7 @@ where
|
||||
}
|
||||
ExprKind::Constant {
|
||||
value: Constant::Str(value),
|
||||
..
|
||||
kind,
|
||||
} => {
|
||||
if self.in_type_definition && !self.in_literal {
|
||||
self.deferred_string_type_definitions.push((
|
||||
@@ -2334,6 +2396,9 @@ where
|
||||
self.add_check(check);
|
||||
}
|
||||
}
|
||||
if self.settings.enabled.contains(&CheckCode::UP025) {
|
||||
pyupgrade::plugins::rewrite_unicode_literal(self, expr, value, kind);
|
||||
}
|
||||
}
|
||||
ExprKind::Lambda { args, body, .. } => {
|
||||
// Visit the arguments, but avoid the body, which will be deferred.
|
||||
@@ -2664,12 +2729,15 @@ where
|
||||
|
||||
self.check_builtin_shadowing(name, excepthandler, false);
|
||||
|
||||
let name_range =
|
||||
helpers::excepthandler_name_range(excepthandler, self.locator).unwrap();
|
||||
|
||||
if self.current_scope().values.contains_key(&name.as_str()) {
|
||||
self.handle_node_store(
|
||||
name,
|
||||
&Expr::new(
|
||||
excepthandler.location,
|
||||
excepthandler.end_location.unwrap(),
|
||||
name_range.location,
|
||||
name_range.end_location,
|
||||
ExprKind::Name {
|
||||
id: name.to_string(),
|
||||
ctx: ExprContext::Store,
|
||||
@@ -2682,8 +2750,8 @@ where
|
||||
self.handle_node_store(
|
||||
name,
|
||||
&Expr::new(
|
||||
excepthandler.location,
|
||||
excepthandler.end_location.unwrap(),
|
||||
name_range.location,
|
||||
name_range.end_location,
|
||||
ExprKind::Name {
|
||||
id: name.to_string(),
|
||||
ctx: ExprContext::Store,
|
||||
@@ -2702,7 +2770,7 @@ where
|
||||
if self.settings.enabled.contains(&CheckCode::F841) {
|
||||
self.add_check(Check::new(
|
||||
CheckKind::UnusedVariable(name.to_string()),
|
||||
Range::from_located(excepthandler),
|
||||
name_range,
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -3862,7 +3930,11 @@ impl<'a> Checker<'a> {
|
||||
|| self.settings.enabled.contains(&CheckCode::D416)
|
||||
|| self.settings.enabled.contains(&CheckCode::D417)
|
||||
{
|
||||
pydocstyle::plugins::sections(self, &docstring);
|
||||
pydocstyle::plugins::sections(
|
||||
self,
|
||||
&docstring,
|
||||
self.settings.pydocstyle.convention.as_ref(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3905,16 +3977,26 @@ impl<'a> Checker<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn check_ast(
|
||||
python_ast: &Suite,
|
||||
locator: &SourceCodeLocator,
|
||||
stylist: &SourceCodeStyleDetector,
|
||||
noqa_line_for: &IntMap<usize, usize>,
|
||||
settings: &Settings,
|
||||
autofix: flags::Autofix,
|
||||
noqa: flags::Noqa,
|
||||
path: &Path,
|
||||
) -> Vec<Check> {
|
||||
let mut checker = Checker::new(settings, noqa_line_for, autofix, noqa, path, locator);
|
||||
let mut checker = Checker::new(
|
||||
settings,
|
||||
noqa_line_for,
|
||||
autofix,
|
||||
noqa,
|
||||
path,
|
||||
locator,
|
||||
stylist,
|
||||
);
|
||||
checker.push_scope(Scope::new(ScopeKind::Module));
|
||||
checker.bind_builtins();
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
use crate::checks::{Check, CheckCode};
|
||||
use crate::pycodestyle::checks::{line_too_long, no_newline_at_end_of_file};
|
||||
use crate::pygrep_hooks::plugins::blanket_type_ignore;
|
||||
use crate::pygrep_hooks::plugins::{blanket_noqa, blanket_type_ignore};
|
||||
use crate::pyupgrade::checks::unnecessary_coding_comment;
|
||||
use crate::settings::{flags, Settings};
|
||||
|
||||
@@ -18,6 +18,7 @@ pub fn check_lines(
|
||||
let enforce_line_too_long = settings.enabled.contains(&CheckCode::E501);
|
||||
let enforce_no_newline_at_end_of_file = settings.enabled.contains(&CheckCode::W292);
|
||||
let enforce_blanket_type_ignore = settings.enabled.contains(&CheckCode::PGH003);
|
||||
let enforce_blanket_noqa = settings.enabled.contains(&CheckCode::PGH004);
|
||||
|
||||
let mut commented_lines_iter = commented_lines.iter().peekable();
|
||||
for (index, line) in contents.lines().enumerate() {
|
||||
@@ -45,6 +46,14 @@ pub fn check_lines(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if enforce_blanket_noqa {
|
||||
if commented_lines.contains(&(index + 1)) {
|
||||
if let Some(check) = blanket_noqa(index, line) {
|
||||
checks.push(check);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if enforce_line_too_long {
|
||||
|
||||
@@ -49,6 +49,9 @@ pub fn check_noqa(
|
||||
while let Some((index, check)) =
|
||||
checks_iter.next_if(|(_index, check)| check.location.row() <= *lineno)
|
||||
{
|
||||
if check.kind == CheckKind::BlanketNOQA {
|
||||
continue;
|
||||
}
|
||||
// Grab the noqa (logical) line number for the current (physical) line.
|
||||
// If there are newlines at the end of the file, they won't be represented in
|
||||
// `noqa_line_for`, so fallback to the current line.
|
||||
|
||||
@@ -7,7 +7,7 @@ use crate::lex::docstring_detection::StateMachine;
|
||||
use crate::ruff::checks::Context;
|
||||
use crate::settings::flags;
|
||||
use crate::source_code_locator::SourceCodeLocator;
|
||||
use crate::{eradicate, flake8_quotes, pycodestyle, ruff, Settings};
|
||||
use crate::{eradicate, flake8_implicit_str_concat, flake8_quotes, pycodestyle, ruff, Settings};
|
||||
|
||||
pub fn check_tokens(
|
||||
locator: &SourceCodeLocator,
|
||||
@@ -26,6 +26,8 @@ pub fn check_tokens(
|
||||
|| settings.enabled.contains(&CheckCode::Q003);
|
||||
let enforce_commented_out_code = settings.enabled.contains(&CheckCode::ERA001);
|
||||
let enforce_invalid_escape_sequence = settings.enabled.contains(&CheckCode::W605);
|
||||
let enforce_implicit_string_concatenation = settings.enabled.contains(&CheckCode::ISC001)
|
||||
|| settings.enabled.contains(&CheckCode::ISC002);
|
||||
|
||||
let mut state_machine = StateMachine::default();
|
||||
for &(start, ref tok, end) in tokens.iter().flatten() {
|
||||
@@ -99,5 +101,14 @@ pub fn check_tokens(
|
||||
}
|
||||
}
|
||||
|
||||
// ISC001, ISC002
|
||||
if enforce_implicit_string_concatenation {
|
||||
checks.extend(
|
||||
flake8_implicit_str_concat::checks::implicit(tokens, locator)
|
||||
.into_iter()
|
||||
.filter(|check| settings.enabled.contains(check.kind.code())),
|
||||
);
|
||||
}
|
||||
|
||||
checks
|
||||
}
|
||||
|
||||
137
src/checks.rs
137
src/checks.rs
@@ -165,6 +165,7 @@ pub enum CheckCode {
|
||||
// mccabe
|
||||
C901,
|
||||
// flake8-tidy-imports
|
||||
TID251,
|
||||
TID252,
|
||||
// flake8-return
|
||||
RET501,
|
||||
@@ -175,6 +176,10 @@ pub enum CheckCode {
|
||||
RET506,
|
||||
RET507,
|
||||
RET508,
|
||||
// flake8-implicit-str-concat
|
||||
ISC001,
|
||||
ISC002,
|
||||
ISC003,
|
||||
// flake8-print
|
||||
T201,
|
||||
T203,
|
||||
@@ -226,6 +231,12 @@ pub enum CheckCode {
|
||||
UP016,
|
||||
UP017,
|
||||
UP018,
|
||||
UP019,
|
||||
UP020,
|
||||
UP021,
|
||||
UP022,
|
||||
UP023,
|
||||
UP025,
|
||||
// pydocstyle
|
||||
D100,
|
||||
D101,
|
||||
@@ -325,11 +336,13 @@ pub enum CheckCode {
|
||||
RUF001,
|
||||
RUF002,
|
||||
RUF003,
|
||||
RUF004,
|
||||
RUF100,
|
||||
// pygrep-hooks
|
||||
PGH001,
|
||||
PGH002,
|
||||
PGH003,
|
||||
PGH004,
|
||||
// pandas-vet
|
||||
PD002,
|
||||
PD003,
|
||||
@@ -368,6 +381,7 @@ pub enum CheckCategory {
|
||||
Flake8Comprehensions,
|
||||
Flake8Debugger,
|
||||
Flake8ErrMsg,
|
||||
Flake8ImplicitStrConcat,
|
||||
Flake8ImportConventions,
|
||||
Flake8Print,
|
||||
Flake8Quotes,
|
||||
@@ -411,6 +425,7 @@ impl CheckCategory {
|
||||
CheckCategory::Flake8Comprehensions => "flake8-comprehensions",
|
||||
CheckCategory::Flake8Debugger => "flake8-debugger",
|
||||
CheckCategory::Flake8ErrMsg => "flake8-errmsg",
|
||||
CheckCategory::Flake8ImplicitStrConcat => "flake8-implicit-str-concat",
|
||||
CheckCategory::Flake8ImportConventions => "flake8-import-conventions",
|
||||
CheckCategory::Flake8Print => "flake8-print",
|
||||
CheckCategory::Flake8Quotes => "flake8-quotes",
|
||||
@@ -444,19 +459,21 @@ impl CheckCategory {
|
||||
CheckCategory::Flake8Bugbear => vec![CheckCodePrefix::B],
|
||||
CheckCategory::Flake8Builtins => vec![CheckCodePrefix::A],
|
||||
CheckCategory::Flake8Comprehensions => vec![CheckCodePrefix::C4],
|
||||
CheckCategory::Flake8Datetimez => vec![CheckCodePrefix::DTZ],
|
||||
CheckCategory::Flake8Debugger => vec![CheckCodePrefix::T10],
|
||||
CheckCategory::Flake8ErrMsg => vec![CheckCodePrefix::EM],
|
||||
CheckCategory::Flake8ImplicitStrConcat => vec![CheckCodePrefix::ISC],
|
||||
CheckCategory::Flake8ImportConventions => vec![CheckCodePrefix::ICN],
|
||||
CheckCategory::Flake8Print => vec![CheckCodePrefix::T20],
|
||||
CheckCategory::Flake8Quotes => vec![CheckCodePrefix::Q],
|
||||
CheckCategory::Flake8Return => vec![CheckCodePrefix::RET],
|
||||
CheckCategory::Flake8Simplify => vec![CheckCodePrefix::SIM],
|
||||
CheckCategory::Flake8TidyImports => vec![CheckCodePrefix::TID],
|
||||
CheckCategory::Flake8UnusedArguments => vec![CheckCodePrefix::ARG],
|
||||
CheckCategory::Flake8Datetimez => vec![CheckCodePrefix::DTZ],
|
||||
CheckCategory::Isort => vec![CheckCodePrefix::I],
|
||||
CheckCategory::McCabe => vec![CheckCodePrefix::C90],
|
||||
CheckCategory::PandasVet => vec![CheckCodePrefix::PD],
|
||||
CheckCategory::PEP8Naming => vec![CheckCodePrefix::N],
|
||||
CheckCategory::PandasVet => vec![CheckCodePrefix::PD],
|
||||
CheckCategory::Pycodestyle => vec![CheckCodePrefix::E, CheckCodePrefix::W],
|
||||
CheckCategory::Pydocstyle => vec![CheckCodePrefix::D],
|
||||
CheckCategory::Pyflakes => vec![CheckCodePrefix::F],
|
||||
@@ -468,7 +485,6 @@ impl CheckCategory {
|
||||
CheckCodePrefix::PLW,
|
||||
],
|
||||
CheckCategory::Pyupgrade => vec![CheckCodePrefix::UP],
|
||||
CheckCategory::Flake8ImportConventions => vec![CheckCodePrefix::ICN],
|
||||
CheckCategory::Ruff => vec![CheckCodePrefix::RUF],
|
||||
}
|
||||
}
|
||||
@@ -518,6 +534,10 @@ impl CheckCategory {
|
||||
"https://pypi.org/project/flake8-errmsg/0.4.0/",
|
||||
&Platform::PyPI,
|
||||
)),
|
||||
CheckCategory::Flake8ImplicitStrConcat => Some((
|
||||
"https://pypi.org/project/flake8-implicit-str-concat/0.3.0/",
|
||||
&Platform::PyPI,
|
||||
)),
|
||||
CheckCategory::Flake8ImportConventions => None,
|
||||
CheckCategory::Flake8Print => Some((
|
||||
"https://pypi.org/project/flake8-print/5.0.0/",
|
||||
@@ -776,6 +796,7 @@ pub enum CheckKind {
|
||||
// flake8-debugger
|
||||
Debugger(DebuggerUsingType),
|
||||
// flake8-tidy-imports
|
||||
BannedApi { name: String, message: String },
|
||||
BannedRelativeImport(Strictness),
|
||||
// flake8-return
|
||||
UnnecessaryReturnNone,
|
||||
@@ -786,6 +807,10 @@ pub enum CheckKind {
|
||||
SuperfluousElseRaise(Branch),
|
||||
SuperfluousElseContinue(Branch),
|
||||
SuperfluousElseBreak(Branch),
|
||||
// flake8-implicit-str-concat
|
||||
SingleLineImplicitStringConcatenation,
|
||||
MultiLineImplicitStringConcatenation,
|
||||
ExplicitStringConcatenation,
|
||||
// flake8-print
|
||||
PrintFound,
|
||||
PPrintFound,
|
||||
@@ -822,6 +847,7 @@ pub enum CheckKind {
|
||||
// pyupgrade
|
||||
TypeOfPrimitive(Primitive),
|
||||
UselessMetaclassType,
|
||||
TypingTextStrAlias,
|
||||
DeprecatedUnittestAlias(String, String),
|
||||
UselessObjectInheritance(String),
|
||||
UsePEP585Annotation(String),
|
||||
@@ -837,6 +863,11 @@ pub enum CheckKind {
|
||||
RemoveSixCompat,
|
||||
DatetimeTimezoneUTC,
|
||||
NativeLiterals,
|
||||
OpenAlias,
|
||||
ReplaceUniversalNewlines,
|
||||
ReplaceStdoutStderr,
|
||||
RewriteCElementTree,
|
||||
RewriteUnicodeLiteral,
|
||||
// pydocstyle
|
||||
BlankLineAfterLastSection(String),
|
||||
BlankLineAfterSection(String),
|
||||
@@ -920,6 +951,7 @@ pub enum CheckKind {
|
||||
NoEval,
|
||||
DeprecatedLogWarn,
|
||||
BlanketTypeIgnore,
|
||||
BlanketNOQA,
|
||||
// flake8-unused-arguments
|
||||
UnusedFunctionArgument(String),
|
||||
UnusedMethodArgument(String),
|
||||
@@ -949,6 +981,7 @@ pub enum CheckKind {
|
||||
AmbiguousUnicodeCharacterString(char, char),
|
||||
AmbiguousUnicodeCharacterDocstring(char, char),
|
||||
AmbiguousUnicodeCharacterComment(char, char),
|
||||
KeywordArgumentBeforeStarArgument(String),
|
||||
UnusedNOQA(Option<UnusedCodes>),
|
||||
// flake8-datetimez
|
||||
CallDatetimeWithoutTzinfo,
|
||||
@@ -968,10 +1001,14 @@ impl CheckCode {
|
||||
pub fn lint_source(&self) -> &'static LintSource {
|
||||
match self {
|
||||
CheckCode::RUF100 => &LintSource::NoQA,
|
||||
CheckCode::E501 | CheckCode::W292 | CheckCode::UP009 | CheckCode::PGH003 => {
|
||||
&LintSource::Lines
|
||||
}
|
||||
CheckCode::E501
|
||||
| CheckCode::W292
|
||||
| CheckCode::UP009
|
||||
| CheckCode::PGH003
|
||||
| CheckCode::PGH004 => &LintSource::Lines,
|
||||
CheckCode::ERA001
|
||||
| CheckCode::ISC001
|
||||
| CheckCode::ISC002
|
||||
| CheckCode::Q000
|
||||
| CheckCode::Q001
|
||||
| CheckCode::Q002
|
||||
@@ -1146,6 +1183,10 @@ impl CheckCode {
|
||||
// flake8-debugger
|
||||
CheckCode::T100 => CheckKind::Debugger(DebuggerUsingType::Import("...".to_string())),
|
||||
// flake8-tidy-imports
|
||||
CheckCode::TID251 => CheckKind::BannedApi {
|
||||
name: "...".to_string(),
|
||||
message: "...".to_string(),
|
||||
},
|
||||
CheckCode::TID252 => CheckKind::BannedRelativeImport(Strictness::All),
|
||||
// flake8-return
|
||||
CheckCode::RET501 => CheckKind::UnnecessaryReturnNone,
|
||||
@@ -1156,6 +1197,10 @@ impl CheckCode {
|
||||
CheckCode::RET506 => CheckKind::SuperfluousElseRaise(Branch::Else),
|
||||
CheckCode::RET507 => CheckKind::SuperfluousElseContinue(Branch::Else),
|
||||
CheckCode::RET508 => CheckKind::SuperfluousElseBreak(Branch::Else),
|
||||
// flake8-implicit-str-concat
|
||||
CheckCode::ISC001 => CheckKind::SingleLineImplicitStringConcatenation,
|
||||
CheckCode::ISC002 => CheckKind::MultiLineImplicitStringConcatenation,
|
||||
CheckCode::ISC003 => CheckKind::ExplicitStringConcatenation,
|
||||
// flake8-print
|
||||
CheckCode::T201 => CheckKind::PrintFound,
|
||||
CheckCode::T203 => CheckKind::PPrintFound,
|
||||
@@ -1212,6 +1257,12 @@ impl CheckCode {
|
||||
CheckCode::UP016 => CheckKind::RemoveSixCompat,
|
||||
CheckCode::UP017 => CheckKind::DatetimeTimezoneUTC,
|
||||
CheckCode::UP018 => CheckKind::NativeLiterals,
|
||||
CheckCode::UP019 => CheckKind::TypingTextStrAlias,
|
||||
CheckCode::UP020 => CheckKind::OpenAlias,
|
||||
CheckCode::UP021 => CheckKind::ReplaceUniversalNewlines,
|
||||
CheckCode::UP022 => CheckKind::ReplaceStdoutStderr,
|
||||
CheckCode::UP023 => CheckKind::RewriteCElementTree,
|
||||
CheckCode::UP025 => CheckKind::RewriteUnicodeLiteral,
|
||||
// pydocstyle
|
||||
CheckCode::D100 => CheckKind::PublicModule,
|
||||
CheckCode::D101 => CheckKind::PublicClass,
|
||||
@@ -1310,6 +1361,7 @@ impl CheckCode {
|
||||
CheckCode::PGH001 => CheckKind::NoEval,
|
||||
CheckCode::PGH002 => CheckKind::DeprecatedLogWarn,
|
||||
CheckCode::PGH003 => CheckKind::BlanketTypeIgnore,
|
||||
CheckCode::PGH004 => CheckKind::BlanketNOQA,
|
||||
// flake8-unused-arguments
|
||||
CheckCode::ARG001 => CheckKind::UnusedFunctionArgument("...".to_string()),
|
||||
CheckCode::ARG002 => CheckKind::UnusedMethodArgument("...".to_string()),
|
||||
@@ -1351,6 +1403,7 @@ impl CheckCode {
|
||||
CheckCode::RUF001 => CheckKind::AmbiguousUnicodeCharacterString('𝐁', 'B'),
|
||||
CheckCode::RUF002 => CheckKind::AmbiguousUnicodeCharacterDocstring('𝐁', 'B'),
|
||||
CheckCode::RUF003 => CheckKind::AmbiguousUnicodeCharacterComment('𝐁', 'B'),
|
||||
CheckCode::RUF004 => CheckKind::KeywordArgumentBeforeStarArgument("...".to_string()),
|
||||
CheckCode::RUF100 => CheckKind::UnusedNOQA(None),
|
||||
}
|
||||
}
|
||||
@@ -1544,8 +1597,10 @@ impl CheckCode {
|
||||
CheckCode::FBT002 => CheckCategory::Flake8BooleanTrap,
|
||||
CheckCode::FBT003 => CheckCategory::Flake8BooleanTrap,
|
||||
CheckCode::I001 => CheckCategory::Isort,
|
||||
CheckCode::TID252 => CheckCategory::Flake8TidyImports,
|
||||
CheckCode::ICN001 => CheckCategory::Flake8ImportConventions,
|
||||
CheckCode::ISC001 => CheckCategory::Flake8ImplicitStrConcat,
|
||||
CheckCode::ISC002 => CheckCategory::Flake8ImplicitStrConcat,
|
||||
CheckCode::ISC003 => CheckCategory::Flake8ImplicitStrConcat,
|
||||
CheckCode::N801 => CheckCategory::PEP8Naming,
|
||||
CheckCode::N802 => CheckCategory::PEP8Naming,
|
||||
CheckCode::N803 => CheckCategory::PEP8Naming,
|
||||
@@ -1576,6 +1631,7 @@ impl CheckCode {
|
||||
CheckCode::PGH001 => CheckCategory::PygrepHooks,
|
||||
CheckCode::PGH002 => CheckCategory::PygrepHooks,
|
||||
CheckCode::PGH003 => CheckCategory::PygrepHooks,
|
||||
CheckCode::PGH004 => CheckCategory::PygrepHooks,
|
||||
CheckCode::PLC0414 => CheckCategory::Pylint,
|
||||
CheckCode::PLC2201 => CheckCategory::Pylint,
|
||||
CheckCode::PLC3002 => CheckCategory::Pylint,
|
||||
@@ -1603,6 +1659,7 @@ impl CheckCode {
|
||||
CheckCode::RUF001 => CheckCategory::Ruff,
|
||||
CheckCode::RUF002 => CheckCategory::Ruff,
|
||||
CheckCode::RUF003 => CheckCategory::Ruff,
|
||||
CheckCode::RUF004 => CheckCategory::Ruff,
|
||||
CheckCode::RUF100 => CheckCategory::Ruff,
|
||||
CheckCode::S101 => CheckCategory::Flake8Bandit,
|
||||
CheckCode::S102 => CheckCategory::Flake8Bandit,
|
||||
@@ -1614,6 +1671,8 @@ impl CheckCode {
|
||||
CheckCode::T100 => CheckCategory::Flake8Debugger,
|
||||
CheckCode::T201 => CheckCategory::Flake8Print,
|
||||
CheckCode::T203 => CheckCategory::Flake8Print,
|
||||
CheckCode::TID251 => CheckCategory::Flake8TidyImports,
|
||||
CheckCode::TID252 => CheckCategory::Flake8TidyImports,
|
||||
CheckCode::UP001 => CheckCategory::Pyupgrade,
|
||||
CheckCode::UP003 => CheckCategory::Pyupgrade,
|
||||
CheckCode::UP004 => CheckCategory::Pyupgrade,
|
||||
@@ -1631,6 +1690,12 @@ impl CheckCode {
|
||||
CheckCode::UP016 => CheckCategory::Pyupgrade,
|
||||
CheckCode::UP017 => CheckCategory::Pyupgrade,
|
||||
CheckCode::UP018 => CheckCategory::Pyupgrade,
|
||||
CheckCode::UP019 => CheckCategory::Pyupgrade,
|
||||
CheckCode::UP020 => CheckCategory::Pyupgrade,
|
||||
CheckCode::UP021 => CheckCategory::Pyupgrade,
|
||||
CheckCode::UP022 => CheckCategory::Pyupgrade,
|
||||
CheckCode::UP023 => CheckCategory::Pyupgrade,
|
||||
CheckCode::UP025 => CheckCategory::Pyupgrade,
|
||||
CheckCode::W292 => CheckCategory::Pycodestyle,
|
||||
CheckCode::W605 => CheckCategory::Pycodestyle,
|
||||
CheckCode::YTT101 => CheckCategory::Flake82020,
|
||||
@@ -1782,6 +1847,7 @@ impl CheckKind {
|
||||
// flake8-debugger
|
||||
CheckKind::Debugger(..) => &CheckCode::T100,
|
||||
// flake8-tidy-imports
|
||||
CheckKind::BannedApi { .. } => &CheckCode::TID251,
|
||||
CheckKind::BannedRelativeImport(..) => &CheckCode::TID252,
|
||||
// flake8-return
|
||||
CheckKind::UnnecessaryReturnNone => &CheckCode::RET501,
|
||||
@@ -1792,6 +1858,10 @@ impl CheckKind {
|
||||
CheckKind::SuperfluousElseRaise(..) => &CheckCode::RET506,
|
||||
CheckKind::SuperfluousElseContinue(..) => &CheckCode::RET507,
|
||||
CheckKind::SuperfluousElseBreak(..) => &CheckCode::RET508,
|
||||
// flake8-implicit-str-concat
|
||||
CheckKind::SingleLineImplicitStringConcatenation => &CheckCode::ISC001,
|
||||
CheckKind::MultiLineImplicitStringConcatenation => &CheckCode::ISC002,
|
||||
CheckKind::ExplicitStringConcatenation => &CheckCode::ISC003,
|
||||
// flake8-print
|
||||
CheckKind::PrintFound => &CheckCode::T201,
|
||||
CheckKind::PPrintFound => &CheckCode::T203,
|
||||
@@ -1843,6 +1913,12 @@ impl CheckKind {
|
||||
CheckKind::RemoveSixCompat => &CheckCode::UP016,
|
||||
CheckKind::DatetimeTimezoneUTC => &CheckCode::UP017,
|
||||
CheckKind::NativeLiterals => &CheckCode::UP018,
|
||||
CheckKind::TypingTextStrAlias => &CheckCode::UP019,
|
||||
CheckKind::OpenAlias => &CheckCode::UP020,
|
||||
CheckKind::ReplaceUniversalNewlines => &CheckCode::UP021,
|
||||
CheckKind::ReplaceStdoutStderr => &CheckCode::UP022,
|
||||
CheckKind::RewriteCElementTree => &CheckCode::UP023,
|
||||
CheckKind::RewriteUnicodeLiteral => &CheckCode::UP025,
|
||||
// pydocstyle
|
||||
CheckKind::BlankLineAfterLastSection(..) => &CheckCode::D413,
|
||||
CheckKind::BlankLineAfterSection(..) => &CheckCode::D410,
|
||||
@@ -1926,6 +2002,7 @@ impl CheckKind {
|
||||
CheckKind::NoEval => &CheckCode::PGH001,
|
||||
CheckKind::DeprecatedLogWarn => &CheckCode::PGH002,
|
||||
CheckKind::BlanketTypeIgnore => &CheckCode::PGH003,
|
||||
CheckKind::BlanketNOQA => &CheckCode::PGH004,
|
||||
// flake8-unused-arguments
|
||||
CheckKind::UnusedFunctionArgument(..) => &CheckCode::ARG001,
|
||||
CheckKind::UnusedMethodArgument(..) => &CheckCode::ARG002,
|
||||
@@ -1965,6 +2042,7 @@ impl CheckKind {
|
||||
CheckKind::AmbiguousUnicodeCharacterString(..) => &CheckCode::RUF001,
|
||||
CheckKind::AmbiguousUnicodeCharacterDocstring(..) => &CheckCode::RUF002,
|
||||
CheckKind::AmbiguousUnicodeCharacterComment(..) => &CheckCode::RUF003,
|
||||
CheckKind::KeywordArgumentBeforeStarArgument(..) => &CheckCode::RUF004,
|
||||
CheckKind::UnusedNOQA(..) => &CheckCode::RUF100,
|
||||
}
|
||||
}
|
||||
@@ -2402,6 +2480,7 @@ impl CheckKind {
|
||||
DebuggerUsingType::Import(name) => format!("Import for `{name}` found"),
|
||||
},
|
||||
// flake8-tidy-imports
|
||||
CheckKind::BannedApi { name, message } => format!("`{name}` is banned: {message}"),
|
||||
CheckKind::BannedRelativeImport(strictness) => match strictness {
|
||||
Strictness::Parents => {
|
||||
"Relative imports from parent modules are banned".to_string()
|
||||
@@ -2433,6 +2512,16 @@ impl CheckKind {
|
||||
CheckKind::SuperfluousElseBreak(branch) => {
|
||||
format!("Unnecessary `{branch}` after `break` statement")
|
||||
}
|
||||
// flake8-implicit-str-concat
|
||||
CheckKind::SingleLineImplicitStringConcatenation => {
|
||||
"Implicitly concatenated string literals on one line".to_string()
|
||||
}
|
||||
CheckKind::MultiLineImplicitStringConcatenation => {
|
||||
"Implicitly concatenated string literals over continuation line".to_string()
|
||||
}
|
||||
CheckKind::ExplicitStringConcatenation => {
|
||||
"Explicitly concatenated string should be implicitly concatenated".to_string()
|
||||
}
|
||||
// flake8-print
|
||||
CheckKind::PrintFound => "`print` found".to_string(),
|
||||
CheckKind::PPrintFound => "`pprint` found".to_string(),
|
||||
@@ -2533,8 +2622,9 @@ impl CheckKind {
|
||||
format!("Use `{}` instead of `type(...)`", primitive.builtin())
|
||||
}
|
||||
CheckKind::UselessMetaclassType => "`__metaclass__ = type` is implied".to_string(),
|
||||
CheckKind::TypingTextStrAlias => "`typing.Text` is deprecated, use `str`".to_string(),
|
||||
CheckKind::DeprecatedUnittestAlias(alias, target) => {
|
||||
format!("`{alias}` is deprecated, use `{target}` instead")
|
||||
format!("`{alias}` is deprecated, use `{target}`")
|
||||
}
|
||||
CheckKind::UselessObjectInheritance(name) => {
|
||||
format!("Class `{name}` inherits from object")
|
||||
@@ -2567,9 +2657,20 @@ impl CheckKind {
|
||||
CheckKind::RemoveSixCompat => "Unnecessary `six` compatibility usage".to_string(),
|
||||
CheckKind::DatetimeTimezoneUTC => "Use `datetime.UTC` alias".to_string(),
|
||||
CheckKind::NativeLiterals => "Unnecessary call to `str` and `bytes`".to_string(),
|
||||
CheckKind::OpenAlias => "Use builtin `open`".to_string(),
|
||||
CheckKind::ConvertTypedDictFunctionalToClass(name) => {
|
||||
format!("Convert `{name}` from `TypedDict` functional to class syntax")
|
||||
}
|
||||
CheckKind::ReplaceUniversalNewlines => {
|
||||
"`universal_newlines` is deprecated, use `text`".to_string()
|
||||
}
|
||||
CheckKind::ReplaceStdoutStderr => {
|
||||
"Sending stdout and stderr to pipe is deprecated, use `capture_output`".to_string()
|
||||
}
|
||||
CheckKind::RewriteCElementTree => {
|
||||
"`cElementTree` is deprecated, use `ElementTree`".to_string()
|
||||
}
|
||||
CheckKind::RewriteUnicodeLiteral => "Remove unicode literals from strings".to_string(),
|
||||
CheckKind::ConvertNamedTupleFunctionalToClass(name) => {
|
||||
format!("Convert `{name}` from `NamedTuple` functional to class syntax")
|
||||
}
|
||||
@@ -2775,13 +2876,14 @@ impl CheckKind {
|
||||
"Boolean positional value in function call".to_string()
|
||||
}
|
||||
// pygrep-hooks
|
||||
CheckKind::NoEval => "No builtin `eval()` allowed".to_string(),
|
||||
CheckKind::DeprecatedLogWarn => {
|
||||
"`warn` is deprecated in favor of `warning`".to_string()
|
||||
}
|
||||
CheckKind::BlanketNOQA => "Use specific error codes when using `noqa`".to_string(),
|
||||
CheckKind::BlanketTypeIgnore => {
|
||||
"Use specific error codes when ignoring type issues".to_string()
|
||||
}
|
||||
CheckKind::DeprecatedLogWarn => {
|
||||
"`warn` is deprecated in favor of `warning`".to_string()
|
||||
}
|
||||
CheckKind::NoEval => "No builtin `eval()` allowed".to_string(),
|
||||
// flake8-unused-arguments
|
||||
CheckKind::UnusedFunctionArgument(name) => {
|
||||
format!("Unused function argument: `{name}`")
|
||||
@@ -2862,6 +2964,9 @@ impl CheckKind {
|
||||
'{representant}'?)"
|
||||
)
|
||||
}
|
||||
CheckKind::KeywordArgumentBeforeStarArgument(name) => {
|
||||
format!("Keyword argument `{name}` must come after starred arguments")
|
||||
}
|
||||
CheckKind::UnusedNOQA(codes) => match codes {
|
||||
None => "Unused blanket `noqa` directive".to_string(),
|
||||
Some(codes) => {
|
||||
@@ -3009,7 +3114,12 @@ impl CheckKind {
|
||||
| CheckKind::MisplacedComparisonConstant(..)
|
||||
| CheckKind::MissingReturnTypeSpecialMethod(..)
|
||||
| CheckKind::NativeLiterals
|
||||
| CheckKind::OpenAlias
|
||||
| CheckKind::NewLineAfterLastParagraph
|
||||
| CheckKind::ReplaceUniversalNewlines
|
||||
| CheckKind::ReplaceStdoutStderr
|
||||
| CheckKind::RewriteCElementTree
|
||||
| CheckKind::RewriteUnicodeLiteral
|
||||
| CheckKind::NewLineAfterSectionName(..)
|
||||
| CheckKind::NoBlankLineAfterFunction(..)
|
||||
| CheckKind::NoBlankLineBeforeClass(..)
|
||||
@@ -3042,6 +3152,7 @@ impl CheckKind {
|
||||
| CheckKind::SuperCallWithParameters
|
||||
| CheckKind::TrueFalseComparison(..)
|
||||
| CheckKind::TypeOfPrimitive(..)
|
||||
| CheckKind::TypingTextStrAlias
|
||||
| CheckKind::UnnecessaryCallAroundSorted(..)
|
||||
| CheckKind::UnnecessaryCollectionCall(..)
|
||||
| CheckKind::UnnecessaryComprehension(..)
|
||||
@@ -3116,6 +3227,7 @@ pub static PREFIX_REDIRECTS: Lazy<FxHashMap<&'static str, CheckCodePrefix>> = La
|
||||
("U015", CheckCodePrefix::UP015),
|
||||
("U016", CheckCodePrefix::UP016),
|
||||
("U017", CheckCodePrefix::UP017),
|
||||
("U019", CheckCodePrefix::UP019),
|
||||
// TODO(charlie): Remove by 2023-02-01.
|
||||
("I252", CheckCodePrefix::TID252),
|
||||
("M001", CheckCodePrefix::RUF100),
|
||||
@@ -3191,6 +3303,7 @@ pub static CODE_REDIRECTS: Lazy<FxHashMap<&'static str, CheckCode>> = Lazy::new(
|
||||
("U015", CheckCode::UP015),
|
||||
("U016", CheckCode::UP016),
|
||||
("U017", CheckCode::UP017),
|
||||
("U019", CheckCode::UP019),
|
||||
// TODO(charlie): Remove by 2023-02-01.
|
||||
("I252", CheckCode::TID252),
|
||||
("M001", CheckCode::RUF100),
|
||||
|
||||
@@ -28,6 +28,7 @@ pub enum CheckCodePrefix {
|
||||
A001,
|
||||
A002,
|
||||
A003,
|
||||
ALL,
|
||||
ANN,
|
||||
ANN0,
|
||||
ANN00,
|
||||
@@ -313,6 +314,12 @@ pub enum CheckCodePrefix {
|
||||
ICN0,
|
||||
ICN00,
|
||||
ICN001,
|
||||
ISC,
|
||||
ISC0,
|
||||
ISC00,
|
||||
ISC001,
|
||||
ISC002,
|
||||
ISC003,
|
||||
M,
|
||||
M0,
|
||||
M001,
|
||||
@@ -376,6 +383,7 @@ pub enum CheckCodePrefix {
|
||||
PGH001,
|
||||
PGH002,
|
||||
PGH003,
|
||||
PGH004,
|
||||
PLC,
|
||||
PLC0,
|
||||
PLC04,
|
||||
@@ -456,6 +464,7 @@ pub enum CheckCodePrefix {
|
||||
RUF001,
|
||||
RUF002,
|
||||
RUF003,
|
||||
RUF004,
|
||||
RUF1,
|
||||
RUF10,
|
||||
RUF100,
|
||||
@@ -483,6 +492,7 @@ pub enum CheckCodePrefix {
|
||||
TID,
|
||||
TID2,
|
||||
TID25,
|
||||
TID251,
|
||||
TID252,
|
||||
U,
|
||||
U0,
|
||||
@@ -504,6 +514,7 @@ pub enum CheckCodePrefix {
|
||||
U015,
|
||||
U016,
|
||||
U017,
|
||||
U019,
|
||||
UP,
|
||||
UP0,
|
||||
UP00,
|
||||
@@ -525,6 +536,13 @@ pub enum CheckCodePrefix {
|
||||
UP016,
|
||||
UP017,
|
||||
UP018,
|
||||
UP019,
|
||||
UP02,
|
||||
UP020,
|
||||
UP021,
|
||||
UP022,
|
||||
UP023,
|
||||
UP025,
|
||||
W,
|
||||
W2,
|
||||
W29,
|
||||
@@ -553,6 +571,7 @@ pub enum CheckCodePrefix {
|
||||
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum SuffixLength {
|
||||
None,
|
||||
Zero,
|
||||
One,
|
||||
Two,
|
||||
@@ -570,6 +589,305 @@ impl CheckCodePrefix {
|
||||
CheckCodePrefix::A001 => vec![CheckCode::A001],
|
||||
CheckCodePrefix::A002 => vec![CheckCode::A002],
|
||||
CheckCodePrefix::A003 => vec![CheckCode::A003],
|
||||
CheckCodePrefix::ALL => vec![
|
||||
CheckCode::E401,
|
||||
CheckCode::E402,
|
||||
CheckCode::E501,
|
||||
CheckCode::E711,
|
||||
CheckCode::E712,
|
||||
CheckCode::E713,
|
||||
CheckCode::E714,
|
||||
CheckCode::E721,
|
||||
CheckCode::E722,
|
||||
CheckCode::E731,
|
||||
CheckCode::E741,
|
||||
CheckCode::E742,
|
||||
CheckCode::E743,
|
||||
CheckCode::E902,
|
||||
CheckCode::E999,
|
||||
CheckCode::W292,
|
||||
CheckCode::W605,
|
||||
CheckCode::F401,
|
||||
CheckCode::F402,
|
||||
CheckCode::F403,
|
||||
CheckCode::F404,
|
||||
CheckCode::F405,
|
||||
CheckCode::F406,
|
||||
CheckCode::F407,
|
||||
CheckCode::F501,
|
||||
CheckCode::F502,
|
||||
CheckCode::F503,
|
||||
CheckCode::F504,
|
||||
CheckCode::F505,
|
||||
CheckCode::F506,
|
||||
CheckCode::F507,
|
||||
CheckCode::F508,
|
||||
CheckCode::F509,
|
||||
CheckCode::F521,
|
||||
CheckCode::F522,
|
||||
CheckCode::F523,
|
||||
CheckCode::F524,
|
||||
CheckCode::F525,
|
||||
CheckCode::F541,
|
||||
CheckCode::F601,
|
||||
CheckCode::F602,
|
||||
CheckCode::F621,
|
||||
CheckCode::F622,
|
||||
CheckCode::F631,
|
||||
CheckCode::F632,
|
||||
CheckCode::F633,
|
||||
CheckCode::F634,
|
||||
CheckCode::F701,
|
||||
CheckCode::F702,
|
||||
CheckCode::F704,
|
||||
CheckCode::F706,
|
||||
CheckCode::F707,
|
||||
CheckCode::F722,
|
||||
CheckCode::F811,
|
||||
CheckCode::F821,
|
||||
CheckCode::F822,
|
||||
CheckCode::F823,
|
||||
CheckCode::F831,
|
||||
CheckCode::F841,
|
||||
CheckCode::F842,
|
||||
CheckCode::F901,
|
||||
CheckCode::PLC0414,
|
||||
CheckCode::PLC2201,
|
||||
CheckCode::PLC3002,
|
||||
CheckCode::PLE0117,
|
||||
CheckCode::PLE0118,
|
||||
CheckCode::PLE1142,
|
||||
CheckCode::PLR0206,
|
||||
CheckCode::PLR0402,
|
||||
CheckCode::PLR1701,
|
||||
CheckCode::PLR1722,
|
||||
CheckCode::PLW0120,
|
||||
CheckCode::PLW0602,
|
||||
CheckCode::A001,
|
||||
CheckCode::A002,
|
||||
CheckCode::A003,
|
||||
CheckCode::B002,
|
||||
CheckCode::B003,
|
||||
CheckCode::B004,
|
||||
CheckCode::B005,
|
||||
CheckCode::B006,
|
||||
CheckCode::B007,
|
||||
CheckCode::B008,
|
||||
CheckCode::B009,
|
||||
CheckCode::B010,
|
||||
CheckCode::B011,
|
||||
CheckCode::B012,
|
||||
CheckCode::B013,
|
||||
CheckCode::B014,
|
||||
CheckCode::B015,
|
||||
CheckCode::B016,
|
||||
CheckCode::B017,
|
||||
CheckCode::B018,
|
||||
CheckCode::B019,
|
||||
CheckCode::B020,
|
||||
CheckCode::B021,
|
||||
CheckCode::B022,
|
||||
CheckCode::B023,
|
||||
CheckCode::B024,
|
||||
CheckCode::B025,
|
||||
CheckCode::B026,
|
||||
CheckCode::B027,
|
||||
CheckCode::B904,
|
||||
CheckCode::B905,
|
||||
CheckCode::BLE001,
|
||||
CheckCode::C400,
|
||||
CheckCode::C401,
|
||||
CheckCode::C402,
|
||||
CheckCode::C403,
|
||||
CheckCode::C404,
|
||||
CheckCode::C405,
|
||||
CheckCode::C406,
|
||||
CheckCode::C408,
|
||||
CheckCode::C409,
|
||||
CheckCode::C410,
|
||||
CheckCode::C411,
|
||||
CheckCode::C413,
|
||||
CheckCode::C414,
|
||||
CheckCode::C415,
|
||||
CheckCode::C416,
|
||||
CheckCode::C417,
|
||||
CheckCode::T100,
|
||||
CheckCode::C901,
|
||||
CheckCode::TID251,
|
||||
CheckCode::TID252,
|
||||
CheckCode::RET501,
|
||||
CheckCode::RET502,
|
||||
CheckCode::RET503,
|
||||
CheckCode::RET504,
|
||||
CheckCode::RET505,
|
||||
CheckCode::RET506,
|
||||
CheckCode::RET507,
|
||||
CheckCode::RET508,
|
||||
CheckCode::ISC001,
|
||||
CheckCode::ISC002,
|
||||
CheckCode::ISC003,
|
||||
CheckCode::T201,
|
||||
CheckCode::T203,
|
||||
CheckCode::Q000,
|
||||
CheckCode::Q001,
|
||||
CheckCode::Q002,
|
||||
CheckCode::Q003,
|
||||
CheckCode::ANN001,
|
||||
CheckCode::ANN002,
|
||||
CheckCode::ANN003,
|
||||
CheckCode::ANN101,
|
||||
CheckCode::ANN102,
|
||||
CheckCode::ANN201,
|
||||
CheckCode::ANN202,
|
||||
CheckCode::ANN204,
|
||||
CheckCode::ANN205,
|
||||
CheckCode::ANN206,
|
||||
CheckCode::ANN401,
|
||||
CheckCode::YTT101,
|
||||
CheckCode::YTT102,
|
||||
CheckCode::YTT103,
|
||||
CheckCode::YTT201,
|
||||
CheckCode::YTT202,
|
||||
CheckCode::YTT203,
|
||||
CheckCode::YTT204,
|
||||
CheckCode::YTT301,
|
||||
CheckCode::YTT302,
|
||||
CheckCode::YTT303,
|
||||
CheckCode::SIM118,
|
||||
CheckCode::UP001,
|
||||
CheckCode::UP003,
|
||||
CheckCode::UP004,
|
||||
CheckCode::UP005,
|
||||
CheckCode::UP006,
|
||||
CheckCode::UP007,
|
||||
CheckCode::UP008,
|
||||
CheckCode::UP009,
|
||||
CheckCode::UP010,
|
||||
CheckCode::UP011,
|
||||
CheckCode::UP012,
|
||||
CheckCode::UP013,
|
||||
CheckCode::UP014,
|
||||
CheckCode::UP015,
|
||||
CheckCode::UP016,
|
||||
CheckCode::UP017,
|
||||
CheckCode::UP018,
|
||||
CheckCode::UP019,
|
||||
CheckCode::UP020,
|
||||
CheckCode::UP021,
|
||||
CheckCode::UP022,
|
||||
CheckCode::UP023,
|
||||
CheckCode::UP025,
|
||||
CheckCode::D100,
|
||||
CheckCode::D101,
|
||||
CheckCode::D102,
|
||||
CheckCode::D103,
|
||||
CheckCode::D104,
|
||||
CheckCode::D105,
|
||||
CheckCode::D106,
|
||||
CheckCode::D107,
|
||||
CheckCode::D200,
|
||||
CheckCode::D201,
|
||||
CheckCode::D202,
|
||||
CheckCode::D203,
|
||||
CheckCode::D204,
|
||||
CheckCode::D205,
|
||||
CheckCode::D206,
|
||||
CheckCode::D207,
|
||||
CheckCode::D208,
|
||||
CheckCode::D209,
|
||||
CheckCode::D210,
|
||||
CheckCode::D211,
|
||||
CheckCode::D212,
|
||||
CheckCode::D213,
|
||||
CheckCode::D214,
|
||||
CheckCode::D215,
|
||||
CheckCode::D300,
|
||||
CheckCode::D301,
|
||||
CheckCode::D400,
|
||||
CheckCode::D402,
|
||||
CheckCode::D403,
|
||||
CheckCode::D404,
|
||||
CheckCode::D405,
|
||||
CheckCode::D406,
|
||||
CheckCode::D407,
|
||||
CheckCode::D408,
|
||||
CheckCode::D409,
|
||||
CheckCode::D410,
|
||||
CheckCode::D411,
|
||||
CheckCode::D412,
|
||||
CheckCode::D413,
|
||||
CheckCode::D414,
|
||||
CheckCode::D415,
|
||||
CheckCode::D416,
|
||||
CheckCode::D417,
|
||||
CheckCode::D418,
|
||||
CheckCode::D419,
|
||||
CheckCode::N801,
|
||||
CheckCode::N802,
|
||||
CheckCode::N803,
|
||||
CheckCode::N804,
|
||||
CheckCode::N805,
|
||||
CheckCode::N806,
|
||||
CheckCode::N807,
|
||||
CheckCode::N811,
|
||||
CheckCode::N812,
|
||||
CheckCode::N813,
|
||||
CheckCode::N814,
|
||||
CheckCode::N815,
|
||||
CheckCode::N816,
|
||||
CheckCode::N817,
|
||||
CheckCode::N818,
|
||||
CheckCode::I001,
|
||||
CheckCode::ERA001,
|
||||
CheckCode::S101,
|
||||
CheckCode::S102,
|
||||
CheckCode::S104,
|
||||
CheckCode::S105,
|
||||
CheckCode::S106,
|
||||
CheckCode::S107,
|
||||
CheckCode::FBT001,
|
||||
CheckCode::FBT002,
|
||||
CheckCode::FBT003,
|
||||
CheckCode::ARG001,
|
||||
CheckCode::ARG002,
|
||||
CheckCode::ARG003,
|
||||
CheckCode::ARG004,
|
||||
CheckCode::ARG005,
|
||||
CheckCode::ICN001,
|
||||
CheckCode::DTZ001,
|
||||
CheckCode::DTZ002,
|
||||
CheckCode::DTZ003,
|
||||
CheckCode::DTZ004,
|
||||
CheckCode::DTZ005,
|
||||
CheckCode::DTZ006,
|
||||
CheckCode::DTZ007,
|
||||
CheckCode::DTZ011,
|
||||
CheckCode::DTZ012,
|
||||
CheckCode::RUF001,
|
||||
CheckCode::RUF002,
|
||||
CheckCode::RUF003,
|
||||
CheckCode::RUF004,
|
||||
CheckCode::RUF100,
|
||||
CheckCode::PGH001,
|
||||
CheckCode::PGH002,
|
||||
CheckCode::PGH003,
|
||||
CheckCode::PGH004,
|
||||
CheckCode::PD002,
|
||||
CheckCode::PD003,
|
||||
CheckCode::PD004,
|
||||
CheckCode::PD007,
|
||||
CheckCode::PD008,
|
||||
CheckCode::PD009,
|
||||
CheckCode::PD010,
|
||||
CheckCode::PD011,
|
||||
CheckCode::PD012,
|
||||
CheckCode::PD013,
|
||||
CheckCode::PD015,
|
||||
CheckCode::PD901,
|
||||
CheckCode::EM101,
|
||||
CheckCode::EM102,
|
||||
CheckCode::EM103,
|
||||
],
|
||||
CheckCodePrefix::ANN => vec![
|
||||
CheckCode::ANN001,
|
||||
CheckCode::ANN002,
|
||||
@@ -1357,7 +1675,7 @@ impl CheckCodePrefix {
|
||||
":".bold(),
|
||||
"`I2` has been remapped to `TID2`".bold()
|
||||
);
|
||||
vec![CheckCode::TID252]
|
||||
vec![CheckCode::TID251, CheckCode::TID252]
|
||||
}
|
||||
CheckCodePrefix::I25 => {
|
||||
one_time_warning!(
|
||||
@@ -1366,7 +1684,7 @@ impl CheckCodePrefix {
|
||||
":".bold(),
|
||||
"`I25` has been remapped to `TID25`".bold()
|
||||
);
|
||||
vec![CheckCode::TID252]
|
||||
vec![CheckCode::TID251, CheckCode::TID252]
|
||||
}
|
||||
CheckCodePrefix::I252 => {
|
||||
one_time_warning!(
|
||||
@@ -1435,6 +1753,12 @@ impl CheckCodePrefix {
|
||||
CheckCodePrefix::ICN0 => vec![CheckCode::ICN001],
|
||||
CheckCodePrefix::ICN00 => vec![CheckCode::ICN001],
|
||||
CheckCodePrefix::ICN001 => vec![CheckCode::ICN001],
|
||||
CheckCodePrefix::ISC => vec![CheckCode::ISC001, CheckCode::ISC002, CheckCode::ISC003],
|
||||
CheckCodePrefix::ISC0 => vec![CheckCode::ISC001, CheckCode::ISC002, CheckCode::ISC003],
|
||||
CheckCodePrefix::ISC00 => vec![CheckCode::ISC001, CheckCode::ISC002, CheckCode::ISC003],
|
||||
CheckCodePrefix::ISC001 => vec![CheckCode::ISC001],
|
||||
CheckCodePrefix::ISC002 => vec![CheckCode::ISC002],
|
||||
CheckCodePrefix::ISC003 => vec![CheckCode::ISC003],
|
||||
CheckCodePrefix::M => {
|
||||
one_time_warning!(
|
||||
"{}{} {}",
|
||||
@@ -1770,12 +2094,28 @@ impl CheckCodePrefix {
|
||||
);
|
||||
vec![CheckCode::PD901]
|
||||
}
|
||||
CheckCodePrefix::PGH => vec![CheckCode::PGH001, CheckCode::PGH002, CheckCode::PGH003],
|
||||
CheckCodePrefix::PGH0 => vec![CheckCode::PGH001, CheckCode::PGH002, CheckCode::PGH003],
|
||||
CheckCodePrefix::PGH00 => vec![CheckCode::PGH001, CheckCode::PGH002, CheckCode::PGH003],
|
||||
CheckCodePrefix::PGH => vec![
|
||||
CheckCode::PGH001,
|
||||
CheckCode::PGH002,
|
||||
CheckCode::PGH003,
|
||||
CheckCode::PGH004,
|
||||
],
|
||||
CheckCodePrefix::PGH0 => vec![
|
||||
CheckCode::PGH001,
|
||||
CheckCode::PGH002,
|
||||
CheckCode::PGH003,
|
||||
CheckCode::PGH004,
|
||||
],
|
||||
CheckCodePrefix::PGH00 => vec![
|
||||
CheckCode::PGH001,
|
||||
CheckCode::PGH002,
|
||||
CheckCode::PGH003,
|
||||
CheckCode::PGH004,
|
||||
],
|
||||
CheckCodePrefix::PGH001 => vec![CheckCode::PGH001],
|
||||
CheckCodePrefix::PGH002 => vec![CheckCode::PGH002],
|
||||
CheckCodePrefix::PGH003 => vec![CheckCode::PGH003],
|
||||
CheckCodePrefix::PGH004 => vec![CheckCode::PGH004],
|
||||
CheckCodePrefix::PLC => {
|
||||
vec![CheckCode::PLC0414, CheckCode::PLC2201, CheckCode::PLC3002]
|
||||
}
|
||||
@@ -2020,13 +2360,25 @@ impl CheckCodePrefix {
|
||||
CheckCode::RUF001,
|
||||
CheckCode::RUF002,
|
||||
CheckCode::RUF003,
|
||||
CheckCode::RUF004,
|
||||
CheckCode::RUF100,
|
||||
],
|
||||
CheckCodePrefix::RUF0 => vec![CheckCode::RUF001, CheckCode::RUF002, CheckCode::RUF003],
|
||||
CheckCodePrefix::RUF00 => vec![CheckCode::RUF001, CheckCode::RUF002, CheckCode::RUF003],
|
||||
CheckCodePrefix::RUF0 => vec![
|
||||
CheckCode::RUF001,
|
||||
CheckCode::RUF002,
|
||||
CheckCode::RUF003,
|
||||
CheckCode::RUF004,
|
||||
],
|
||||
CheckCodePrefix::RUF00 => vec![
|
||||
CheckCode::RUF001,
|
||||
CheckCode::RUF002,
|
||||
CheckCode::RUF003,
|
||||
CheckCode::RUF004,
|
||||
],
|
||||
CheckCodePrefix::RUF001 => vec![CheckCode::RUF001],
|
||||
CheckCodePrefix::RUF002 => vec![CheckCode::RUF002],
|
||||
CheckCodePrefix::RUF003 => vec![CheckCode::RUF003],
|
||||
CheckCodePrefix::RUF004 => vec![CheckCode::RUF004],
|
||||
CheckCodePrefix::RUF1 => vec![CheckCode::RUF100],
|
||||
CheckCodePrefix::RUF10 => vec![CheckCode::RUF100],
|
||||
CheckCodePrefix::RUF100 => vec![CheckCode::RUF100],
|
||||
@@ -2072,9 +2424,10 @@ impl CheckCodePrefix {
|
||||
CheckCodePrefix::T20 => vec![CheckCode::T201, CheckCode::T203],
|
||||
CheckCodePrefix::T201 => vec![CheckCode::T201],
|
||||
CheckCodePrefix::T203 => vec![CheckCode::T203],
|
||||
CheckCodePrefix::TID => vec![CheckCode::TID252],
|
||||
CheckCodePrefix::TID2 => vec![CheckCode::TID252],
|
||||
CheckCodePrefix::TID25 => vec![CheckCode::TID252],
|
||||
CheckCodePrefix::TID => vec![CheckCode::TID251, CheckCode::TID252],
|
||||
CheckCodePrefix::TID2 => vec![CheckCode::TID251, CheckCode::TID252],
|
||||
CheckCodePrefix::TID25 => vec![CheckCode::TID251, CheckCode::TID252],
|
||||
CheckCodePrefix::TID251 => vec![CheckCode::TID251],
|
||||
CheckCodePrefix::TID252 => vec![CheckCode::TID252],
|
||||
CheckCodePrefix::U => {
|
||||
one_time_warning!(
|
||||
@@ -2101,6 +2454,12 @@ impl CheckCodePrefix {
|
||||
CheckCode::UP016,
|
||||
CheckCode::UP017,
|
||||
CheckCode::UP018,
|
||||
CheckCode::UP019,
|
||||
CheckCode::UP020,
|
||||
CheckCode::UP021,
|
||||
CheckCode::UP022,
|
||||
CheckCode::UP023,
|
||||
CheckCode::UP025,
|
||||
]
|
||||
}
|
||||
CheckCodePrefix::U0 => {
|
||||
@@ -2128,6 +2487,12 @@ impl CheckCodePrefix {
|
||||
CheckCode::UP016,
|
||||
CheckCode::UP017,
|
||||
CheckCode::UP018,
|
||||
CheckCode::UP019,
|
||||
CheckCode::UP020,
|
||||
CheckCode::UP021,
|
||||
CheckCode::UP022,
|
||||
CheckCode::UP023,
|
||||
CheckCode::UP025,
|
||||
]
|
||||
}
|
||||
CheckCodePrefix::U00 => {
|
||||
@@ -2237,6 +2602,7 @@ impl CheckCodePrefix {
|
||||
CheckCode::UP016,
|
||||
CheckCode::UP017,
|
||||
CheckCode::UP018,
|
||||
CheckCode::UP019,
|
||||
]
|
||||
}
|
||||
CheckCodePrefix::U010 => {
|
||||
@@ -2311,6 +2677,15 @@ impl CheckCodePrefix {
|
||||
);
|
||||
vec![CheckCode::UP017]
|
||||
}
|
||||
CheckCodePrefix::U019 => {
|
||||
one_time_warning!(
|
||||
"{}{} {}",
|
||||
"warning".yellow().bold(),
|
||||
":".bold(),
|
||||
"`U019` has been remapped to `UP019`".bold()
|
||||
);
|
||||
vec![CheckCode::UP019]
|
||||
}
|
||||
CheckCodePrefix::UP => vec![
|
||||
CheckCode::UP001,
|
||||
CheckCode::UP003,
|
||||
@@ -2329,6 +2704,12 @@ impl CheckCodePrefix {
|
||||
CheckCode::UP016,
|
||||
CheckCode::UP017,
|
||||
CheckCode::UP018,
|
||||
CheckCode::UP019,
|
||||
CheckCode::UP020,
|
||||
CheckCode::UP021,
|
||||
CheckCode::UP022,
|
||||
CheckCode::UP023,
|
||||
CheckCode::UP025,
|
||||
],
|
||||
CheckCodePrefix::UP0 => vec![
|
||||
CheckCode::UP001,
|
||||
@@ -2348,6 +2729,12 @@ impl CheckCodePrefix {
|
||||
CheckCode::UP016,
|
||||
CheckCode::UP017,
|
||||
CheckCode::UP018,
|
||||
CheckCode::UP019,
|
||||
CheckCode::UP020,
|
||||
CheckCode::UP021,
|
||||
CheckCode::UP022,
|
||||
CheckCode::UP023,
|
||||
CheckCode::UP025,
|
||||
],
|
||||
CheckCodePrefix::UP00 => vec![
|
||||
CheckCode::UP001,
|
||||
@@ -2377,6 +2764,7 @@ impl CheckCodePrefix {
|
||||
CheckCode::UP016,
|
||||
CheckCode::UP017,
|
||||
CheckCode::UP018,
|
||||
CheckCode::UP019,
|
||||
],
|
||||
CheckCodePrefix::UP010 => vec![CheckCode::UP010],
|
||||
CheckCodePrefix::UP011 => vec![CheckCode::UP011],
|
||||
@@ -2387,6 +2775,19 @@ impl CheckCodePrefix {
|
||||
CheckCodePrefix::UP016 => vec![CheckCode::UP016],
|
||||
CheckCodePrefix::UP017 => vec![CheckCode::UP017],
|
||||
CheckCodePrefix::UP018 => vec![CheckCode::UP018],
|
||||
CheckCodePrefix::UP019 => vec![CheckCode::UP019],
|
||||
CheckCodePrefix::UP02 => vec![
|
||||
CheckCode::UP020,
|
||||
CheckCode::UP021,
|
||||
CheckCode::UP022,
|
||||
CheckCode::UP023,
|
||||
CheckCode::UP025,
|
||||
],
|
||||
CheckCodePrefix::UP020 => vec![CheckCode::UP020],
|
||||
CheckCodePrefix::UP021 => vec![CheckCode::UP021],
|
||||
CheckCodePrefix::UP022 => vec![CheckCode::UP022],
|
||||
CheckCodePrefix::UP023 => vec![CheckCode::UP023],
|
||||
CheckCodePrefix::UP025 => vec![CheckCode::UP025],
|
||||
CheckCodePrefix::W => vec![CheckCode::W292, CheckCode::W605],
|
||||
CheckCodePrefix::W2 => vec![CheckCode::W292],
|
||||
CheckCodePrefix::W29 => vec![CheckCode::W292],
|
||||
@@ -2446,6 +2847,7 @@ impl CheckCodePrefix {
|
||||
CheckCodePrefix::A001 => SuffixLength::Three,
|
||||
CheckCodePrefix::A002 => SuffixLength::Three,
|
||||
CheckCodePrefix::A003 => SuffixLength::Three,
|
||||
CheckCodePrefix::ALL => SuffixLength::None,
|
||||
CheckCodePrefix::ANN => SuffixLength::Zero,
|
||||
CheckCodePrefix::ANN0 => SuffixLength::One,
|
||||
CheckCodePrefix::ANN00 => SuffixLength::Two,
|
||||
@@ -2731,6 +3133,12 @@ impl CheckCodePrefix {
|
||||
CheckCodePrefix::ICN0 => SuffixLength::One,
|
||||
CheckCodePrefix::ICN00 => SuffixLength::Two,
|
||||
CheckCodePrefix::ICN001 => SuffixLength::Three,
|
||||
CheckCodePrefix::ISC => SuffixLength::Zero,
|
||||
CheckCodePrefix::ISC0 => SuffixLength::One,
|
||||
CheckCodePrefix::ISC00 => SuffixLength::Two,
|
||||
CheckCodePrefix::ISC001 => SuffixLength::Three,
|
||||
CheckCodePrefix::ISC002 => SuffixLength::Three,
|
||||
CheckCodePrefix::ISC003 => SuffixLength::Three,
|
||||
CheckCodePrefix::M => SuffixLength::Zero,
|
||||
CheckCodePrefix::M0 => SuffixLength::One,
|
||||
CheckCodePrefix::M001 => SuffixLength::Three,
|
||||
@@ -2794,6 +3202,7 @@ impl CheckCodePrefix {
|
||||
CheckCodePrefix::PGH001 => SuffixLength::Three,
|
||||
CheckCodePrefix::PGH002 => SuffixLength::Three,
|
||||
CheckCodePrefix::PGH003 => SuffixLength::Three,
|
||||
CheckCodePrefix::PGH004 => SuffixLength::Three,
|
||||
CheckCodePrefix::PLC => SuffixLength::Zero,
|
||||
CheckCodePrefix::PLC0 => SuffixLength::One,
|
||||
CheckCodePrefix::PLC04 => SuffixLength::Two,
|
||||
@@ -2874,6 +3283,7 @@ impl CheckCodePrefix {
|
||||
CheckCodePrefix::RUF001 => SuffixLength::Three,
|
||||
CheckCodePrefix::RUF002 => SuffixLength::Three,
|
||||
CheckCodePrefix::RUF003 => SuffixLength::Three,
|
||||
CheckCodePrefix::RUF004 => SuffixLength::Three,
|
||||
CheckCodePrefix::RUF1 => SuffixLength::One,
|
||||
CheckCodePrefix::RUF10 => SuffixLength::Two,
|
||||
CheckCodePrefix::RUF100 => SuffixLength::Three,
|
||||
@@ -2901,6 +3311,7 @@ impl CheckCodePrefix {
|
||||
CheckCodePrefix::TID => SuffixLength::Zero,
|
||||
CheckCodePrefix::TID2 => SuffixLength::One,
|
||||
CheckCodePrefix::TID25 => SuffixLength::Two,
|
||||
CheckCodePrefix::TID251 => SuffixLength::Three,
|
||||
CheckCodePrefix::TID252 => SuffixLength::Three,
|
||||
CheckCodePrefix::U => SuffixLength::Zero,
|
||||
CheckCodePrefix::U0 => SuffixLength::One,
|
||||
@@ -2922,6 +3333,7 @@ impl CheckCodePrefix {
|
||||
CheckCodePrefix::U015 => SuffixLength::Three,
|
||||
CheckCodePrefix::U016 => SuffixLength::Three,
|
||||
CheckCodePrefix::U017 => SuffixLength::Three,
|
||||
CheckCodePrefix::U019 => SuffixLength::Three,
|
||||
CheckCodePrefix::UP => SuffixLength::Zero,
|
||||
CheckCodePrefix::UP0 => SuffixLength::One,
|
||||
CheckCodePrefix::UP00 => SuffixLength::Two,
|
||||
@@ -2943,6 +3355,13 @@ impl CheckCodePrefix {
|
||||
CheckCodePrefix::UP016 => SuffixLength::Three,
|
||||
CheckCodePrefix::UP017 => SuffixLength::Three,
|
||||
CheckCodePrefix::UP018 => SuffixLength::Three,
|
||||
CheckCodePrefix::UP019 => SuffixLength::Three,
|
||||
CheckCodePrefix::UP02 => SuffixLength::Two,
|
||||
CheckCodePrefix::UP020 => SuffixLength::Three,
|
||||
CheckCodePrefix::UP021 => SuffixLength::Three,
|
||||
CheckCodePrefix::UP022 => SuffixLength::Three,
|
||||
CheckCodePrefix::UP023 => SuffixLength::Three,
|
||||
CheckCodePrefix::UP025 => SuffixLength::Three,
|
||||
CheckCodePrefix::W => SuffixLength::Zero,
|
||||
CheckCodePrefix::W2 => SuffixLength::One,
|
||||
CheckCodePrefix::W29 => SuffixLength::Two,
|
||||
@@ -2973,6 +3392,7 @@ impl CheckCodePrefix {
|
||||
|
||||
pub const CATEGORIES: &[CheckCodePrefix] = &[
|
||||
CheckCodePrefix::A,
|
||||
CheckCodePrefix::ALL,
|
||||
CheckCodePrefix::ANN,
|
||||
CheckCodePrefix::ARG,
|
||||
CheckCodePrefix::B,
|
||||
@@ -2987,6 +3407,7 @@ pub const CATEGORIES: &[CheckCodePrefix] = &[
|
||||
CheckCodePrefix::FBT,
|
||||
CheckCodePrefix::I,
|
||||
CheckCodePrefix::ICN,
|
||||
CheckCodePrefix::ISC,
|
||||
CheckCodePrefix::N,
|
||||
CheckCodePrefix::PD,
|
||||
CheckCodePrefix::PGH,
|
||||
|
||||
47
src/cli.rs
47
src/cli.rs
@@ -19,7 +19,8 @@ use crate::settings::types::{
|
||||
pub struct Cli {
|
||||
#[arg(required_unless_present_any = ["explain", "generate_shell_completion"])]
|
||||
pub files: Vec<PathBuf>,
|
||||
/// Path to the `pyproject.toml` file to use for configuration.
|
||||
/// Path to the `pyproject.toml` or `ruff.toml` file to use for
|
||||
/// configuration.
|
||||
#[arg(long)]
|
||||
pub config: Option<PathBuf>,
|
||||
/// Enable verbose logging.
|
||||
@@ -43,17 +44,28 @@ pub struct Cli {
|
||||
fix: bool,
|
||||
#[clap(long, overrides_with("fix"), hide = true)]
|
||||
no_fix: bool,
|
||||
/// Fix any fixable lint errors, but don't report on leftover violations.
|
||||
/// Implies `--fix`.
|
||||
#[arg(long, overrides_with("no_fix_only"))]
|
||||
fix_only: bool,
|
||||
#[clap(long, overrides_with("fix_only"), hide = true)]
|
||||
no_fix_only: bool,
|
||||
/// Avoid writing any fixed files back; instead, output a diff for each
|
||||
/// changed file to stdout.
|
||||
#[arg(long)]
|
||||
pub diff: bool,
|
||||
/// Disable cache reads.
|
||||
#[arg(short, long)]
|
||||
pub no_cache: bool,
|
||||
/// List of error codes to enable.
|
||||
/// Comma-separated list of error codes to enable (or ALL, to enable all
|
||||
/// checks).
|
||||
#[arg(long, value_delimiter = ',')]
|
||||
pub select: Option<Vec<CheckCodePrefix>>,
|
||||
/// Like --select, but adds additional error codes on top of the selected
|
||||
/// ones.
|
||||
#[arg(long, value_delimiter = ',')]
|
||||
pub extend_select: Option<Vec<CheckCodePrefix>>,
|
||||
/// List of error codes to ignore.
|
||||
/// Comma-separated list of error codes to disable.
|
||||
#[arg(long, value_delimiter = ',')]
|
||||
pub ignore: Option<Vec<CheckCodePrefix>>,
|
||||
/// Like --ignore, but adds additional error codes on top of the ignored
|
||||
@@ -94,17 +106,22 @@ pub struct Cli {
|
||||
no_respect_gitignore: bool,
|
||||
/// Enforce exclusions, even for paths passed to Ruff directly on the
|
||||
/// command-line.
|
||||
#[arg(long, overrides_with("no_show_source"))]
|
||||
#[arg(long, overrides_with("no_force_exclude"))]
|
||||
force_exclude: bool,
|
||||
#[clap(long, overrides_with("force_exclude"), hide = true)]
|
||||
no_force_exclude: bool,
|
||||
/// Enable or disable automatic update checks.
|
||||
#[arg(long, overrides_with("no_update_check"))]
|
||||
update_check: bool,
|
||||
#[clap(long, overrides_with("update_check"), hide = true)]
|
||||
no_update_check: bool,
|
||||
/// See the files Ruff will be run against with the current settings.
|
||||
#[arg(long)]
|
||||
pub show_files: bool,
|
||||
/// See the settings Ruff will use to check a given Python file.
|
||||
#[arg(long)]
|
||||
pub show_settings: bool,
|
||||
/// Enable automatic additions of noqa directives to failing lines.
|
||||
/// Enable automatic additions of `noqa` directives to failing lines.
|
||||
#[arg(long)]
|
||||
pub add_noqa: bool,
|
||||
/// Regular expression matching the name of dummy variables.
|
||||
@@ -117,7 +134,7 @@ pub struct Cli {
|
||||
/// formatting.
|
||||
#[arg(long)]
|
||||
pub line_length: Option<usize>,
|
||||
/// Max McCabe complexity allowed for a function.
|
||||
/// Maximum McCabe complexity allowed for a given function.
|
||||
#[arg(long)]
|
||||
pub max_complexity: Option<usize>,
|
||||
/// Round-trip auto-formatting.
|
||||
@@ -147,6 +164,7 @@ impl Cli {
|
||||
add_noqa: self.add_noqa,
|
||||
autoformat: self.autoformat,
|
||||
config: self.config,
|
||||
diff: self.diff,
|
||||
exit_zero: self.exit_zero,
|
||||
explain: self.explain,
|
||||
files: self.files,
|
||||
@@ -180,10 +198,12 @@ impl Cli {
|
||||
target_version: self.target_version,
|
||||
unfixable: self.unfixable,
|
||||
// TODO(charlie): Included in `pyproject.toml`, but not inherited.
|
||||
fix: resolve_bool_arg(self.fix, self.no_fix),
|
||||
format: self.format,
|
||||
force_exclude: resolve_bool_arg(self.force_exclude, self.no_force_exclude),
|
||||
cache_dir: self.cache_dir,
|
||||
fix: resolve_bool_arg(self.fix, self.no_fix),
|
||||
fix_only: resolve_bool_arg(self.fix_only, self.no_fix_only),
|
||||
force_exclude: resolve_bool_arg(self.force_exclude, self.no_force_exclude),
|
||||
format: self.format,
|
||||
update_check: resolve_bool_arg(self.update_check, self.no_update_check),
|
||||
},
|
||||
)
|
||||
}
|
||||
@@ -205,6 +225,7 @@ pub struct Arguments {
|
||||
pub add_noqa: bool,
|
||||
pub autoformat: bool,
|
||||
pub config: Option<PathBuf>,
|
||||
pub diff: bool,
|
||||
pub exit_zero: bool,
|
||||
pub explain: Option<CheckCode>,
|
||||
pub files: Vec<PathBuf>,
|
||||
@@ -239,10 +260,12 @@ pub struct Overrides {
|
||||
pub target_version: Option<PythonVersion>,
|
||||
pub unfixable: Option<Vec<CheckCodePrefix>>,
|
||||
// TODO(charlie): Captured in pyproject.toml as a default, but not part of `Settings`.
|
||||
pub fix: Option<bool>,
|
||||
pub format: Option<SerializationFormat>,
|
||||
pub force_exclude: Option<bool>,
|
||||
pub cache_dir: Option<PathBuf>,
|
||||
pub fix: Option<bool>,
|
||||
pub fix_only: Option<bool>,
|
||||
pub force_exclude: Option<bool>,
|
||||
pub format: Option<SerializationFormat>,
|
||||
pub update_check: Option<bool>,
|
||||
}
|
||||
|
||||
/// Map the CLI settings to a `LogLevel`.
|
||||
|
||||
@@ -38,14 +38,8 @@ pub fn run(
|
||||
let duration = start.elapsed();
|
||||
debug!("Identified files to lint in: {:?}", duration);
|
||||
|
||||
// Discover the package root for each Python file.
|
||||
let package_roots = packages::detect_package_roots(
|
||||
&paths
|
||||
.iter()
|
||||
.flatten()
|
||||
.map(ignore::DirEntry::path)
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
// Validate the `Settings` and return any errors.
|
||||
resolver.validate(pyproject_strategy)?;
|
||||
|
||||
// Initialize the cache.
|
||||
if matches!(cache, flags::Cache::Enabled) {
|
||||
@@ -71,6 +65,15 @@ pub fn run(
|
||||
}
|
||||
};
|
||||
|
||||
// Discover the package root for each Python file.
|
||||
let package_roots = packages::detect_package_roots(
|
||||
&paths
|
||||
.iter()
|
||||
.flatten()
|
||||
.map(ignore::DirEntry::path)
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
|
||||
let start = Instant::now();
|
||||
let mut diagnostics: Diagnostics = par_iter(&paths)
|
||||
.map(|entry| {
|
||||
@@ -176,6 +179,9 @@ pub fn add_noqa(
|
||||
let duration = start.elapsed();
|
||||
debug!("Identified files to lint in: {:?}", duration);
|
||||
|
||||
// Validate the `Settings` and return any errors.
|
||||
resolver.validate(pyproject_strategy)?;
|
||||
|
||||
let start = Instant::now();
|
||||
let modifications: usize = par_iter(&paths)
|
||||
.flatten()
|
||||
@@ -212,6 +218,9 @@ pub fn autoformat(
|
||||
let duration = start.elapsed();
|
||||
debug!("Identified files to lint in: {:?}", duration);
|
||||
|
||||
// Validate the `Settings` and return any errors.
|
||||
resolver.validate(pyproject_strategy)?;
|
||||
|
||||
let start = Instant::now();
|
||||
let modifications = par_iter(&paths)
|
||||
.flatten()
|
||||
@@ -245,6 +254,9 @@ pub fn show_settings(
|
||||
let (paths, resolver) =
|
||||
resolver::python_files_in_path(files, pyproject_strategy, file_strategy, overrides)?;
|
||||
|
||||
// Validate the `Settings` and return any errors.
|
||||
resolver.validate(pyproject_strategy)?;
|
||||
|
||||
// Print the list of files.
|
||||
let Some(entry) = paths
|
||||
.iter()
|
||||
@@ -268,9 +280,12 @@ pub fn show_files(
|
||||
overrides: &Overrides,
|
||||
) -> Result<()> {
|
||||
// Collect all files in the hierarchy.
|
||||
let (paths, _resolver) =
|
||||
let (paths, resolver) =
|
||||
resolver::python_files_in_path(files, pyproject_strategy, file_strategy, overrides)?;
|
||||
|
||||
// Validate the `Settings` and return any errors.
|
||||
resolver.validate(pyproject_strategy)?;
|
||||
|
||||
// Print the list of files.
|
||||
for entry in paths
|
||||
.iter()
|
||||
@@ -317,6 +332,9 @@ pub fn explain(code: &CheckCode, format: &SerializationFormat) -> Result<()> {
|
||||
SerializationFormat::Github => {
|
||||
bail!("`--explain` does not support GitHub format")
|
||||
}
|
||||
SerializationFormat::Gitlab => {
|
||||
bail!("`--explain` does not support GitLab format")
|
||||
}
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ use rustpython_ast::Stmt;
|
||||
use rustpython_parser::lexer;
|
||||
use rustpython_parser::lexer::Tok;
|
||||
|
||||
use crate::ast::helpers;
|
||||
use crate::ast::types::Range;
|
||||
use crate::autofix::Fix;
|
||||
use crate::source_code_locator::SourceCodeLocator;
|
||||
@@ -17,13 +16,10 @@ pub fn add_return_none_annotation(locator: &SourceCodeLocator, stmt: &Stmt) -> R
|
||||
let mut seen_lpar = false;
|
||||
let mut seen_rpar = false;
|
||||
let mut count: usize = 0;
|
||||
for (start, tok, ..) in lexer::make_tokenizer(&contents).flatten() {
|
||||
for (start, tok, ..) in lexer::make_tokenizer_located(&contents, range.location).flatten() {
|
||||
if seen_lpar && seen_rpar {
|
||||
if matches!(tok, Tok::Colon) {
|
||||
return Ok(Fix::insertion(
|
||||
" -> None".to_string(),
|
||||
helpers::to_absolute(start, range.location),
|
||||
));
|
||||
return Ok(Fix::insertion(" -> None".to_string(), start));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ use rustpython_ast::{Constant, Expr, ExprKind, Stmt, StmtKind};
|
||||
|
||||
use crate::ast::types::Range;
|
||||
use crate::ast::visitor::Visitor;
|
||||
use crate::ast::{cast, visitor};
|
||||
use crate::ast::{cast, helpers, visitor};
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::checks::{CheckCode, CheckKind};
|
||||
use crate::docstrings::definition::{Definition, DefinitionKind};
|
||||
@@ -167,7 +167,7 @@ pub fn definition(checker: &mut Checker, definition: &Definition, visibility: &V
|
||||
if checker.settings.enabled.contains(&CheckCode::ANN201) {
|
||||
checker.add_check(Check::new(
|
||||
CheckKind::MissingReturnTypePublicFunction(name.to_string()),
|
||||
Range::from_located(stmt),
|
||||
helpers::identifier_range(stmt, checker.locator),
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -175,7 +175,7 @@ pub fn definition(checker: &mut Checker, definition: &Definition, visibility: &V
|
||||
if checker.settings.enabled.contains(&CheckCode::ANN202) {
|
||||
checker.add_check(Check::new(
|
||||
CheckKind::MissingReturnTypePrivateFunction(name.to_string()),
|
||||
Range::from_located(stmt),
|
||||
helpers::identifier_range(stmt, checker.locator),
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -309,14 +309,14 @@ pub fn definition(checker: &mut Checker, definition: &Definition, visibility: &V
|
||||
if checker.settings.enabled.contains(&CheckCode::ANN206) {
|
||||
checker.add_check(Check::new(
|
||||
CheckKind::MissingReturnTypeClassMethod(name.to_string()),
|
||||
Range::from_located(stmt),
|
||||
helpers::identifier_range(stmt, checker.locator),
|
||||
));
|
||||
}
|
||||
} else if visibility::is_staticmethod(checker, cast::decorator_list(stmt)) {
|
||||
if checker.settings.enabled.contains(&CheckCode::ANN205) {
|
||||
checker.add_check(Check::new(
|
||||
CheckKind::MissingReturnTypeStaticMethod(name.to_string()),
|
||||
Range::from_located(stmt),
|
||||
helpers::identifier_range(stmt, checker.locator),
|
||||
));
|
||||
}
|
||||
} else if visibility::is_init(stmt) {
|
||||
@@ -328,7 +328,7 @@ pub fn definition(checker: &mut Checker, definition: &Definition, visibility: &V
|
||||
{
|
||||
let mut check = Check::new(
|
||||
CheckKind::MissingReturnTypeSpecialMethod(name.to_string()),
|
||||
Range::from_located(stmt),
|
||||
helpers::identifier_range(stmt, checker.locator),
|
||||
);
|
||||
if checker.patch(check.kind.code()) {
|
||||
match fixes::add_return_none_annotation(checker.locator, stmt) {
|
||||
@@ -343,7 +343,7 @@ pub fn definition(checker: &mut Checker, definition: &Definition, visibility: &V
|
||||
if checker.settings.enabled.contains(&CheckCode::ANN204) {
|
||||
checker.add_check(Check::new(
|
||||
CheckKind::MissingReturnTypeSpecialMethod(name.to_string()),
|
||||
Range::from_located(stmt),
|
||||
helpers::identifier_range(stmt, checker.locator),
|
||||
));
|
||||
}
|
||||
} else {
|
||||
@@ -352,7 +352,7 @@ pub fn definition(checker: &mut Checker, definition: &Definition, visibility: &V
|
||||
if checker.settings.enabled.contains(&CheckCode::ANN201) {
|
||||
checker.add_check(Check::new(
|
||||
CheckKind::MissingReturnTypePublicFunction(name.to_string()),
|
||||
Range::from_located(stmt),
|
||||
helpers::identifier_range(stmt, checker.locator),
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -360,7 +360,7 @@ pub fn definition(checker: &mut Checker, definition: &Definition, visibility: &V
|
||||
if checker.settings.enabled.contains(&CheckCode::ANN202) {
|
||||
checker.add_check(Check::new(
|
||||
CheckKind::MissingReturnTypePrivateFunction(name.to_string()),
|
||||
Range::from_located(stmt),
|
||||
helpers::identifier_range(stmt, checker.locator),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(
|
||||
Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions, JsonSchema,
|
||||
Debug, PartialEq, Eq, Default, Serialize, Deserialize, ConfigurationOptions, JsonSchema,
|
||||
)]
|
||||
#[serde(
|
||||
deny_unknown_fields,
|
||||
@@ -51,7 +51,7 @@ pub struct Options {
|
||||
pub allow_star_arg_any: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Hash, Default)]
|
||||
#[derive(Debug, Default, Hash)]
|
||||
#[allow(clippy::struct_excessive_bools)]
|
||||
pub struct Settings {
|
||||
pub mypy_init_return: bool,
|
||||
@@ -60,14 +60,24 @@ pub struct Settings {
|
||||
pub allow_star_arg_any: bool,
|
||||
}
|
||||
|
||||
impl Settings {
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
pub fn from_options(options: Options) -> Self {
|
||||
impl From<Options> for Settings {
|
||||
fn from(options: Options) -> Self {
|
||||
Self {
|
||||
mypy_init_return: options.mypy_init_return.unwrap_or_default(),
|
||||
suppress_dummy_args: options.suppress_dummy_args.unwrap_or_default(),
|
||||
suppress_none_returning: options.suppress_none_returning.unwrap_or_default(),
|
||||
allow_star_arg_any: options.allow_star_arg_any.unwrap_or_default(),
|
||||
mypy_init_return: options.mypy_init_return.unwrap_or(false),
|
||||
suppress_dummy_args: options.suppress_dummy_args.unwrap_or(false),
|
||||
suppress_none_returning: options.suppress_none_returning.unwrap_or(false),
|
||||
allow_star_arg_any: options.allow_star_arg_any.unwrap_or(false),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Settings> for Options {
|
||||
fn from(settings: Settings) -> Self {
|
||||
Self {
|
||||
mypy_init_return: Some(settings.mypy_init_return),
|
||||
suppress_dummy_args: Some(settings.suppress_dummy_args),
|
||||
suppress_none_returning: Some(settings.suppress_none_returning),
|
||||
allow_star_arg_any: Some(settings.allow_star_arg_any),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,9 +6,9 @@ expression: checks
|
||||
MissingReturnTypePublicFunction: bar
|
||||
location:
|
||||
row: 29
|
||||
column: 4
|
||||
column: 8
|
||||
end_location:
|
||||
row: 30
|
||||
column: 16
|
||||
row: 29
|
||||
column: 11
|
||||
fix: ~
|
||||
|
||||
|
||||
@@ -6,10 +6,10 @@ expression: checks
|
||||
MissingReturnTypePublicFunction: foo
|
||||
location:
|
||||
row: 4
|
||||
column: 0
|
||||
column: 4
|
||||
end_location:
|
||||
row: 5
|
||||
column: 8
|
||||
row: 4
|
||||
column: 7
|
||||
fix: ~
|
||||
- kind:
|
||||
MissingTypeFunctionArgument: a
|
||||
@@ -33,10 +33,10 @@ expression: checks
|
||||
MissingReturnTypePublicFunction: foo
|
||||
location:
|
||||
row: 9
|
||||
column: 0
|
||||
column: 4
|
||||
end_location:
|
||||
row: 10
|
||||
column: 8
|
||||
row: 9
|
||||
column: 7
|
||||
fix: ~
|
||||
- kind:
|
||||
MissingTypeFunctionArgument: b
|
||||
@@ -60,19 +60,19 @@ expression: checks
|
||||
MissingReturnTypePublicFunction: foo
|
||||
location:
|
||||
row: 19
|
||||
column: 0
|
||||
column: 4
|
||||
end_location:
|
||||
row: 20
|
||||
column: 8
|
||||
row: 19
|
||||
column: 7
|
||||
fix: ~
|
||||
- kind:
|
||||
MissingReturnTypePublicFunction: foo
|
||||
location:
|
||||
row: 24
|
||||
column: 0
|
||||
column: 4
|
||||
end_location:
|
||||
row: 25
|
||||
column: 8
|
||||
row: 24
|
||||
column: 7
|
||||
fix: ~
|
||||
- kind:
|
||||
DynamicallyTypedExpression: a
|
||||
|
||||
@@ -6,10 +6,10 @@ expression: checks
|
||||
MissingReturnTypeSpecialMethod: __init__
|
||||
location:
|
||||
row: 5
|
||||
column: 4
|
||||
column: 8
|
||||
end_location:
|
||||
row: 6
|
||||
column: 11
|
||||
row: 5
|
||||
column: 16
|
||||
fix:
|
||||
content: " -> None"
|
||||
location:
|
||||
@@ -22,10 +22,10 @@ expression: checks
|
||||
MissingReturnTypeSpecialMethod: __init__
|
||||
location:
|
||||
row: 11
|
||||
column: 4
|
||||
column: 8
|
||||
end_location:
|
||||
row: 12
|
||||
column: 11
|
||||
row: 11
|
||||
column: 16
|
||||
fix:
|
||||
content: " -> None"
|
||||
location:
|
||||
@@ -38,9 +38,9 @@ expression: checks
|
||||
MissingReturnTypePrivateFunction: __init__
|
||||
location:
|
||||
row: 40
|
||||
column: 0
|
||||
column: 4
|
||||
end_location:
|
||||
row: 41
|
||||
column: 7
|
||||
row: 40
|
||||
column: 12
|
||||
fix: ~
|
||||
|
||||
|
||||
@@ -6,18 +6,18 @@ expression: checks
|
||||
MissingReturnTypePublicFunction: foo
|
||||
location:
|
||||
row: 45
|
||||
column: 0
|
||||
column: 4
|
||||
end_location:
|
||||
row: 46
|
||||
column: 15
|
||||
row: 45
|
||||
column: 7
|
||||
fix: ~
|
||||
- kind:
|
||||
MissingReturnTypePublicFunction: foo
|
||||
location:
|
||||
row: 50
|
||||
column: 0
|
||||
column: 4
|
||||
end_location:
|
||||
row: 55
|
||||
column: 14
|
||||
row: 50
|
||||
column: 7
|
||||
fix: ~
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ use crate::ast::types::Range;
|
||||
use crate::autofix::Fix;
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::checks::{Check, CheckKind};
|
||||
use crate::code_gen::SourceGenerator;
|
||||
use crate::source_code_generator::SourceCodeGenerator;
|
||||
|
||||
fn assertion_error(msg: Option<&Expr>) -> Stmt {
|
||||
Stmt::new(
|
||||
@@ -47,7 +47,8 @@ pub fn assert_false(checker: &mut Checker, stmt: &Stmt, test: &Expr, msg: Option
|
||||
|
||||
let mut check = Check::new(CheckKind::DoNotAssertFalse, Range::from_located(test));
|
||||
if checker.patch(check.kind.code()) {
|
||||
let mut generator = SourceGenerator::new();
|
||||
let mut generator =
|
||||
SourceCodeGenerator::new(checker.style.indentation(), checker.style.quote());
|
||||
generator.unparse_stmt(&assertion_error(msg));
|
||||
if let Ok(content) = generator.generate() {
|
||||
check.amend(Fix::replacement(
|
||||
|
||||
@@ -7,7 +7,7 @@ use crate::ast::types::Range;
|
||||
use crate::autofix::Fix;
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::checks::{Check, CheckCode, CheckKind};
|
||||
use crate::code_gen::SourceGenerator;
|
||||
use crate::source_code_generator::SourceCodeGenerator;
|
||||
|
||||
fn type_pattern(elts: Vec<&Expr>) -> Expr {
|
||||
Expr::new(
|
||||
@@ -54,7 +54,8 @@ fn duplicate_handler_exceptions<'a>(
|
||||
Range::from_located(expr),
|
||||
);
|
||||
if checker.patch(check.kind.code()) {
|
||||
let mut generator = SourceGenerator::new();
|
||||
let mut generator =
|
||||
SourceCodeGenerator::new(checker.style.indentation(), checker.style.quote());
|
||||
if unique_elts.len() == 1 {
|
||||
generator.unparse_expr(unique_elts[0], 0);
|
||||
} else {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use rustpython_ast::{ExprKind, Stmt, StmtKind};
|
||||
|
||||
use crate::ast::types::Range;
|
||||
use crate::ast::helpers;
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::checks::{Check, CheckKind};
|
||||
|
||||
@@ -17,6 +17,6 @@ pub fn f_string_docstring(checker: &mut Checker, body: &[Stmt]) {
|
||||
};
|
||||
checker.add_check(Check::new(
|
||||
CheckKind::FStringDocstring,
|
||||
Range::from_located(stmt),
|
||||
helpers::identifier_range(stmt, checker.locator),
|
||||
));
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@ use crate::ast::types::Range;
|
||||
use crate::autofix::Fix;
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::checks::{Check, CheckKind};
|
||||
use crate::code_gen::SourceGenerator;
|
||||
use crate::python::identifiers::IDENTIFIER_REGEX;
|
||||
use crate::python::keyword::KWLIST;
|
||||
use crate::source_code_generator::SourceCodeGenerator;
|
||||
|
||||
fn attribute(value: &Expr, attr: &str) -> Expr {
|
||||
Expr::new(
|
||||
@@ -46,7 +46,8 @@ pub fn getattr_with_constant(checker: &mut Checker, expr: &Expr, func: &Expr, ar
|
||||
|
||||
let mut check = Check::new(CheckKind::GetAttrWithConstant, Range::from_located(expr));
|
||||
if checker.patch(check.kind.code()) {
|
||||
let mut generator = SourceGenerator::new();
|
||||
let mut generator =
|
||||
SourceCodeGenerator::new(checker.style.indentation(), checker.style.quote());
|
||||
generator.unparse_expr(&attribute(obj, value), 0);
|
||||
if let Ok(content) = generator.generate() {
|
||||
check.amend(Fix::replacement(
|
||||
|
||||
@@ -4,7 +4,7 @@ use crate::ast::types::Range;
|
||||
use crate::autofix::Fix;
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::checks::{Check, CheckKind};
|
||||
use crate::code_gen::SourceGenerator;
|
||||
use crate::source_code_generator::SourceCodeGenerator;
|
||||
|
||||
/// B013
|
||||
pub fn redundant_tuple_in_exception_handler(checker: &mut Checker, handlers: &[Excepthandler]) {
|
||||
@@ -23,7 +23,8 @@ pub fn redundant_tuple_in_exception_handler(checker: &mut Checker, handlers: &[E
|
||||
Range::from_located(type_),
|
||||
);
|
||||
if checker.patch(check.kind.code()) {
|
||||
let mut generator = SourceGenerator::new();
|
||||
let mut generator =
|
||||
SourceCodeGenerator::new(checker.style.indentation(), checker.style.quote());
|
||||
generator.unparse_expr(elt, 0);
|
||||
if let Ok(content) = generator.generate() {
|
||||
check.amend(Fix::replacement(
|
||||
|
||||
@@ -6,11 +6,17 @@ use crate::ast::types::Range;
|
||||
use crate::autofix::Fix;
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::checks::{Check, CheckKind};
|
||||
use crate::code_gen::SourceGenerator;
|
||||
use crate::python::identifiers::IDENTIFIER_REGEX;
|
||||
use crate::python::keyword::KWLIST;
|
||||
use crate::source_code_generator::SourceCodeGenerator;
|
||||
use crate::source_code_style::SourceCodeStyleDetector;
|
||||
|
||||
fn assignment(obj: &Expr, name: &str, value: &Expr) -> Result<String> {
|
||||
fn assignment(
|
||||
obj: &Expr,
|
||||
name: &str,
|
||||
value: &Expr,
|
||||
stylist: &SourceCodeStyleDetector,
|
||||
) -> Result<String> {
|
||||
let stmt = Stmt::new(
|
||||
Location::default(),
|
||||
Location::default(),
|
||||
@@ -28,7 +34,7 @@ fn assignment(obj: &Expr, name: &str, value: &Expr) -> Result<String> {
|
||||
type_comment: None,
|
||||
},
|
||||
);
|
||||
let mut generator = SourceGenerator::new();
|
||||
let mut generator = SourceCodeGenerator::new(stylist.indentation(), stylist.quote());
|
||||
generator.unparse_stmt(&stmt);
|
||||
generator.generate().map_err(std::convert::Into::into)
|
||||
}
|
||||
@@ -63,7 +69,7 @@ pub fn setattr_with_constant(checker: &mut Checker, expr: &Expr, func: &Expr, ar
|
||||
if expr == child.as_ref() {
|
||||
let mut check = Check::new(CheckKind::SetAttrWithConstant, Range::from_located(expr));
|
||||
if checker.patch(check.kind.code()) {
|
||||
match assignment(obj, name, value) {
|
||||
match assignment(obj, name, value, checker.style) {
|
||||
Ok(content) => check.amend(Fix::replacement(
|
||||
content,
|
||||
expr.location,
|
||||
|
||||
@@ -5,7 +5,7 @@ use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(
|
||||
Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions, JsonSchema,
|
||||
Debug, PartialEq, Eq, Default, Serialize, Deserialize, ConfigurationOptions, JsonSchema,
|
||||
)]
|
||||
#[serde(
|
||||
deny_unknown_fields,
|
||||
@@ -26,15 +26,23 @@ pub struct Options {
|
||||
pub extend_immutable_calls: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Hash, Default)]
|
||||
#[derive(Debug, Default, Hash)]
|
||||
pub struct Settings {
|
||||
pub extend_immutable_calls: Vec<String>,
|
||||
}
|
||||
|
||||
impl Settings {
|
||||
pub fn from_options(options: Options) -> Self {
|
||||
impl From<Options> for Settings {
|
||||
fn from(options: Options) -> Self {
|
||||
Self {
|
||||
extend_immutable_calls: options.extend_immutable_calls.unwrap_or_default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Settings> for Options {
|
||||
fn from(settings: Settings) -> Self {
|
||||
Self {
|
||||
extend_immutable_calls: Some(settings.extend_immutable_calls),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ expression: checks
|
||||
row: 10
|
||||
column: 12
|
||||
fix:
|
||||
content: "raise AssertionError('message')"
|
||||
content: "raise AssertionError(\"message\")"
|
||||
location:
|
||||
row: 10
|
||||
column: 0
|
||||
|
||||
@@ -27,11 +27,18 @@ pub struct Settings {
|
||||
pub max_string_length: usize,
|
||||
}
|
||||
|
||||
impl Settings {
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
pub fn from_options(options: Options) -> Self {
|
||||
impl From<Options> for Settings {
|
||||
fn from(options: Options) -> Self {
|
||||
Self {
|
||||
max_string_length: options.max_string_length.unwrap_or_default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Settings> for Options {
|
||||
fn from(settings: Settings) -> Self {
|
||||
Self {
|
||||
max_string_length: Some(settings.max_string_length),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user